diff --git a/src/WZDmaInputFilter.cc b/src/WZDmaInputFilter.cc index 930d937e78f6ac8f830784e3948576fa0190a4dc..1b0ed3c256e2804101b0aa383a87e465bdf49942 100644 --- a/src/WZDmaInputFilter.cc +++ b/src/WZDmaInputFilter.cc @@ -18,6 +18,7 @@ WZDmaInputFilter::WZDmaInputFilter(size_t packetBufferSize, sconeHost_{conf.getSconeHost()}, sconePort_{conf.getSconePort()}, sconeBoard_{conf.getSconeBoard()} { // Initialize the DMA subsystem + dma_is_initialized_ = false; if (wz_init(&dma_) < 0) { std::string msg = "Cannot initialize WZ DMA device"; if (errno == ENOENT) { @@ -27,6 +28,7 @@ WZDmaInputFilter::WZDmaInputFilter(size_t packetBufferSize, } throw std::system_error(errno, std::system_category(), msg); } + dma_is_initialized_ = true; // Start the DMA if (wz_start_dma(&dma_) < 0) { @@ -38,8 +40,11 @@ WZDmaInputFilter::WZDmaInputFilter(size_t packetBufferSize, } WZDmaInputFilter::~WZDmaInputFilter() { - wz_stop_dma(&dma_); - wz_close(&dma_); + if (dma_is_initialized_) { + wz_stop_dma(&dma_); + wz_close(&dma_); + dma_is_initialized_ = false; + } LOG(TRACE) << "Destroyed WZ DMA input filter"; } @@ -51,22 +56,26 @@ inline ssize_t WZDmaInputFilter::read_packet_from_dma(char **buffer) { bytes_read = wz_read_start(&dma_, buffer); if (bytes_read < 0) { + int errno_saved = errno; stats.nbDmaErrors++; - LOG(ERROR) << tools::strerror( - "#" + std::to_string(nbReads()) + - ": Read failed, returned: " + std::to_string(bytes_read)); + LOG(ERROR) << tools::strerror("#" + std::to_string(nbReads()) + + ": Read failed, returned: " + + std::to_string(bytes_read)) + << ", errno: " << errno_saved; - if (errno == EIO) { + if (errno_saved == EIO) { LOG(ERROR) << "#" << nbReads() << ": Trying to restart DMA (attempt #" << tries << "):"; wz_stop_dma(&dma_); wz_close(&dma_); + dma_is_initialized_ = false; // Initialize the DMA subsystem if (wz_init(&dma_) < 0) { throw std::system_error(errno, std::system_category(), "Cannot initialize WZ DMA device"); } + dma_is_initialized_ = true; if (wz_start_dma(&dma_) < 0) { throw std::system_error(errno, std::system_category(), @@ -81,7 +90,7 @@ inline ssize_t WZDmaInputFilter::read_packet_from_dma(char **buffer) { } continue; } - throw std::system_error(errno, std::system_category(), + throw std::system_error(errno_saved, std::system_category(), "FATAL: Unrecoverable DMA error detected."); } break; diff --git a/src/WZDmaInputFilter.h b/src/WZDmaInputFilter.h index c80cbf6f870b59712397533b6494a30b8eaa85fd..e8a4e8846df275c6738cfecf13784b6f864ab900 100644 --- a/src/WZDmaInputFilter.h +++ b/src/WZDmaInputFilter.h @@ -33,6 +33,7 @@ private: } stats; struct wz_private dma_; + bool dma_is_initialized_; std::string sconeHost_; std::string sconePort_; diff --git a/src/wz_dma.c b/src/wz_dma.c index 267a6c7d7d7032ae39886a42cfaf53841b024996..6a3bb685803a6412e12ecca4f49f49397146569b 100644 --- a/src/wz_dma.c +++ b/src/wz_dma.c @@ -23,40 +23,52 @@ int wz_init(struct wz_private* wz) wz->fd_user = -1; wz->fd_control = -1; wz->fd_memory = -1; + wz->fd_memory_is_allocated = 0; wz->usr_regs = NULL; wz->data_buf = NULL; //int err = 0; if ( (wz->fd_user = open("/dev/wz-xdma0_user", O_RDWR)) < 0 ) { + wz->fd_user = -1; PERROR("Can't open /dev/wz-xdma0_user"); return -1; }; if ( (wz->fd_control = open("/dev/wz-xdma0_control", O_RDWR)) < 0 ) { + wz->fd_control = -1; PERROR("Can't open /dev/wz-xdma0_control"); + wz_close(wz); return -1; }; if ( (wz->fd_memory = open("/dev/wz-xdma0_c2h_0", O_RDWR)) < 0 ) { + wz->fd_memory = -1; PERROR("Can't open /dev/wz-xdma0_c2h_0"); + wz_close(wz); return -1; }; //Allocate buffers if ( (res = ioctl(wz->fd_memory, IOCTL_XDMA_WZ_ALLOC_BUFFERS, 0L)) < 0 ) { PERROR("Can't mmap DMA buffers"); + wz_close(wz); return -1; } + wz->fd_memory_is_allocated = 1; //Now mmap the user registers if ( (wz->usr_regs = (volatile uint32_t *) mmap(NULL, 1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, wz->fd_user, 0)) == MAP_FAILED) { + wz->usr_regs = NULL; PERROR("Can't mmap user registers"); + wz_close(wz); return -1; } if ( (wz->data_buf = (volatile char *) mmap(NULL, TOT_BUF_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, wz->fd_memory, 0)) == MAP_FAILED) { + wz->data_buf = NULL; PERROR("Can't mmap data buffer"); + wz_close(wz); return -1; } @@ -75,12 +87,32 @@ int wz_init(struct wz_private* wz) /* The opposite of wz_init */ int wz_close(struct wz_private* wz) { - munmap((void *)wz->data_buf, TOT_BUF_LEN); - munmap((void *)wz->usr_regs, 1024*1024); - ioctl(wz->fd_memory, IOCTL_XDMA_WZ_FREE_BUFFERS, 0L); - close(wz->fd_memory); - close(wz->fd_control); - close(wz->fd_user); + if (wz->data_buf) { + munmap((void *)wz->data_buf, TOT_BUF_LEN); + } + if (wz->usr_regs) { + munmap((void *)wz->usr_regs, 1024*1024); + } + if (wz->fd_memory_is_allocated) { + ioctl(wz->fd_memory, IOCTL_XDMA_WZ_FREE_BUFFERS, 0L); + } + if (wz->fd_memory != -1) { + close(wz->fd_memory); + } + if (wz->fd_control != -1) { + close(wz->fd_control); + } + if (wz->fd_user != -1) { + close(wz->fd_user); + } + + wz->fd_user = -1; + wz->fd_control = -1; + wz->fd_memory = -1; + wz->fd_memory_is_allocated = 0; + wz->usr_regs = NULL; + wz->data_buf = NULL; + return 0; } diff --git a/src/wz_dma.h b/src/wz_dma.h index d32563c67f8920662a7a900b396a43f8dd5653b4..e84ddc1d9367fb3dcea2d28e5b2ebf1dbad1e659 100644 --- a/src/wz_dma.h +++ b/src/wz_dma.h @@ -11,6 +11,7 @@ struct wz_private { int fd_user; int fd_control; int fd_memory; + int fd_memory_is_allocated; volatile uint32_t *usr_regs; volatile char *data_buf; };