aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorSugandha Gupta <sugandha.gupta@ettus.com>2019-01-25 17:36:26 -0800
committermichael-west <michael.west@ettus.com>2019-05-21 17:20:42 -0700
commit2960e559515348dce83bfdbdd6ef39e551235045 (patch)
tree1a603f4c28f23c5bccd298b9be57b92a5991defc /host
parent41f732a4c8bb9df116a01958f0914708475097df (diff)
downloaduhd-2960e559515348dce83bfdbdd6ef39e551235045.tar.gz
uhd-2960e559515348dce83bfdbdd6ef39e551235045.tar.bz2
uhd-2960e559515348dce83bfdbdd6ef39e551235045.zip
device3: Constraint send/recv_frame_size based on down/upstream MTU
We need to properly contraint the send/recv_frame_size based on the minimum MTU of all the down/upstream blocks. This fixes the issue with E310 tx/rx streaming as it has smaller MTU sizes than the other usrps.
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/rfnoc/sink_block_ctrl_base.hpp12
-rw-r--r--host/include/uhd/rfnoc/source_block_ctrl_base.hpp12
-rw-r--r--host/lib/rfnoc/block_ctrl_base.cpp8
-rw-r--r--host/lib/rfnoc/sink_block_ctrl_base.cpp14
-rw-r--r--host/lib/rfnoc/source_block_ctrl_base.cpp10
-rw-r--r--host/lib/usrp/device3/device3_impl.hpp3
-rw-r--r--host/lib/usrp/device3/device3_io_impl.cpp54
-rw-r--r--host/lib/usrp/e300/e300_impl.cpp5
-rw-r--r--host/lib/usrp/e300/e300_impl.hpp3
-rw-r--r--host/lib/usrp/mpmd/mpmd_impl.cpp4
-rw-r--r--host/lib/usrp/mpmd/mpmd_impl.hpp3
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp7
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp3
13 files changed, 132 insertions, 6 deletions
diff --git a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp
index a2d4685be..5267612e6 100644
--- a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp
+++ b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp
@@ -63,6 +63,18 @@ public:
*/
size_t get_fifo_size(size_t block_port = 0) const;
+ /*! Return the MTU size on a given block port.
+ *
+ * This is necessary for setting up transports, among other things.
+ *
+ * If the block port is not defined, it will return 0, and not throw.
+ *
+ * \param block_port The block port (0 through 15).
+ *
+ * Returns the MTU in bytes.
+ */
+ size_t get_mtu(size_t block_port = 0) const;
+
/*! Configure flow control for incoming streams.
*
* If flow control is enabled for incoming streams, this block will periodically
diff --git a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp
index a22a19da9..e79b7ef69 100644
--- a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp
+++ b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp
@@ -118,6 +118,18 @@ public:
const size_t block_port = 0,
const uhd::sid_t& sid = uhd::sid_t());
+ /*! Return the MTU size on a given block port.
+ *
+ * This is necessary for setting up transports, among other things.
+ *
+ * If the block port is not defined, it will return 0, and not throw.
+ *
+ * \param block_port The block port (0 through 15).
+ *
+ * Returns the MTU in bytes.
+ */
+ size_t get_mtu(size_t block_port = 0) const;
+
protected:
/***********************************************************************
diff --git a/host/lib/rfnoc/block_ctrl_base.cpp b/host/lib/rfnoc/block_ctrl_base.cpp
index ed8068b5b..e70267b96 100644
--- a/host/lib/rfnoc/block_ctrl_base.cpp
+++ b/host/lib/rfnoc/block_ctrl_base.cpp
@@ -94,12 +94,16 @@ block_ctrl_base::block_ctrl_base(const make_args_t& make_args)
// Set source addresses:
sr_write(SR_BLOCK_SID, get_address(ctrl_port), ctrl_port);
// Set sink buffer sizes:
- settingsbus_reg_t reg = SR_READBACK_REG_FIFOSIZE;
- size_t buf_size_bytes = size_t(sr_read64(reg, ctrl_port));
+ settingsbus_reg_t reg_fifo = SR_READBACK_REG_FIFOSIZE;
+ size_t buf_size_bytes = size_t(sr_read64(reg_fifo, ctrl_port));
if (buf_size_bytes > 0)
n_valid_input_buffers++;
_tree->create<size_t>(_root_path / "input_buffer_size" / ctrl_port)
.set(buf_size_bytes);
+ // Set MTU size and convert to bytes:
+ settingsbus_reg_t reg_mtu = SR_READBACK_REG_MTU;
+ size_t mtu = 8 * (1 << size_t(sr_read64(reg_mtu, ctrl_port)));
+ _tree->create<size_t>(_root_path / "mtu" / ctrl_port).set(mtu);
// Set default destination SIDs
// Otherwise, the default is someone else's SID, which we don't want
sr_write(SR_RESP_IN_DST_SID, 0xFFFF, ctrl_port);
diff --git a/host/lib/rfnoc/sink_block_ctrl_base.cpp b/host/lib/rfnoc/sink_block_ctrl_base.cpp
index bb81706f9..f1d65350a 100644
--- a/host/lib/rfnoc/sink_block_ctrl_base.cpp
+++ b/host/lib/rfnoc/sink_block_ctrl_base.cpp
@@ -43,11 +43,19 @@ std::vector<size_t> sink_block_ctrl_base::get_input_ports() const
**********************************************************************/
size_t sink_block_ctrl_base::get_fifo_size(size_t block_port) const
{
- if (_tree->exists(
- _root_path / "input_buffer_size" / str(boost::format("%d") % block_port))) {
+ if (_tree->exists(_root_path / "input_buffer_size" / std::to_string(block_port))) {
return _tree
->access<size_t>(
- _root_path / "input_buffer_size" / str(boost::format("%d") % block_port))
+ _root_path / "input_buffer_size" / std::to_string(block_port))
+ .get();
+ }
+ return 0;
+}
+
+size_t sink_block_ctrl_base::get_mtu(size_t block_port) const
+{
+ if (_tree->exists(_root_path / "mtu" / std::to_string(block_port))) {
+ return _tree->access<size_t>(_root_path / "mtu" / std::to_string(block_port))
.get();
}
return 0;
diff --git a/host/lib/rfnoc/source_block_ctrl_base.cpp b/host/lib/rfnoc/source_block_ctrl_base.cpp
index 656ab26af..d06b6632d 100644
--- a/host/lib/rfnoc/source_block_ctrl_base.cpp
+++ b/host/lib/rfnoc/source_block_ctrl_base.cpp
@@ -143,6 +143,16 @@ void source_block_ctrl_base::configure_flow_control_out(const bool enable_fc_out
sr_write(SR_FLOW_CTRL_EN, config, block_port);
}
+size_t source_block_ctrl_base::get_mtu(size_t block_port) const
+{
+ if (_tree->exists(_root_path / "mtu" / std::to_string(block_port))) {
+ return _tree->access<size_t>(_root_path / "mtu" / std::to_string(block_port))
+ .get();
+ }
+ return 0;
+}
+
+
/***********************************************************************
* Hooks
**********************************************************************/
diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp
index 3bf6f6111..62fd399ac 100644
--- a/host/lib/usrp/device3/device3_impl.hpp
+++ b/host/lib/usrp/device3/device3_impl.hpp
@@ -206,6 +206,9 @@ protected:
//! Is called after a streamer is generated
virtual void post_streamer_hooks(uhd::direction_t) {}
+ //! get mtu
+ virtual size_t get_mtu(const size_t, const uhd::direction_t) = 0;
+
/***********************************************************************
* Channel-related
**********************************************************************/
diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp
index ce8ff2cbf..081f881d5 100644
--- a/host/lib/usrp/device3/device3_io_impl.cpp
+++ b/host/lib/usrp/device3/device3_io_impl.cpp
@@ -338,6 +338,33 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t& args_)
// Setup the DSP transport hints
device_addr_t rx_hints = get_rx_hints(mb_index);
+ // Traverse the upstream nodes for minimum mtu
+ size_t min_mtu = blk_ctrl->get_mtu(block_port);
+ UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " << blk_ctrl->unique_id()
+ << ": " << min_mtu;
+ std::vector<boost::shared_ptr<uhd::rfnoc::source_block_ctrl_base>>
+ upstream_source_nodes =
+ blk_ctrl->find_upstream_node<uhd::rfnoc::source_block_ctrl_base>();
+ for (const boost::shared_ptr<uhd::rfnoc::source_block_ctrl_base>& node :
+ upstream_source_nodes) {
+ // Get MTU from Port 0 of the upstream nodes. This is okay for now as
+ // currently we use port 0 of a block in case of channel 1.
+ UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " << node->unique_id()
+ << ": " << node->get_mtu(0);
+ min_mtu = std::min(min_mtu, node->get_mtu(0));
+ }
+ // Contraint min_mtu by device mtu
+ min_mtu = std::min(min_mtu, get_mtu(mb_index, uhd::direction_t::RX_DIRECTION));
+ if (rx_hints.has_key("recv_frame_size")) {
+ if (rx_hints.cast<size_t>("recv_frame_size", min_mtu) > min_mtu) {
+ UHD_RX_STREAMER_LOG() << "Requested recv_frame_size of " << rx_hints["recv_frame_size"]
+ << " exceeds the maximum possible on this stream. Using " << min_mtu;
+ }
+ min_mtu =
+ std::min(min_mtu, rx_hints.cast<size_t>("recv_frame_size", min_mtu));
+ }
+ rx_hints["recv_frame_size"] = std::to_string(min_mtu);
+
// allocate sid and create transport
uhd::sid_t stream_address = blk_ctrl->get_address(block_port);
UHD_RX_STREAMER_LOG() << "creating rx stream " << rx_hints.to_string();
@@ -577,6 +604,33 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t& args_)
// Setup the dsp transport hints
device_addr_t tx_hints = get_tx_hints(mb_index);
+
+ // Traverse the downstream nodes for minimum mtu
+ size_t min_mtu = blk_ctrl->get_mtu(block_port);
+ UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " << blk_ctrl->unique_id()
+ << ": " << min_mtu;
+ std::vector<boost::shared_ptr<uhd::rfnoc::sink_block_ctrl_base>>
+ downstream_sink_nodes =
+ blk_ctrl->find_downstream_node<uhd::rfnoc::sink_block_ctrl_base>();
+ for (const boost::shared_ptr<uhd::rfnoc::sink_block_ctrl_base>& node :
+ downstream_sink_nodes) {
+ // Get MTU from Port 0 of the downstream nodes. This is okay for now as
+ // currently we use port 0 of a block in case of channel 1.
+ UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " << node->unique_id()
+ << ": " << node->get_mtu(0);
+ min_mtu = std::min(min_mtu, node->get_mtu(0));
+ }
+ min_mtu = std::min(min_mtu, get_mtu(mb_index, uhd::direction_t::TX_DIRECTION));
+ if (tx_hints.has_key("send_frame_size")) {
+ if (tx_hints.cast<size_t>("send_frame_size", min_mtu) > min_mtu) {
+ UHD_TX_STREAMER_LOG() << "Requested send_frame_size of " << tx_hints["send_frame_size"]
+ << " exceeds the maximum possible on this stream. Using " << min_mtu;
+ }
+ min_mtu =
+ std::min(min_mtu, tx_hints.cast<size_t>("send_frame_size", min_mtu));
+ }
+ tx_hints["send_frame_size"] = std::to_string(min_mtu);
+
const size_t fifo_size = blk_ctrl->get_fifo_size(block_port);
// Allocate sid and create transport
uhd::sid_t stream_address = blk_ctrl->get_address(block_port);
diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp
index 59a8cec88..5a6376039 100644
--- a/host/lib/usrp/e300/e300_impl.cpp
+++ b/host/lib/usrp/e300/e300_impl.cpp
@@ -731,6 +731,11 @@ uhd::both_xports_t e300_impl::make_transport(
return xports;
}
+size_t e300_impl::get_mtu(const size_t /*mb_index*/, const uhd::direction_t dir) {
+ return (dir == RX_DIRECTION) ? _data_xport_params.recv_frame_size :
+ _data_xport_params.send_frame_size;
+}
+
void e300_impl::_update_clock_source(const std::string &source)
{
if (source != "internal") {
diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp
index 2e919cf9b..0a6f153eb 100644
--- a/host/lib/usrp/e300/e300_impl.hpp
+++ b/host/lib/usrp/e300/e300_impl.hpp
@@ -166,6 +166,9 @@ private: // methods
return uhd::ENDIANNESS_LITTLE;
};
+ //! get mtu
+ size_t get_mtu(const size_t, const uhd::direction_t);
+
/************************************************************************
* Helpers
***********************************************************************/
diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp
index b8ce6cabd..2f3584498 100644
--- a/host/lib/usrp/mpmd/mpmd_impl.cpp
+++ b/host/lib/usrp/mpmd/mpmd_impl.cpp
@@ -348,6 +348,10 @@ void mpmd_impl::setup_rpc_blocks(
}
}
+size_t mpmd_impl::get_mtu(const size_t mb_index, const uhd::direction_t dir) {
+ return _mb[mb_index]->get_mtu(dir);
+}
+
/*****************************************************************************
* Factory & Registry
****************************************************************************/
diff --git a/host/lib/usrp/mpmd/mpmd_impl.hpp b/host/lib/usrp/mpmd/mpmd_impl.hpp
index f74627afa..bdb6bd691 100644
--- a/host/lib/usrp/mpmd/mpmd_impl.hpp
+++ b/host/lib/usrp/mpmd/mpmd_impl.hpp
@@ -246,6 +246,9 @@ public:
uhd::usrp::device3_impl::xport_type_t,
const uhd::device_addr_t&);
+ //! get mtu
+ size_t get_mtu(const size_t, const uhd::direction_t);
+
private:
uhd::device_addr_t get_rx_hints(size_t mb_index);
uhd::device_addr_t get_tx_hints(size_t mb_index);
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 796d422ad..b9b4a06f9 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -1526,7 +1526,7 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address,
// Increasing number of recv frames here because ctrl_iface uses it
// to determine how many control packets can be in flight before it
// must wait for an ACK
- default_buff_args.num_recv_frames =
+ default_buff_args.num_recv_frames =
uhd::rfnoc::CMD_FIFO_SIZE / uhd::rfnoc::MAX_CMD_PKT_SIZE;
} else if (xport_type == TX_DATA) {
size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE
@@ -1993,6 +1993,11 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(
return frame_size;
}
+size_t x300_impl::get_mtu(const size_t /*mb_index*/, const uhd::direction_t dir) {
+ return (dir == RX_DIRECTION) ? _max_frame_sizes.recv_frame_size :
+ _max_frame_sizes.send_frame_size;
+}
+
/***********************************************************************
* compat checks
**********************************************************************/
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index c101b3032..8d50f9914 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -173,6 +173,9 @@ private:
const xport_type_t xport_type,
const uhd::device_addr_t& args);
+ //! get mtu
+ size_t get_mtu(const size_t, const uhd::direction_t);
+
struct frame_size_t
{
size_t recv_frame_size;