uint64_t rx_pkts;
uint64_t tx_pkts;
uint64_t err_pkts;
- struct queue_storage_info_t *q_storage;
+ union {
+ struct queue_storage_info_t *q_storage;
+ struct qbman_result *cscn;
+ };
};
struct swp_active_dqs {
for (i = 0; i < priv->nb_tx_queues; i++) {
mc_q->dev = dev;
- mc_q->flow_id = DPNI_NEW_FLOW_ID;
+ mc_q->flow_id = 0xffff;
priv->tx_vq[i] = mc_q++;
+ dpaa2_q = (struct dpaa2_queue *)priv->tx_vq[i];
+ dpaa2_q->cscn = rte_malloc(NULL,
+ sizeof(struct qbman_result), 16);
+ if (!dpaa2_q->cscn)
+ goto fail_tx;
}
vq_id = 0;
}
return 0;
+fail_tx:
+ i -= 1;
+ while (i >= 0) {
+ dpaa2_q = (struct dpaa2_queue *)priv->tx_vq[i];
+ rte_free(dpaa2_q->cscn);
+ priv->tx_vq[i--] = NULL;
+ }
+ i = priv->nb_rx_queues;
fail:
i -= 1;
mc_q = priv->rx_vq[0];
PMD_INIT_FUNC_TRACE();
/* Return if queue already configured */
- if (dpaa2_q->flow_id != DPNI_NEW_FLOW_ID)
+ if (dpaa2_q->flow_id != 0xffff)
return 0;
memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue));
}
dpaa2_q->tc_index = tc_id;
+ if (priv->flags & DPAA2_TX_CGR_SUPPORT) {
+ struct dpni_congestion_notification_cfg cong_notif_cfg;
+
+ cong_notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES;
+ /* Notify about congestion when the queue size is 32 KB */
+ cong_notif_cfg.threshold_entry = CONG_ENTER_TX_THRESHOLD;
+ /* Notify that the queue is not congested when the data in
+ * the queue is below this thershold.
+ */
+ cong_notif_cfg.threshold_exit = CONG_EXIT_TX_THRESHOLD;
+ cong_notif_cfg.message_ctx = 0;
+ cong_notif_cfg.message_iova = (uint64_t)dpaa2_q->cscn;
+ cong_notif_cfg.dest_cfg.dest_type = DPNI_DEST_NONE;
+ cong_notif_cfg.notification_mode =
+ DPNI_CONG_OPT_WRITE_MEM_ON_ENTER |
+ DPNI_CONG_OPT_WRITE_MEM_ON_EXIT |
+ DPNI_CONG_OPT_COHERENT_WRITE;
+
+ ret = dpni_set_congestion_notification(dpni, CMD_PRI_LOW,
+ priv->token,
+ DPNI_QUEUE_TX,
+ tc_id,
+ &cong_notif_cfg);
+ if (ret) {
+ PMD_INIT_LOG(ERR,
+ "Error in setting tx congestion notification: = %d",
+ -ret);
+ return -ret;
+ }
+ }
dev->data->tx_queues[tx_queue_id] = dpaa2_q;
return 0;
}
static void
dpaa2_dev_close(struct rte_eth_dev *dev)
{
+ struct rte_eth_dev_data *data = dev->data;
struct dpaa2_dev_priv *priv = dev->data->dev_private;
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
- int ret;
+ int i, ret;
+ struct dpaa2_queue *dpaa2_q;
PMD_INIT_FUNC_TRACE();
+ for (i = 0; i < data->nb_tx_queues; i++) {
+ dpaa2_q = (struct dpaa2_queue *)data->tx_queues[i];
+ if (!dpaa2_q->cscn) {
+ rte_free(dpaa2_q->cscn);
+ dpaa2_q->cscn = NULL;
+ }
+ }
+
/* Clean the device first */
ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token);
if (ret) {
priv->max_vlan_filters = attr.vlan_filter_entries;
priv->flags = 0;
+ priv->flags |= DPAA2_TX_CGR_SUPPORT;
+ PMD_INIT_LOG(INFO, "Enable the tx congestion control support");
+
/* Allocate memory for hardware structure for queues */
ret = dpaa2_alloc_rx_tx_queues(eth_dev);
if (ret) {
/*default tc to be used for ,congestion, distribution etc configuration. */
#define DPAA2_DEF_TC 0
+/* Threshold for a queue to *Enter* Congestion state.
+ * It is set to 32KB
+ */
+#define CONG_ENTER_TX_THRESHOLD (32 * 1024)
+
+/* Threshold for a queue to *Exit* Congestion state.
+ */
+#define CONG_EXIT_TX_THRESHOLD (24 * 1024)
+
/* Size of the input SMMU mapped memory required by MC */
#define DIST_PARAM_IOVA_SIZE 256
+/* Enable TX Congestion control support
+ * default is disable
+ */
+#define DPAA2_TX_CGR_SUPPORT 0x01
+
struct dpaa2_dev_priv {
void *hw;
int32_t hw_id;
/*Clear the unused FD fields before sending*/
while (nb_pkts) {
+ /*Check if the queue is congested*/
+ if (qbman_result_SCN_state_in_mem(dpaa2_q->cscn))
+ goto skip_tx;
+
frames_to_send = (nb_pkts >> 3) ? MAX_TX_RING_SLOTS : nb_pkts;
for (loop = 0; loop < frames_to_send; loop++) {
return mc_send_command(mc_io, &cmd);
}
+int dpni_set_congestion_notification(
+ struct fsl_mc_io *mc_io,
+ uint32_t cmd_flags,
+ uint16_t token,
+ enum dpni_queue_type qtype,
+ uint8_t tc_id,
+ const struct dpni_congestion_notification_cfg *cfg)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(
+ DPNI_CMDID_SET_CONGESTION_NOTIFICATION,
+ cmd_flags,
+ token);
+ DPNI_CMD_SET_CONGESTION_NOTIFICATION(cmd, qtype, tc_id, cfg);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_congestion_notification(struct fsl_mc_io *mc_io,
+ uint32_t cmd_flags,
+ uint16_t token,
+ enum dpni_queue_type qtype,
+ uint8_t tc_id,
+ struct dpni_congestion_notification_cfg *cfg)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(
+ DPNI_CMDID_GET_CONGESTION_NOTIFICATION,
+ cmd_flags,
+ token);
+ DPNI_CMD_GET_CONGESTION_NOTIFICATION(cmd, qtype, tc_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ DPNI_RSP_GET_CONGESTION_NOTIFICATION(cmd, cfg);
+
+ return 0;
+}
+
int dpni_get_api_version(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t *major_ver,
* All flows within traffic class considered; see dpni_set_queue()
*/
#define DPNI_ALL_TC_FLOWS (uint16_t)(-1)
-/**
- * Generate new flow ID; see dpni_set_queue()
- */
-#define DPNI_NEW_FLOW_ID (uint16_t)(-1)
+
/**
* Tx traffic is always released to a buffer pool on transmit, there are no
* resources allocated to have the frames confirmed back to the source after
uint16_t token,
uint8_t tc_id,
const struct dpni_rx_tc_dist_cfg *cfg);
+/**
+ * enum dpni_congestion_unit - DPNI congestion units
+ * @DPNI_CONGESTION_UNIT_BYTES: bytes units
+ * @DPNI_CONGESTION_UNIT_FRAMES: frames units
+ */
+enum dpni_congestion_unit {
+ DPNI_CONGESTION_UNIT_BYTES = 0,
+ DPNI_CONGESTION_UNIT_FRAMES
+};
+
/**
* enum dpni_dest - DPNI destination types
DPNI_DEST_DPCON = 2
};
+/**
+ * struct dpni_dest_cfg - Structure representing DPNI destination parameters
+ * @dest_type: Destination type
+ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type
+ * @priority: Priority selection within the DPIO or DPCON channel; valid values
+ * are 0-1 or 0-7, depending on the number of priorities in that
+ * channel; not relevant for 'DPNI_DEST_NONE' option
+ */
+struct dpni_dest_cfg {
+ enum dpni_dest dest_type;
+ int dest_id;
+ uint8_t priority;
+};
+
+/* DPNI congestion options */
+
+/**
+ * CSCN message is written to message_iova once entering a
+ * congestion state (see 'threshold_entry')
+ */
+#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER 0x00000001
+/**
+ * CSCN message is written to message_iova once exiting a
+ * congestion state (see 'threshold_exit')
+ */
+#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT 0x00000002
+/**
+ * CSCN write will attempt to allocate into a cache (coherent write);
+ * valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is selected
+ */
+#define DPNI_CONG_OPT_COHERENT_WRITE 0x00000004
+/**
+ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to
+ * DPIO/DPCON's WQ channel once entering a congestion state
+ * (see 'threshold_entry')
+ */
+#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER 0x00000008
+/**
+ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to
+ * DPIO/DPCON's WQ channel once exiting a congestion state
+ * (see 'threshold_exit')
+ */
+#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT 0x00000010
+/**
+ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' when the CSCN is written to the
+ * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled)
+ */
+#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020
+
+/**
+ * struct dpni_congestion_notification_cfg - congestion notification
+ * configuration
+ * @units: units type
+ * @threshold_entry: above this threshold we enter a congestion state.
+ * set it to '0' to disable it
+ * @threshold_exit: below this threshold we exit the congestion state.
+ * @message_ctx: The context that will be part of the CSCN message
+ * @message_iova: I/O virtual address (must be in DMA-able memory),
+ * must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is
+ * contained in 'options'
+ * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel
+ * @notification_mode: Mask of available options; use 'DPNI_CONG_OPT_<X>' values
+ */
+
+struct dpni_congestion_notification_cfg {
+ enum dpni_congestion_unit units;
+ uint32_t threshold_entry;
+ uint32_t threshold_exit;
+ uint64_t message_ctx;
+ uint64_t message_iova;
+ struct dpni_dest_cfg dest_cfg;
+ uint16_t notification_mode;
+};
+
+/**
+ * dpni_set_congestion_notification() - Set traffic class congestion
+ * notification configuration
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @qtype: Type of queue - Rx, Tx and Tx confirm types are supported
+ * @tc_id: Traffic class selection (0-7)
+ * @cfg: congestion notification configuration
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpni_set_congestion_notification(
+ struct fsl_mc_io *mc_io,
+ uint32_t cmd_flags,
+ uint16_t token,
+ enum dpni_queue_type qtype,
+ uint8_t tc_id,
+ const struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * dpni_get_congestion_notification() - Get traffic class congestion
+ * notification configuration
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @qtype: Type of queue - Rx, Tx and Tx confirm types are supported
+ * @tc_id: Traffic class selection (0-7)
+ * @cfg: congestion notification configuration
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpni_get_congestion_notification(struct fsl_mc_io *mc_io,
+ uint32_t cmd_flags,
+ uint16_t token,
+ enum dpni_queue_type qtype,
+ uint8_t tc_id,
+ struct dpni_congestion_notification_cfg *cfg);
+
/**
* struct dpni_queue - Queue structure
* Calling this function with 'mode' set to DPNI_CONF_SINGLE switches all
* Tx confirmations to a shared Tx conf queue. The ID of the queue when
* calling dpni_set/get_queue is -1.
+ * Tx confirmation mode can only be changed while the DPNI is disabled.
+ * Executing this command while the DPNI is enabled will return an error.
*
* Return: '0' on Success; Error code otherwise.
*/
#define DPNI_CMDID_GET_BUFFER_LAYOUT ((0x264 << 4) | (0x1))
#define DPNI_CMDID_SET_BUFFER_LAYOUT ((0x265 << 4) | (0x1))
+#define DPNI_CMDID_SET_CONGESTION_NOTIFICATION ((0x267 << 4) | (0x1))
+#define DPNI_CMDID_GET_CONGESTION_NOTIFICATION ((0x268 << 4) | (0x1))
#define DPNI_CMDID_GET_OFFLOAD ((0x26B << 4) | (0x1))
#define DPNI_CMDID_SET_OFFLOAD ((0x26C << 4) | (0x1))
#define DPNI_CMDID_SET_TX_CONFIRMATION_MODE ((0x266 << 4) | (0x1))
#define DPNI_RSP_GET_TX_CONFIRMATION_MODE(cmd, mode) \
MC_RSP_OP(cmd, 0, 32, 8, enum dpni_confirmation_mode, mode)
+#define DPNI_CMD_SET_CONGESTION_NOTIFICATION(cmd, qtype, tc, cfg) \
+do { \
+ MC_CMD_OP(cmd, 0, 0, 8, enum dpni_queue_type, qtype); \
+ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc); \
+ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, (cfg)->dest_cfg.dest_id); \
+ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, (cfg)->notification_mode); \
+ MC_CMD_OP(cmd, 1, 48, 8, uint8_t, (cfg)->dest_cfg.priority); \
+ MC_CMD_OP(cmd, 1, 56, 4, enum dpni_dest, (cfg)->dest_cfg.dest_type); \
+ MC_CMD_OP(cmd, 1, 60, 2, enum dpni_congestion_unit, (cfg)->units); \
+ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, (cfg)->message_iova); \
+ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, (cfg)->message_ctx); \
+ MC_CMD_OP(cmd, 4, 0, 32, uint32_t, (cfg)->threshold_entry); \
+ MC_CMD_OP(cmd, 4, 32, 32, uint32_t, (cfg)->threshold_exit); \
+} while (0)
+
+#define DPNI_CMD_GET_CONGESTION_NOTIFICATION(cmd, qtype, tc) \
+do { \
+ MC_CMD_OP(cmd, 0, 0, 8, enum dpni_queue_type, qtype); \
+ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc); \
+} while (0)
+
+#define DPNI_RSP_GET_CONGESTION_NOTIFICATION(cmd, cfg) \
+do { \
+ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, (cfg)->dest_cfg.dest_id); \
+ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, (cfg)->notification_mode); \
+ MC_RSP_OP(cmd, 1, 48, 8, uint8_t, (cfg)->dest_cfg.priority); \
+ MC_RSP_OP(cmd, 1, 56, 4, enum dpni_dest, (cfg)->dest_cfg.dest_type); \
+ MC_RSP_OP(cmd, 1, 60, 2, enum dpni_congestion_unit, (cfg)->units); \
+ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, (cfg)->message_iova); \
+ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, (cfg)->message_ctx); \
+ MC_RSP_OP(cmd, 4, 0, 32, uint32_t, (cfg)->threshold_entry); \
+ MC_RSP_OP(cmd, 4, 32, 32, uint32_t, (cfg)->threshold_exit); \
+} while (0)
+
#endif /* _FSL_DPNI_CMD_H */