diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/701-net-0201-dpaa2-eth-Enable-Tx-PFC.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/701-net-0201-dpaa2-eth-Enable-Tx-PFC.patch | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/701-net-0201-dpaa2-eth-Enable-Tx-PFC.patch b/target/linux/layerscape/patches-5.4/701-net-0201-dpaa2-eth-Enable-Tx-PFC.patch new file mode 100644 index 0000000000..4efc15514d --- /dev/null +++ b/target/linux/layerscape/patches-5.4/701-net-0201-dpaa2-eth-Enable-Tx-PFC.patch @@ -0,0 +1,263 @@ +From 07fb72fb5b3d2faeeb742ae573aa54a4a1eeee12 Mon Sep 17 00:00:00 2001 +From: Ioana Radulescu <ruxandra.radulescu@nxp.com> +Date: Tue, 17 Sep 2019 20:36:08 +0300 +Subject: [PATCH] dpaa2-eth: Enable Tx PFC + +Configure the hardware to generate PFC frames based on Rx congestion +notifications. When a certain number of frames accumulate in the +ingress queues corresponding to a traffic class, priority flow control +frames are generated for that TC. + +Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com> +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 49 ++++++++++++++++++++- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 11 +++++ + drivers/net/ethernet/freescale/dpaa2/dpni-cmd.h | 25 +++++++++++ + drivers/net/ethernet/freescale/dpaa2/dpni.c | 46 +++++++++++++++++++ + drivers/net/ethernet/freescale/dpaa2/dpni.h | 56 ++++++++++++++++++++++++ + 5 files changed, 186 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -3622,6 +3622,47 @@ static int dpaa2_eth_dcbnl_ieee_getpfc(s + return 0; + } + ++static inline bool is_prio_enabled(u8 pfc_en, u8 tc) ++{ ++ return !!(pfc_en & (1 << tc)); ++} ++ ++static int set_pfc_cn(struct dpaa2_eth_priv *priv, u8 pfc_en) ++{ ++ struct dpni_congestion_notification_cfg cfg = {0}; ++ int i, err; ++ ++ cfg.notification_mode = DPNI_CONG_OPT_FLOW_CONTROL; ++ cfg.units = DPNI_CONGESTION_UNIT_FRAMES; ++ cfg.message_iova = 0ULL; ++ cfg.message_ctx = 0ULL; ++ ++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) { ++ if (is_prio_enabled(pfc_en, i)) { ++ cfg.threshold_entry = DPAA2_ETH_CN_THRESH_ENTRY(priv); ++ cfg.threshold_exit = DPAA2_ETH_CN_THRESH_EXIT(priv); ++ } else { ++ /* For priorities not set in the pfc_en mask, we leave ++ * the congestion thresholds at zero, which effectively ++ * disables generation of PFC frames for them ++ */ ++ cfg.threshold_entry = 0; ++ cfg.threshold_exit = 0; ++ } ++ ++ err = dpni_set_congestion_notification(priv->mc_io, 0, ++ priv->mc_token, ++ DPNI_QUEUE_RX, i, &cfg); ++ if (err) { ++ netdev_err(priv->net_dev, ++ "dpni_set_congestion_notification failed\n"); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ + static int dpaa2_eth_dcbnl_ieee_setpfc(struct net_device *net_dev, + struct ieee_pfc *pfc) + { +@@ -3639,7 +3680,8 @@ static int dpaa2_eth_dcbnl_ieee_setpfc(s + /* We allow PFC configuration even if it won't have any effect until + * general pause frames are enabled + */ +- if (!dpaa2_eth_rx_pause_enabled(priv->link_state.options)) ++ if (!dpaa2_eth_rx_pause_enabled(priv->link_state.options) || ++ !dpaa2_eth_tx_pause_enabled(priv->link_state.options)) + netdev_warn(net_dev, "Pause support must be enabled in order for PFC to work!\n"); + + link_cfg.rate = priv->link_state.rate; +@@ -3654,6 +3696,11 @@ static int dpaa2_eth_dcbnl_ieee_setpfc(s + return err; + } + ++ /* Configure congestion notifications for the enabled priorities */ ++ err = set_pfc_cn(priv, pfc->pfc_en); ++ if (err) ++ return err; ++ + memcpy(&priv->pfc, pfc, sizeof(priv->pfc)); + + return 0; +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +@@ -65,6 +65,17 @@ + #define DPAA2_ETH_CG_TAILDROP_THRESH(priv) \ + (1024 * dpaa2_eth_queue_count(priv) / dpaa2_eth_tc_count(priv)) + ++/* Congestion group notification threshold: when this many frames accumulate ++ * on the Rx queues belonging to the same TC, the MAC is instructed to send ++ * PFC frames for that TC. ++ * When number of pending frames drops below exit threshold transmission of ++ * PFC frames is stopped. ++ */ ++#define DPAA2_ETH_CN_THRESH_ENTRY(priv) \ ++ (DPAA2_ETH_CG_TAILDROP_THRESH(priv) / 2) ++#define DPAA2_ETH_CN_THRESH_EXIT(priv) \ ++ (DPAA2_ETH_CN_THRESH_ENTRY(priv) * 3 / 4) ++ + /* Maximum number of buffers that can be acquired/released through a single + * QBMan command + */ +--- a/drivers/net/ethernet/freescale/dpaa2/dpni-cmd.h ++++ b/drivers/net/ethernet/freescale/dpaa2/dpni-cmd.h +@@ -601,4 +601,29 @@ struct dpni_cmd_remove_qos_entry { + __le64 mask_iova; + }; + ++#define DPNI_DEST_TYPE_SHIFT 0 ++#define DPNI_DEST_TYPE_SIZE 4 ++#define DPNI_CONG_UNITS_SHIFT 4 ++#define DPNI_CONG_UNITS_SIZE 2 ++ ++struct dpni_cmd_set_congestion_notification { ++ /* cmd word 0 */ ++ u8 qtype; ++ u8 tc; ++ u8 pad[6]; ++ /* cmd word 1 */ ++ __le32 dest_id; ++ __le16 notification_mode; ++ u8 dest_priority; ++ /* from LSB: dest_type: 4 units:2 */ ++ u8 type_units; ++ /* cmd word 2 */ ++ __le64 message_iova; ++ /* cmd word 3 */ ++ __le64 message_ctx; ++ /* cmd word 4 */ ++ __le32 threshold_entry; ++ __le32 threshold_exit; ++}; ++ + #endif /* _FSL_DPNI_CMD_H */ +--- a/drivers/net/ethernet/freescale/dpaa2/dpni.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpni.c +@@ -1355,6 +1355,52 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io + } + + /** ++ * 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, ++ u32 cmd_flags, ++ u16 token, ++ enum dpni_queue_type qtype, ++ u8 tc_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct dpni_cmd_set_congestion_notification *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = ++ mc_encode_cmd_header(DPNI_CMDID_SET_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ cmd_params = (struct dpni_cmd_set_congestion_notification *)cmd.params; ++ cmd_params->qtype = qtype; ++ cmd_params->tc = tc_id; ++ cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id); ++ cmd_params->notification_mode = cpu_to_le16(cfg->notification_mode); ++ cmd_params->dest_priority = cfg->dest_cfg.priority; ++ dpni_set_field(cmd_params->type_units, DEST_TYPE, ++ cfg->dest_cfg.dest_type); ++ dpni_set_field(cmd_params->type_units, CONG_UNITS, cfg->units); ++ cmd_params->message_iova = cpu_to_le64(cfg->message_iova); ++ cmd_params->message_ctx = cpu_to_le64(cfg->message_ctx); ++ cmd_params->threshold_entry = cpu_to_le32(cfg->threshold_entry); ++ cmd_params->threshold_exit = cpu_to_le32(cfg->threshold_exit); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** + * dpni_set_queue() - Set queue parameters + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +--- a/drivers/net/ethernet/freescale/dpaa2/dpni.h ++++ b/drivers/net/ethernet/freescale/dpaa2/dpni.h +@@ -883,6 +883,62 @@ enum dpni_congestion_point { + }; + + /** ++ * 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; ++ u8 priority; ++}; ++ ++/* DPNI congestion options */ ++ ++/** ++ * This congestion will trigger flow control or priority flow control. ++ * This will have effect only if flow control is enabled with ++ * dpni_set_link_cfg(). ++ */ ++#define DPNI_CONG_OPT_FLOW_CONTROL 0x00000040 ++ ++/** ++ * 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; ++ u32 threshold_entry; ++ u32 threshold_exit; ++ u64 message_ctx; ++ u64 message_iova; ++ struct dpni_dest_cfg dest_cfg; ++ u16 notification_mode; ++}; ++ ++int dpni_set_congestion_notification( ++ struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ enum dpni_queue_type qtype, ++ u8 tc_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** + * struct dpni_taildrop - Structure representing the taildrop + * @enable: Indicates whether the taildrop is active or not. + * @units: Indicates the unit of THRESHOLD. Queue taildrop only supports |