diff --git a/include/villas/fpga/dma.h b/include/villas/fpga/dma.h index f97965c93..1d3a215e1 100644 --- a/include/villas/fpga/dma.h +++ b/include/villas/fpga/dma.h @@ -64,6 +64,5 @@ int dma_simple_write_complete(struct ip *c, char **buf, size_t *len); int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len); int dma_init(struct ip *c); -int dma_init_rings(struct ip *c, struct dma_mem *bd); #endif /* _DMA_H_ */ \ No newline at end of file diff --git a/include/villas/fpga/intc.h b/include/villas/fpga/intc.h index 65784f081..da08afcd7 100644 --- a/include/villas/fpga/intc.h +++ b/include/villas/fpga/intc.h @@ -11,12 +11,28 @@ #include +enum intc_flags { + INTC_ENABLED = (1 << 0), + INTC_POLLING = (1 << 1) +}; + +struct intc { + int num_irqs; /**< Number of available MSI vectors */ + + int efds[32]; /**< Event FDs */ + int nos[32]; /**< Interrupt numbers from /proc/interrupts */ + + int flags[32]; /**< Mask of intc_flags */ +}; + int intc_init(struct ip *c); +void intc_destroy(struct ip *c); + int intc_enable(struct ip *c, uint32_t mask, int poll); int intc_disable(struct ip *c, uint32_t mask); -uint64_t intc_wait(struct ip *c, int irq, int poll); +uint64_t intc_wait(struct ip *c, int irq); #endif /* _INTC_H_ */ \ No newline at end of file diff --git a/include/villas/fpga/ip.h b/include/villas/fpga/ip.h index 3eb2d9fd4..a573709c1 100644 --- a/include/villas/fpga/ip.h +++ b/include/villas/fpga/ip.h @@ -17,6 +17,7 @@ #include "fpga/timer.h" #include "fpga/model.h" #include "fpga/dft.h" +#include "fpga/intc.h" #include "nodes/fpga.h" #define REGISTER_IP_TYPE(ip) \ @@ -44,6 +45,7 @@ struct ip_type { int (*parse)(struct ip *c); int (*init)(struct ip *c); + int (*reset)(struct ip *c); void (*dump)(struct ip *c); void (*destroy)(struct ip *c); }; @@ -64,14 +66,12 @@ struct ip { union { struct model model; - struct { - int size; - } bram; struct timer timer; struct fifo fifo; struct dma dma; struct sw sw; struct dft dft; + struct intc intc; }; struct fpga *card; @@ -94,6 +94,8 @@ void ip_destroy(struct ip *c); void ip_dump(struct ip *c); +int ip_reset(struct ip *c); + int ip_parse(struct ip *c, config_setting_t *cfg); #endif \ No newline at end of file diff --git a/include/villas/kernel/vfio.h b/include/villas/kernel/vfio.h index c116d523e..6286efa0d 100644 --- a/include/villas/kernel/vfio.h +++ b/include/villas/kernel/vfio.h @@ -12,14 +12,18 @@ #include #include +#include #include #include -#include +#include "list.h" #define VFIO_DEV(x) "/dev/vfio/" x +/* Forward declaration */ +struct dma_mem; + struct vfio_group { int fd; /**< VFIO group file descriptor */ int index; /**< Index of the IOMMU group as listed under /sys/kernel/iommu_groups/ */ @@ -38,11 +42,8 @@ struct vfio_dev { struct vfio_device_info info; struct vfio_irq_info *irqs; struct vfio_region_info *regions; - + void **mappings; - - int *msi_efds; /**< Array of assigned eventfs for MSI handling */ - int *msi_irqs; /**< Linux assigned IRQ number for MSI (see /proc/interrupts) */ struct pci_dev *pdev; /**< libpci handle of the device */ struct vfio_group *group; /**< The VFIO group this device belongs to */ @@ -53,6 +54,8 @@ struct vfio_container { int version; int extensions; + uint64_t iova_next; /**< Next free IOVA address */ + struct list groups; }; @@ -71,8 +74,11 @@ int vfio_pci_attach(struct vfio_dev *d, struct vfio_container *c, struct pci_dev /** Hot resets a VFIO-PCI device */ int vfio_pci_reset(struct vfio_dev *d); -/** Create a new eventfd and binds it to the MSI irqs of the device */ -int vfio_pci_msi_fd(struct vfio_dev *d, uint32_t mask); +int vfio_pci_msi_init(struct vfio_dev *d, int efds[32]); + +int vfio_pci_msi_deinit(struct vfio_dev *d, int efds[32]); + +int vfio_pci_msi_find(struct vfio_dev *d, int nos[32]); /** Enable memory accesses and bus mastering for PCI device */ int vfio_pci_enable(struct vfio_dev *d); @@ -95,8 +101,11 @@ void vfio_dump(struct vfio_container *c); /** Map a device memory region to the application address space (e.g. PCI BARs) */ void * vfio_map_region(struct vfio_dev *d, int idx); -/** Allocate a virtual memory region and map it for DMA access from the devices */ -void * vfio_map_dma(struct vfio_container *c, size_t size, size_t pgsize, uint64_t phyaddr); +/** Map VM to an IOVA, which is accessible by devices in the container */ +int vfio_map_dma(struct vfio_container *c, struct dma_mem *mem); + +/** Unmap DMA memory */ +int vfio_unmap_dma(struct vfio_container *c, struct dma_mem *mem); /** munmap() a region which has been mapped by vfio_map_region() */ int vfio_unmap_region(struct vfio_dev *d, int idx); diff --git a/include/villas/nodes/fpga.h b/include/villas/nodes/fpga.h index 3b7a88267..9424cca87 100644 --- a/include/villas/nodes/fpga.h +++ b/include/villas/nodes/fpga.h @@ -21,17 +21,11 @@ #include +#include "fpga/dma.h" #include "nodes/fpga.h" #include "node.h" #include "list.h" -#define BASEADDR_HOST 0x80000000 -#define FPGA_BAR 0 /**< The Base Address Register which is mmap()ed to the User Space */ - -#define virt_to_axi(virt, map) ((char *) ((char *) virt - map)) -#define virt_to_dma(virt, dma) ((char *) ((char *) virt - dma) + BASEADDR_HOST) -#define dma_to_virt(addr, dma) ((char *) ((char *) addr - BASEADDR_HOST) + dma) - struct fpga { struct pci_filter filter; /**< Filter for libpci with device id & slot */ struct vfio_dev vd; /**< VFIO device handle. */ @@ -41,7 +35,6 @@ struct fpga { struct list ips; /**< List of IP components on FPGA. */ char *map; /**< PCI BAR0 mapping for register access */ - char *dma; /**< DMA mapped memory */ size_t maplen; size_t dmalen; @@ -60,6 +53,8 @@ struct fpga_dm { int use_irqs; + struct dma_mem dma; + enum { FPGA_DM_DMA, FPGA_DM_FIFO diff --git a/lib/fpga/dma.c b/lib/fpga/dma.c index 9e63ae93c..cf6b5867b 100644 --- a/lib/fpga/dma.c +++ b/lib/fpga/dma.c @@ -85,14 +85,14 @@ int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len) if (ret) return ret; - ret = dma_read_complete(c, NULL, NULL); - if (ret) - return ret; - ret = dma_write_complete(c, NULL, NULL); if (ret) return ret; + ret = dma_read_complete(c, NULL, NULL); + if (ret) + return ret; + return 0; } @@ -100,6 +100,8 @@ int dma_write(struct ip *c, char *buf, size_t len) { XAxiDma *xdma = &c->dma.inst; + debug(25, "DMA write: dmac=%s buf=%p len=%#x", c->name, buf, len); + return xdma->HasSg ? dma_sg_write(c, buf, len) : dma_simple_write(c, buf, len); @@ -108,6 +110,8 @@ int dma_write(struct ip *c, char *buf, size_t len) int dma_read(struct ip *c, char *buf, size_t len) { XAxiDma *xdma = &c->dma.inst; + + debug(25, "DMA read: dmac=%s buf=%p len=%#x", c->name, buf, len); return xdma->HasSg ? dma_sg_read(c, buf, len) @@ -117,6 +121,8 @@ int dma_read(struct ip *c, char *buf, size_t len) int dma_read_complete(struct ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; + + debug(25, "DMA read complete: dmac=%s", c->name); return xdma->HasSg ? dma_sg_read_complete(c, buf, len) @@ -126,6 +132,8 @@ int dma_read_complete(struct ip *c, char **buf, size_t *len) int dma_write_complete(struct ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; + + debug(25, "DMA write complete: dmac=%s", c->name); return xdma->HasSg ? dma_sg_write_complete(c, buf, len) @@ -134,19 +142,19 @@ int dma_write_complete(struct ip *c, char **buf, size_t *len) int dma_sg_write(struct ip *c, char *buf, size_t len) { + int ret, bdcnt; + XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - XAxiDma_Bd *bd; + XAxiDma_Bd *bds, *bd; - int ret; - - buf = virt_to_dma(buf, c->card->dma); + uint32_t remaining, bdlen, bdbuf, cr; /* Checks */ if (!xdma->HasSg) return -1; - if ((len < 1) || (len > ring->MaxTransferLen)) + if (len < 1) return -2; if (!xdma->HasMm2S) @@ -158,47 +166,70 @@ int dma_sg_write(struct ip *c, char *buf, size_t len) return -4; } - ret = XAxiDma_BdRingAlloc(ring, 1, &bd); + bdcnt = CEIL(len, FPGA_DMA_BOUNDARY); + ret = XAxiDma_BdRingAlloc(ring, bdcnt, &bds); if (ret != XST_SUCCESS) return -5; - /* Set up the BD using the information of the packet to transmit */ - ret = XAxiDma_BdSetBufAddr(bd, (uintptr_t) buf); - if (ret != XST_SUCCESS) - return -6; + remaining = len; + bdbuf = (uint32_t) buf; + bd = bds; + for (int i = 0; i < bdcnt; i++) { + bdlen = MIN(remaining, FPGA_DMA_BOUNDARY); - ret = XAxiDma_BdSetLength(bd, len, ring->MaxTransferLen); - if (ret != XST_SUCCESS) - return -7; + ret = XAxiDma_BdSetBufAddr(bd, bdbuf); + if (ret != XST_SUCCESS) + goto out; - /* Set SOF / EOF / ID */ - XAxiDma_BdSetCtrl(bd, XAXIDMA_BD_CTRL_TXEOF_MASK | XAXIDMA_BD_CTRL_TXSOF_MASK); - XAxiDma_BdSetId(bd, (uintptr_t) buf); + ret = XAxiDma_BdSetLength(bd, bdlen, ring->MaxTransferLen); + if (ret != XST_SUCCESS) + goto out; + + /* Set SOF / EOF / ID */ + cr = 0; + if (i == 0) + cr |= XAXIDMA_BD_CTRL_TXSOF_MASK; + if (i == bdcnt - 1) + cr |= XAXIDMA_BD_CTRL_TXEOF_MASK; + + XAxiDma_BdSetCtrl(bd, cr); + XAxiDma_BdSetId(bd, (uintptr_t) buf); + + remaining -= bdlen; + bdbuf += bdlen; + bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd); + } /* Give the BD to DMA to kick off the transmission. */ - ret = XAxiDma_BdRingToHw(ring, 1, bd); + ret = XAxiDma_BdRingToHw(ring, bdcnt, bds); if (ret != XST_SUCCESS) return -8; return 0; + +out: + ret = XAxiDma_BdRingUnAlloc(ring, bdcnt, bds); + if (ret != XST_SUCCESS) + return -6; + + return -5; } int dma_sg_read(struct ip *c, char *buf, size_t len) { + int ret, bdcnt; + XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - XAxiDma_Bd *bd; - - int ret; - - buf = virt_to_dma(buf, c->card->dma); + XAxiDma_Bd *bds, *bd; + uint32_t remaining, bdlen, bdbuf; /* Checks */ if (!xdma->HasSg) return -1; - if ((len < 1) || (len > ring->MaxTransferLen)) + if (len < 1) return -2; if (!xdma->HasS2Mm) @@ -210,56 +241,74 @@ int dma_sg_read(struct ip *c, char *buf, size_t len) return -4; } - ret = XAxiDma_BdRingAlloc(ring, 1, &bd); + bdcnt = CEIL(len, FPGA_DMA_BOUNDARY); + ret = XAxiDma_BdRingAlloc(ring, bdcnt, &bds); if (ret != XST_SUCCESS) return -5; - ret = XAxiDma_BdSetBufAddr(bd, (uintptr_t) buf); - if (ret != XST_SUCCESS) - return -6; + bdbuf = (uint32_t) buf; + remaining = len; + bd = bds; + for (int i = 0; i < bdcnt; i++) { + bdlen = MIN(remaining, FPGA_DMA_BOUNDARY); + ret = XAxiDma_BdSetLength(bd, bdlen, ring->MaxTransferLen); + if (ret != XST_SUCCESS) + goto out; - ret = XAxiDma_BdSetLength(bd, len, ring->MaxTransferLen); - if (ret != XST_SUCCESS) - return -7; + ret = XAxiDma_BdSetBufAddr(bd, bdbuf); + if (ret != XST_SUCCESS) + goto out; - /* Receive BDs do not need to set anything for the control - * The hardware will set the SOF/EOF bits per stream ret */ - XAxiDma_BdSetCtrl(bd, 0); - XAxiDma_BdSetId(bd, (uintptr_t) buf); + /* Receive BDs do not need to set anything for the control + * The hardware will set the SOF/EOF bits per stream ret */ + XAxiDma_BdSetCtrl(bd, 0); + XAxiDma_BdSetId(bd, (uintptr_t) buf); - ret = XAxiDma_BdRingToHw(ring, 1, bd); + remaining -= bdlen; + bdbuf += bdlen; + bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd); + } + + ret = XAxiDma_BdRingToHw(ring, bdcnt, bds); if (ret != XST_SUCCESS) return -8; return 0; + +out: + ret = XAxiDma_BdRingUnAlloc(ring, bdcnt, bds); + if (ret != XST_SUCCESS) + return -6; + + return -5; } int dma_sg_write_complete(struct ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - XAxiDma_Bd *bd; + XAxiDma_Bd *bds; int processed, ret; /* Wait until the one BD TX transaction is done */ - while ((processed = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bd)) == 0) - pthread_testcancel(); + while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK)) + intc_wait(c->card->intc, c->irq); XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE); + processed = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bds); + if (len != NULL) - *len = XAxiDma_BdGetActualLength(bd, XAXIDMA_MAX_TRANSFER_LEN); + *len = XAxiDma_BdGetActualLength(bds, XAXIDMA_MAX_TRANSFER_LEN); if (buf != NULL) - *buf = (char *) (uintptr_t) XAxiDma_BdGetBufAddr(bd); + *buf = (char *) (uintptr_t) XAxiDma_BdGetId(bds); /* Free all processed TX BDs for future transmission */ - ret = XAxiDma_BdRingFree(ring, processed, bd); - if (ret != XST_SUCCESS) { - info("Failed to free %d tx BDs %d", processed, ret); + ret = XAxiDma_BdRingFree(ring, processed, bds); + if (ret != XST_SUCCESS) return -1; - } - + return 0; } @@ -267,25 +316,48 @@ int dma_sg_read_complete(struct ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - XAxiDma_Bd *bd; + XAxiDma_Bd *bds, *bd; - int ret; + int ret, bdcnt; + uint32_t recvlen, sr; + uintptr_t recvbuf; if (!xdma->HasSg) return -1; - while (XAxiDma_BdRingFromHw(ring, 1, &bd) == 0) - pthread_testcancel(); + while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK)) + intc_wait(c->card->intc, c->irq + 1); XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA); - if (len != NULL) - *len = XAxiDma_BdGetActualLength(bd, XAXIDMA_MAX_TRANSFER_LEN); + bdcnt = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bds); + + recvlen = 0; + + bd = bds; + for (int i = 0; i < bdcnt; i++) { + recvlen += XAxiDma_BdGetActualLength(bd, ring->MaxTransferLen); + + sr = XAxiDma_BdGetSts(bd); + if (sr & XAXIDMA_BD_STS_RXSOF_MASK) + if (i != 0) + warn("sof not first"); + + if (sr & XAXIDMA_BD_STS_RXEOF_MASK) + if (i != bdcnt - 1) + warn("eof not last"); + + recvbuf = XAxiDma_BdGetId(bd); + + bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd); + } + if (len != NULL) + *len = recvlen; if (buf != NULL) - *buf = (char *) (uintptr_t) XAxiDma_BdGetBufAddr(bd); + *buf = (char *) recvbuf; /* Free all processed RX BDs for future transmission */ - ret = XAxiDma_BdRingFree(ring, 1, bd); + ret = XAxiDma_BdRingFree(ring, bdcnt, bds); if (ret != XST_SUCCESS) return -3; @@ -297,13 +369,11 @@ int dma_simple_read(struct ip *c, char *buf, size_t len) XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - buf = virt_to_dma(buf, c->card->dma); - /* Checks */ if (xdma->HasSg) return -1; - if ((len < 1) || (len > ring->MaxTransferLen)) + if ((len < 1) || (len > FPGA_DMA_BOUNDARY)) return -2; if (!xdma->HasS2Mm) @@ -335,13 +405,11 @@ int dma_simple_write(struct ip *c, char *buf, size_t len) XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - buf = virt_to_dma(buf, c->card->dma); - /* Checks */ if (xdma->HasSg) return -1; - if ((len < 1) || (len > ring->MaxTransferLen)) + if ((len < 1) || (len > FPGA_DMA_BOUNDARY)) return -2; if (!xdma->HasMm2S) @@ -375,7 +443,7 @@ int dma_simple_read_complete(struct ip *c, char **buf, size_t *len) XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK)) - pthread_testcancel(); + intc_wait(c->card->intc, c->irq + 1); XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA); if (len) @@ -396,7 +464,7 @@ int dma_simple_write_complete(struct ip *c, char **buf, size_t *len) XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK)) - pthread_testcancel(); + intc_wait(c->card->intc, c->irq); XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE); if (len) @@ -428,53 +496,40 @@ static int dma_setup_ring(XAxiDma_BdRing *ring, struct dma_mem *bdbuf) /* Setup Rx BD space */ cnt = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT, bdbuf->len); - ret = XAxiDma_BdRingCreate(ring, bdbuf->base_phys, bdbuf->base_virt, XAXIDMA_BD_MINIMUM_ALIGNMENT, cnt); - if (ret != XST_SUCCESS) { - info("RX create BD ring failed (%d)", ret); - return XST_FAILURE; - } + ret = XAxiDma_BdRingCreate(ring, (uintptr_t) bdbuf->base_phys, (uintptr_t) bdbuf->base_virt, XAXIDMA_BD_MINIMUM_ALIGNMENT, cnt); + if (ret != XST_SUCCESS) + return -1; XAxiDma_BdClear(&clearbd); ret = XAxiDma_BdRingClone(ring, &clearbd); - if (ret != XST_SUCCESS) { - info("RX clone BD failed %d", ret); - return XST_FAILURE; - } - + if (ret != XST_SUCCESS) + return -2; + /* Start the channel */ ret = XAxiDma_BdRingStart(ring); - if (ret != XST_SUCCESS) { - info("failed start bdring txsetup %d", ret); - return XST_FAILURE; - } - + if (ret != XST_SUCCESS) + return -3; + return XST_SUCCESS; } -int dma_init_rings(struct ip *c, struct dma_mem *bd) +static int dma_init_rings(XAxiDma *xdma, struct dma_mem *bd) { int ret; - XAxiDma *xdma = &c->dma.inst; - /* Split BD memory equally between Rx and Tx rings */ - struct dma_mem bd_rx = { - .base_virt = bd->base_virt, - .base_phys = bd->base_phys, - .len = bd->len / 2 - }; - struct dma_mem bd_tx = { - .base_virt = bd->base_virt + bd_rx.len, - .base_phys = bd->base_phys + bd_rx.len, - .len = bd->len - bd_rx.len - }; + struct dma_mem bd_rx, bd_tx; + + ret = dma_mem_split(bd, &bd_rx, &bd_tx); + if (ret) + return -1; ret = dma_setup_ring(XAxiDma_GetRxRing(xdma), &bd_rx); if (ret != XST_SUCCESS) - return -1; + return -2; ret = dma_setup_ring(XAxiDma_GetTxRing(xdma), &bd_tx); if (ret != XST_SUCCESS) - return -1; + return -3; return 0; } @@ -482,7 +537,8 @@ int dma_init_rings(struct ip *c, struct dma_mem *bd) int dma_init(struct ip *c) { int ret, sg; - XAxiDma *xdma = &c->dma.inst; + struct dma *dma = &c->dma; + XAxiDma *xdma = &dma->inst; /* Guess DMA type */ sg = (XAxiDma_In32((uintptr_t) c->card->map + c->baseaddr + XAXIDMA_TX_OFFSET+ XAXIDMA_SR_OFFSET) & @@ -507,16 +563,23 @@ int dma_init(struct ip *c) }; ret = XAxiDma_CfgInitialize(xdma, &xdma_cfg); - if (ret != XST_SUCCESS) { - info("Initialization failed %d", ret); + if (ret != XST_SUCCESS) return -1; - } /* Perform selftest */ ret = XAxiDma_Selftest(xdma); - if (ret != XST_SUCCESS) { - info("DMA selftest failed"); - return -1; + if (ret != XST_SUCCESS) + return -2; + + /* Map buffer descriptors */ + if (xdma->HasSg) { + ret = dma_alloc(c, &dma->bd, FPGA_DMA_BD_SIZE, 0); + if (ret) + return -3; + + ret = dma_init_rings(xdma, &dma->bd); + if (ret) + return -4; } /* Enable completion interrupts for both channels */ @@ -526,9 +589,17 @@ int dma_init(struct ip *c) return 0; } +int dma_reset(struct ip *c) +{ + XAxiDma_Reset(&c->dma.inst); + + return 0; +} + static struct ip_type ip = { .vlnv = { "xilinx.com", "ip", "axi_dma", NULL }, - .init = dma_init + .init = dma_init, + .reset = dma_reset }; REGISTER_IP_TYPE(&ip) \ No newline at end of file diff --git a/lib/fpga/fifo.c b/lib/fpga/fifo.c index fcf2de659..af0df5ead 100644 --- a/lib/fpga/fifo.c +++ b/lib/fpga/fifo.c @@ -59,10 +59,10 @@ ssize_t fifo_read(struct ip *c, char *buf, size_t len) XLlFifo *fifo = &c->fifo.inst; size_t nextlen = 0; - uint32_t rdfo, rxlen; + uint32_t rxlen; - while (!(rdfo = XLlFifo_RxOccupancy(fifo))) - pthread_testcancel(); + while (!XLlFifo_IsRxDone(fifo)) + intc_wait(c->card->intc, c->irq); XLlFifo_IntClear(fifo, XLLF_INT_RC_MASK); /* Get length of next frame */ @@ -89,10 +89,18 @@ int fifo_parse(struct ip *c) return 0; } +int fifo_reset(struct ip *c) +{ + XLlFifo_Reset(&c->fifo.inst); + + return 0; +} + static struct ip_type ip = { .vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }, .init = fifo_init, - .parse = fifo_parse + .parse = fifo_parse, + .reset = fifo_reset }; REGISTER_IP_TYPE(&ip) \ No newline at end of file diff --git a/lib/fpga/ip.c b/lib/fpga/ip.c index 45ab456ec..9d4687a12 100644 --- a/lib/fpga/ip.c +++ b/lib/fpga/ip.c @@ -62,6 +62,13 @@ int ip_init(struct ip *c) return ret; } +int ip_reset(struct ip *c) +{ + debug(3, "Reset IP core: %s", c->name); + + return c->_vt && c->_vt->reset ? c->_vt->reset(c) : 0; +} + void ip_destroy(struct ip *c) { if (c->_vt && c->_vt->destroy)