From 4b4e493f976094115dad7809121a092e2ac31668 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 24 Apr 2014 12:40:58 -0700 Subject: x300: Added hardware flush mechanism to PCIe logic. - Added DMA enabled states to DMA logic to allow for hardware data flushing during init. - niusrprio_session will now check for FPGA busy before downloading --- host/lib/transport/nirio_zero_copy.cpp | 58 ++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'host/lib/transport/nirio_zero_copy.cpp') diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp index c3c8a9368..87739b9c6 100644 --- a/host/lib/transport/nirio_zero_copy.cpp +++ b/host/lib/transport/nirio_zero_copy.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include //sleep #include #include // std::max @@ -143,6 +144,12 @@ public: nirio_status status = 0; size_t actual_depth = 0, actual_size = 0; + //Disable DMA streams in case last shutdown was unclean (cleanup, so don't status chain) + _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED); + _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED); + + _wait_until_stream_ready(); + //Configure frame width nirio_status_chain( _proxy().poke(PCIE_TX_DMA_REG(DMA_FRAME_SIZE_REG, _fifo_instance), @@ -152,14 +159,14 @@ public: _proxy().poke(PCIE_RX_DMA_REG(DMA_FRAME_SIZE_REG, _fifo_instance), static_cast(_xport_params.recv_frame_size/sizeof(fifo_data_t))), status); - //Config 32-bit word flipping and Reset DMA streams + //Config 32-bit word flipping and enable DMA streams nirio_status_chain( _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), - DMA_CTRL_SW_BUF_U32 | DMA_CTRL_RESET), + DMA_CTRL_SW_BUF_U32 | DMA_CTRL_ENABLED), status); nirio_status_chain( _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), - DMA_CTRL_SW_BUF_U32 | DMA_CTRL_RESET), + DMA_CTRL_SW_BUF_U32 | DMA_CTRL_ENABLED), status); //Create FIFOs @@ -189,10 +196,6 @@ public: nirio_status_chain(_send_fifo->start(), status); if (nirio_status_not_fatal(status)) { - //Flush RX kernel buffers in case some cruft was - //left behind from the last run - _flush_rx_buff(); - //allocate re-usable managed receive buffers for (size_t i = 0; i < get_num_recv_frames(); i++){ _mrb_pool.push_back(boost::shared_ptr(new nirio_zero_copy_mrb( @@ -216,9 +219,9 @@ public: { _proxy().get_rio_quirks().remove_tx_fifo(_fifo_instance); - //Reset DMA streams (Teardown, so don't status chain) - _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_RESET); - _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_RESET); + //Disable DMA streams (cleanup, so don't status chain) + _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED); + _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED); _flush_rx_buff(); @@ -284,6 +287,41 @@ private: } } + UHD_INLINE void _wait_until_stream_ready() + { + static const uint32_t TIMEOUT_IN_MS = 100; + + uint32_t reg_data = 0xffffffff; + boost::posix_time::ptime start_time; + boost::posix_time::time_duration elapsed; + nirio_status status = NiRio_Status_Success; + + start_time = boost::posix_time::microsec_clock::local_time(); + do { + boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus + elapsed = boost::posix_time::microsec_clock::local_time() - start_time; + nirio_status_chain(_proxy().peek( + PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); + } while ( + nirio_status_not_fatal(status) && + (reg_data & DMA_STATUS_BUSY) && + elapsed.total_milliseconds() < TIMEOUT_IN_MS); + + start_time = boost::posix_time::microsec_clock::local_time(); + do { + boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus + elapsed = boost::posix_time::microsec_clock::local_time() - start_time; + nirio_status_chain(_proxy().peek( + PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); + } while ( + nirio_status_not_fatal(status) && + (reg_data & DMA_STATUS_BUSY) && + elapsed.total_milliseconds() < TIMEOUT_IN_MS); + + nirio_status_to_exception(status, + "Could not create nirio_zero_copy transport because the FPGA is busy. Try re-downloading the LVBITX."); + } + //memory management -> buffers and fifos niusrprio::niusrprio_session::sptr _fpga_session; uint32_t _fifo_instance; -- cgit v1.2.3 From 8e5fe11b6015c3456261d7b7b2ef6918fefa1ee8 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 24 Apr 2014 13:01:37 -0700 Subject: x300: Cleanup for PCIe flushing --- host/lib/transport/nirio/niusrprio_session.cpp | 28 ++++++------- host/lib/transport/nirio_zero_copy.cpp | 54 ++++++++++++++------------ 2 files changed, 44 insertions(+), 38 deletions(-) (limited to 'host/lib/transport/nirio_zero_copy.cpp') diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index dd9cc2f8b..094009ae9 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -233,22 +233,22 @@ nirio_status niusrprio_session::_ensure_fpga_ready() //Disable all FIFOs in the kernel driver _riok_proxy.stop_all_fifos(); - } - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); - boost::posix_time::time_duration elapsed; - do { - boost::this_thread::sleep(boost::posix_time::microsec(1000)); //Avoid flooding the bus - elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status); - } while ( - nirio_status_not_fatal(status) && - (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK) && - elapsed.total_milliseconds() < FPGA_READY_TIMEOUT_IN_MS); + boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::time_duration elapsed; + do { + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //Avoid flooding the bus + elapsed = boost::posix_time::microsec_clock::local_time() - start_time; + nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status); + } while ( + nirio_status_not_fatal(status) && + (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK) && + elapsed.total_milliseconds() < FPGA_READY_TIMEOUT_IN_MS); - nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status); - if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK)) { - return NiRio_Status_FpgaBusy; + nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status); + if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK)) { + return NiRio_Status_FifoReserved; + } } return status; diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp index 87739b9c6..a739c01f1 100644 --- a/host/lib/transport/nirio_zero_copy.cpp +++ b/host/lib/transport/nirio_zero_copy.cpp @@ -292,34 +292,40 @@ private: static const uint32_t TIMEOUT_IN_MS = 100; uint32_t reg_data = 0xffffffff; + bool tx_busy = true, rx_busy = true; boost::posix_time::ptime start_time; boost::posix_time::time_duration elapsed; nirio_status status = NiRio_Status_Success; - start_time = boost::posix_time::microsec_clock::local_time(); - do { - boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus - elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_proxy().peek( - PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); - } while ( - nirio_status_not_fatal(status) && - (reg_data & DMA_STATUS_BUSY) && - elapsed.total_milliseconds() < TIMEOUT_IN_MS); - - start_time = boost::posix_time::microsec_clock::local_time(); - do { - boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus - elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_proxy().peek( - PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); - } while ( - nirio_status_not_fatal(status) && - (reg_data & DMA_STATUS_BUSY) && - elapsed.total_milliseconds() < TIMEOUT_IN_MS); - - nirio_status_to_exception(status, - "Could not create nirio_zero_copy transport because the FPGA is busy. Try re-downloading the LVBITX."); + nirio_status_chain(_proxy().peek( + PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); + tx_busy = (reg_data & DMA_STATUS_BUSY); + nirio_status_chain(_proxy().peek( + PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); + rx_busy = (reg_data & DMA_STATUS_BUSY); + + if (nirio_status_not_fatal(status) && !tx_busy && !rx_busy) { + start_time = boost::posix_time::microsec_clock::local_time(); + do { + boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus + elapsed = boost::posix_time::microsec_clock::local_time() - start_time; + nirio_status_chain(_proxy().peek( + PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); + tx_busy = (reg_data & DMA_STATUS_BUSY); + nirio_status_chain(_proxy().peek( + PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); + rx_busy = (reg_data & DMA_STATUS_BUSY); + } while ( + nirio_status_not_fatal(status) && + (tx_busy || rx_busy) && + elapsed.total_milliseconds() < TIMEOUT_IN_MS); + + if (tx_busy || rx_busy) { + nirio_status_chain(NiRio_Status_FpgaBusy, status); + } + + nirio_status_to_exception(status, "Could not create nirio_zero_copy transport."); + } } //memory management -> buffers and fifos -- cgit v1.2.3 From 7fad62620d75a56f35fb12d3a74ca5b157e01514 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Mon, 28 Apr 2014 15:22:47 -0700 Subject: x300: Fixed DMA busy logic after review feedback. --- host/lib/transport/nirio/niusrprio_session.cpp | 2 +- host/lib/transport/nirio_zero_copy.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/transport/nirio_zero_copy.cpp') diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index 3afe61eae..97d764736 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -214,7 +214,7 @@ nirio_status niusrprio_session::_ensure_fpga_ready() boost::uint32_t reg_data = 0xffffffff; nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status); - if (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK) + if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK)) { //In case this session was re-initialized *immediately* after the previous //there is a small chance that the server is still finishing up cleaning up diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp index a739c01f1..3bb822720 100644 --- a/host/lib/transport/nirio_zero_copy.cpp +++ b/host/lib/transport/nirio_zero_copy.cpp @@ -304,7 +304,7 @@ private: PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status); rx_busy = (reg_data & DMA_STATUS_BUSY); - if (nirio_status_not_fatal(status) && !tx_busy && !rx_busy) { + if (nirio_status_not_fatal(status) && (tx_busy || rx_busy)) { start_time = boost::posix_time::microsec_clock::local_time(); do { boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus -- cgit v1.2.3