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/niriok_proxy.cpp | 10 +++++ host/lib/transport/nirio/niusrprio_session.cpp | 58 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) (limited to 'host/lib/transport/nirio') diff --git a/host/lib/transport/nirio/niriok_proxy.cpp b/host/lib/transport/nirio/niriok_proxy.cpp index 031623c9a..ac8faf0a4 100644 --- a/host/lib/transport/nirio/niriok_proxy.cpp +++ b/host/lib/transport/nirio/niriok_proxy.cpp @@ -293,6 +293,16 @@ namespace uhd { namespace niusrprio { return nirio_driver_iface::rio_munmap(map); } + + nirio_status niriok_proxy::stop_all_fifos() + { + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO_STOP_ALL; + + return sync_operation(&in, sizeof(in), &out, sizeof(out)); + } }} #ifdef __GNUC__ diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index a07bc4fdf..dd9cc2f8b 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -77,6 +77,8 @@ nirio_status niusrprio_session::open( std::string lvbitx_checksum(_lvbitx->get_bitstream_checksum()); boost::uint16_t download_fpga = (force_download || (_read_bitstream_checksum() != lvbitx_checksum)) ? 1 : 0; + nirio_status_chain(_ensure_fpga_ready(), status); + nirio_status_chain(_rpc_client.niusrprio_open_session( _resource_name, bitfile_path, signature, download_fpga), status); _session_open = nirio_status_not_fatal(status); @@ -93,6 +95,7 @@ nirio_status niusrprio_session::open( } } + nirio_status_chain(_riok_proxy.set_attribute(ADDRESS_SPACE, BUS_INTERFACE), status); return status; } @@ -196,4 +199,59 @@ nirio_status niusrprio_session::_write_bitstream_checksum(const std::string& che return status; } +nirio_status niusrprio_session::_ensure_fpga_ready() +{ + nirio_status status = NiRio_Status_Success; + niriok_scoped_addr_space(_riok_proxy, BUS_INTERFACE, status); + + //Verify that the Ettus FPGA loaded in the device. This may not be true if the + //user is switching to UHD after using LabVIEW FPGA. In that case skip this check. + boost::uint32_t pcie_fpga_signature = 0; + nirio_status_chain(_riok_proxy.peek(FPGA_PCIE_SIG_REG, pcie_fpga_signature), status); + //@TODO: Remove X300 specific constants for future products + if (pcie_fpga_signature != FPGA_X3xx_SIG_VALUE) { + return status; + } + + 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) + { + //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 + //the DMA FIFOs. We currently don't have any feedback from the driver regarding + //this state so just wait. + boost::this_thread::sleep(boost::posix_time::milliseconds(FPGA_READY_TIMEOUT_IN_MS)); + + //Disable all FIFOs in the FPGA + for (size_t i = 0; i < _lvbitx->get_input_fifo_count(); i++) { + _riok_proxy.poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, i), DMA_CTRL_DISABLED); + } + for (size_t i = 0; i < _lvbitx->get_output_fifo_count(); i++) { + _riok_proxy.poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, i), DMA_CTRL_DISABLED); + } + + //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); + + 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; + } + + return status; +} + }} -- 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') 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 e85062880b02db9527f6aa0a86299c7bc95a731d Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Fri, 25 Apr 2014 09:52:23 -0700 Subject: x300: Addressed review feedback - Fixed synchronization for unclaim - Removed stray RIO addr space set --- host/lib/transport/nirio/niusrprio_session.cpp | 1 - host/lib/usrp/x300/x300_impl.cpp | 24 +++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'host/lib/transport/nirio') diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp index 094009ae9..3afe61eae 100644 --- a/host/lib/transport/nirio/niusrprio_session.cpp +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -95,7 +95,6 @@ nirio_status niusrprio_session::open( } } - nirio_status_chain(_riok_proxy.set_attribute(ADDRESS_SPACE, BUS_INTERFACE), status); return status; } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 7cb5d9ad8..e931b7983 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -859,13 +859,14 @@ x300_impl::~x300_impl(void) //kill the claimer task and unclaim the device mb.claimer_task.reset(); - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0); - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0); - - boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); - //If the process is killed, the entire registry will disappear so we - //don't need to worry about unclean shutdowns here. - get_pcie_zpu_iface_registry().pop(mb.addr); + { //Critical section + boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); + mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0); + mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0); + //If the process is killed, the entire registry will disappear so we + //don't need to worry about unclean shutdowns here. + get_pcie_zpu_iface_registry().pop(mb.addr); + } } } catch(...) @@ -1491,10 +1492,11 @@ void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const std::string &attr, c void x300_impl::claimer_loop(wb_iface::sptr iface) { - boost::mutex::scoped_lock(claimer_mutex); - - iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL)); - iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); + { //Critical section + boost::mutex::scoped_lock(claimer_mutex); + iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL)); + iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); + } boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); //1 second } -- 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') 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