@@ -93,6 +93,7 @@ Features
- Sub-Function representors.
- Sub-Function.
- Rx queue LWM (Limit WaterMark) configuration.
+- Host shaper support.
Limitations
@@ -511,6 +512,12 @@ Limitations
- LWM:
- Doesn't support shared Rx queue and Hairpin Rx queue.
+- Host shaper:
+
+ - Support BlueField series NIC from BlueField 2.
+ - When configure host shaper with MLX5_HOST_SHAPER_FLAG_LWM_TRIGGERED flag set,
+ only rate 0 and 100Mbps are supported.
+
Statistics
----------
@@ -192,6 +192,7 @@ New Features
Updated the Mellanox mlx5 driver with new features and improvements, including:
* Added Rx queue LWM(Limit WaterMark) support.
+ * Added host shaper support.
* **Updated Marvell cnxk crypto PMD.**
@@ -16,8 +16,9 @@ if dlopen_ibverbs
]
endif
-libnames = [ 'mlx5', 'ibverbs' ]
+libnames = [ 'mlx5', 'ibverbs', 'mtcr_ul' ]
libs = []
+libmtcr_ul_found = false
foreach libname:libnames
lib = dependency('lib' + libname, static:static_ibverbs, required:false, method: 'pkg-config')
if not lib.found() and not static_ibverbs
@@ -28,10 +29,16 @@ foreach libname:libnames
if not static_ibverbs and not dlopen_ibverbs
ext_deps += lib
endif
+ if libname == 'mtcr_ul'
+ libmtcr_ul_found = true
+ ext_deps += lib
+ endif
else
- build = false
- reason = 'missing dependency, "' + libname + '"'
- subdir_done()
+ if libname != 'mtcr_ul'
+ build = false
+ reason = 'missing dependency, "' + libname + '"'
+ subdir_done()
+ endif
endif
endforeach
if static_ibverbs or dlopen_ibverbs
@@ -205,6 +212,12 @@ has_sym_args = [
[ 'HAVE_MLX5_IBV_IMPORT_CTX_PD_AND_MR', 'infiniband/verbs.h',
'ibv_import_device' ],
]
+if libmtcr_ul_found
+ has_sym_args += [
+ [ 'HAVE_MLX5_MSTFLINT', 'mstflint/mtcr.h',
+ 'mopen'],
+ ]
+endif
config = configuration_data()
foreach arg:has_sym_args
config.set(arg[0], cc.has_header_symbol(arg[1], arg[2], dependencies: libs))
@@ -3768,6 +3768,7 @@ enum {
MLX5_CRYPTO_COMMISSIONING_REGISTER_ID = 0xC003,
MLX5_IMPORT_KEK_HANDLE_REGISTER_ID = 0xC004,
MLX5_CREDENTIAL_HANDLE_REGISTER_ID = 0xC005,
+ MLX5_QSHR_REGISTER_ID = 0x4030,
};
struct mlx5_ifc_register_mtutc_bits {
@@ -3782,6 +3783,30 @@ struct mlx5_ifc_register_mtutc_bits {
u8 time_adjustment[0x20];
};
+struct mlx5_ifc_ets_global_config_register_bits {
+ u8 reserved_at_0[0x2];
+ u8 rate_limit_update[0x1];
+ u8 reserved_at_3[0x29];
+ u8 max_bw_units[0x4];
+ u8 reserved_at_48[0x8];
+ u8 max_bw_value[0x8];
+};
+
+#define ETS_GLOBAL_CONFIG_BW_UNIT_DISABLED 0x0
+#define ETS_GLOBAL_CONFIG_BW_UNIT_HUNDREDS_MBPS 0x3
+#define ETS_GLOBAL_CONFIG_BW_UNIT_GBPS 0x4
+
+struct mlx5_ifc_register_qshr_bits {
+ u8 reserved_at_0[0x4];
+ u8 connected_host[0x1];
+ u8 vqos[0x1];
+ u8 fast_response[0x1];
+ u8 reserved_at_7[0x1];
+ u8 local_port[0x8];
+ u8 reserved_at_16[0x230];
+ struct mlx5_ifc_ets_global_config_register_bits global_config;
+};
+
#define MLX5_MTUTC_TIMESTAMP_MODE_INTERNAL_TIMER 0
#define MLX5_MTUTC_TIMESTAMP_MODE_REAL_TIME 1
@@ -1267,6 +1267,8 @@ struct mlx5_dev_ctx_shared {
void *devx_channel_lwm;
struct rte_intr_handle *intr_handle_lwm;
pthread_mutex_t lwm_config_lock;
+ uint32_t host_shaper_rate:8;
+ uint32_t lwm_triggered:1;
/* Availability of mreg_c's. */
struct mlx5_dev_shared_port port[]; /* per device port data array. */
};
@@ -28,6 +28,9 @@
#include "mlx5_rxtx.h"
#include "mlx5_devx.h"
#include "mlx5_rx.h"
+#ifdef HAVE_MLX5_MSTFLINT
+#include <mstflint/mtcr.h>
+#endif
static __rte_always_inline uint32_t
rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
@@ -1302,3 +1305,104 @@ int mlx5_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
pthread_mutex_unlock(&priv->sh->lwm_config_lock);
return ret;
}
+
+/**
+ * Mlx5 access register function to configure host shaper.
+ * It calls API in libmtcr_ul to access QSHR(Qos Shaper Host Register)
+ * in firmware.
+ *
+ * @param dev
+ * Pointer to rte_eth_dev.
+ * @param lwm_triggered
+ * Flag to enable/disable lwm_triggered bit in QSHR.
+ * @param rate
+ * Host shaper rate, unit is 100Mbps, set to 0 means disable the shaper.
+ * @return
+ * 0 : operation success.
+ * Otherwise:
+ * - ENOENT - no ibdev interface.
+ * - EBUSY - the register access unit is busy.
+ * - EIO - the register access command meets IO error.
+ */
+static int
+mlxreg_config_host_shaper(struct rte_eth_dev *dev,
+ bool lwm_triggered, uint8_t rate)
+{
+#ifdef HAVE_MLX5_MSTFLINT
+ struct mlx5_priv *priv = dev->data->dev_private;
+ uint32_t data[MLX5_ST_SZ_DW(register_qshr)] = {0};
+ int rc, retry_count = 3;
+ mfile *mf = NULL;
+ int status;
+ void *ptr;
+
+ mf = mopen(priv->sh->ibdev_name);
+ if (!mf) {
+ DRV_LOG(WARNING, "mopen failed\n");
+ rte_errno = ENOENT;
+ return -rte_errno;
+ }
+ MLX5_SET(register_qshr, data, connected_host, 1);
+ MLX5_SET(register_qshr, data, fast_response, lwm_triggered ? 1 : 0);
+ MLX5_SET(register_qshr, data, local_port, 1);
+ ptr = MLX5_ADDR_OF(register_qshr, data, global_config);
+ MLX5_SET(ets_global_config_register, ptr, rate_limit_update, 1);
+ MLX5_SET(ets_global_config_register, ptr, max_bw_units,
+ rate ? ETS_GLOBAL_CONFIG_BW_UNIT_HUNDREDS_MBPS :
+ ETS_GLOBAL_CONFIG_BW_UNIT_DISABLED);
+ MLX5_SET(ets_global_config_register, ptr, max_bw_value, rate);
+ do {
+ rc = maccess_reg(mf,
+ MLX5_QSHR_REGISTER_ID,
+ MACCESS_REG_METHOD_SET,
+ (u_int32_t *)&data[0],
+ sizeof(data),
+ sizeof(data),
+ sizeof(data),
+ &status);
+ if ((rc != ME_ICMD_STATUS_IFC_BUSY &&
+ status != ME_REG_ACCESS_BAD_PARAM) ||
+ !(mf->flags & MDEVS_REM)) {
+ break;
+ }
+ DRV_LOG(WARNING, "%s retry.", __func__);
+ usleep(10000);
+ } while (retry_count-- > 0);
+ mclose(mf);
+ rte_errno = (rc == ME_REG_ACCESS_DEV_BUSY) ? EBUSY : EIO;
+ return rc ? -rte_errno : 0;
+#else
+ (void)dev;
+ (void)lwm_triggered;
+ (void)rate;
+ return -1;
+#endif
+}
+
+int rte_pmd_mlx5_config_host_shaper(int port_id, uint8_t rate,
+ uint32_t flags)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct mlx5_priv *priv = dev->data->dev_private;
+ bool lwm_triggered =
+ !!(flags & RTE_BIT32(MLX5_HOST_SHAPER_FLAG_LWM_TRIGGERED));
+
+ if (!lwm_triggered) {
+ priv->sh->host_shaper_rate = rate;
+ } else {
+ switch (rate) {
+ case 0:
+ /* Rate 0 means disable lwm_triggered. */
+ priv->sh->lwm_triggered = 0;
+ break;
+ case 1:
+ /* Rate 1 means enable lwm_triggered. */
+ priv->sh->lwm_triggered = 1;
+ break;
+ default:
+ return -ENOTSUP;
+ }
+ }
+ return mlxreg_config_host_shaper(dev, priv->sh->lwm_triggered,
+ priv->sh->host_shaper_rate);
+}
@@ -141,6 +141,36 @@ int rte_pmd_mlx5_config_rxq_lwm(uint16_t port_id, uint16_t rxq_id,
uint8_t lwm,
lwm_event_rxq_limit_reached_t cb);
+/**
+ * The rate of the host port shaper will be updated directly at the next
+ * LWM event to the rate that comes with this flag set; set rate 0
+ * to disable this rate update.
+ * Unset this flag to update the rate of the host port shaper directly in
+ * the API call; use rate 0 to disable the current shaper.
+ */
+#define MLX5_HOST_SHAPER_FLAG_LWM_TRIGGERED 0
+
+/**
+ * Configure an HW shaper to limit Rx rate for a host port.
+ * The configuration will affect all the ethdev ports belonging to
+ * the same rte_device.
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] rate
+ * Unit is 100Mbps, setting the rate to 0 disables the shaper.
+ * @param[in] flags
+ * Host shaper flags.
+ * @return
+ * 0 : operation success.
+ * Otherwise:
+ * - ENOENT - no ibdev interface.
+ * - EBUSY - the register access unit is busy.
+ * - EIO - the register access command meets IO error.
+ */
+__rte_experimental
+int rte_pmd_mlx5_config_host_shaper(int port_id, uint8_t rate, uint32_t flags);
+
#ifdef __cplusplus
}
#endif
@@ -13,4 +13,5 @@ EXPERIMENTAL {
rte_pmd_mlx5_external_rx_queue_id_map;
rte_pmd_mlx5_external_rx_queue_id_unmap;
rte_pmd_mlx5_config_rxq_lwm;
+ rte_pmd_mlx5_config_host_shaper;
};