Skip to content

Commit

Permalink
ice: Add NDO callback to set the maximum per-queue bitrate
Browse files Browse the repository at this point in the history
Allow for rate limiting Tx queues. Bitrate is set in
Mbps(megabits per second).

Mbps max-rate is set for the queue via sysfs:
/sys/class/net/<iface>/queues/tx-<queue>/tx_maxrate
ex: echo 100 >/sys/class/net/ens7/queues/tx-0/tx_maxrate
    echo 200 >/sys/class/net/ens7/queues/tx-1/tx_maxrate
Note: A value of zero for tx_maxrate means disabled,
default is disabled.

Signed-off-by: Usha Ketineni <usha.k.ketineni@intel.com>
Co-developed-by: Tarun Singh <tarun.k.singh@intel.com>
Signed-off-by: Tarun Singh <tarun.k.singh@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Usha Ketineni authored and Jeff Kirsher committed Nov 8, 2019
1 parent 9d614b6 commit 1ddef45
Show file tree
Hide file tree
Showing 10 changed files with 1,480 additions and 10 deletions.
46 changes: 46 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,10 @@ struct ice_aqc_add_elem {
struct ice_aqc_txsched_elem_data generic[1];
};

struct ice_aqc_conf_elem {
struct ice_aqc_txsched_elem_data generic[1];
};

struct ice_aqc_get_elem {
struct ice_aqc_txsched_elem_data generic[1];
};
Expand Down Expand Up @@ -783,6 +787,44 @@ struct ice_aqc_port_ets_elem {
__le32 tc_node_teid[8]; /* Used for response, reserved in command */
};

/* Rate limiting profile for
* Add RL profile (indirect 0x0410)
* Query RL profile (indirect 0x0411)
* Remove RL profile (indirect 0x0415)
* These indirect commands acts on single or multiple
* RL profiles with specified data.
*/
struct ice_aqc_rl_profile {
__le16 num_profiles;
__le16 num_processed; /* Only for response. Reserved in Command. */
u8 reserved[4];
__le32 addr_high;
__le32 addr_low;
};

struct ice_aqc_rl_profile_elem {
u8 level;
u8 flags;
#define ICE_AQC_RL_PROFILE_TYPE_S 0x0
#define ICE_AQC_RL_PROFILE_TYPE_M (0x3 << ICE_AQC_RL_PROFILE_TYPE_S)
#define ICE_AQC_RL_PROFILE_TYPE_CIR 0
#define ICE_AQC_RL_PROFILE_TYPE_EIR 1
#define ICE_AQC_RL_PROFILE_TYPE_SRL 2
/* The following flag is used for Query RL Profile Data */
#define ICE_AQC_RL_PROFILE_INVAL_S 0x7
#define ICE_AQC_RL_PROFILE_INVAL_M (0x1 << ICE_AQC_RL_PROFILE_INVAL_S)

__le16 profile_id;
__le16 max_burst_size;
__le16 rl_multiply;
__le16 wake_up_calc;
__le16 rl_encode;
};

struct ice_aqc_rl_profile_generic_elem {
struct ice_aqc_rl_profile_elem generic[1];
};

/* Query Scheduler Resource Allocation (indirect 0x0412)
* This indirect command retrieves the scheduler resources allocated by
* EMP Firmware to the given PF.
Expand Down Expand Up @@ -1657,6 +1699,7 @@ struct ice_aq_desc {
struct ice_aqc_sched_elem_cmd sched_elem_cmd;
struct ice_aqc_query_txsched_res query_sched_res;
struct ice_aqc_query_port_ets port_ets;
struct ice_aqc_rl_profile rl_profile;
struct ice_aqc_nvm nvm;
struct ice_aqc_nvm_checksum nvm_checksum;
struct ice_aqc_pf_vf_msg virt;
Expand Down Expand Up @@ -1758,12 +1801,15 @@ enum ice_adminq_opc {
/* transmit scheduler commands */
ice_aqc_opc_get_dflt_topo = 0x0400,
ice_aqc_opc_add_sched_elems = 0x0401,
ice_aqc_opc_cfg_sched_elems = 0x0403,
ice_aqc_opc_get_sched_elems = 0x0404,
ice_aqc_opc_suspend_sched_elems = 0x0409,
ice_aqc_opc_resume_sched_elems = 0x040A,
ice_aqc_opc_query_port_ets = 0x040E,
ice_aqc_opc_delete_sched_elems = 0x040F,
ice_aqc_opc_add_rl_profiles = 0x0410,
ice_aqc_opc_query_sched_res = 0x0412,
ice_aqc_opc_remove_rl_profiles = 0x0415,

/* PHY commands */
ice_aqc_opc_get_phy_caps = 0x0600,
Expand Down
10 changes: 8 additions & 2 deletions drivers/net/ethernet/intel/ice/ice_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,9 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
goto err_unroll_sched;
}
INIT_LIST_HEAD(&hw->agg_list);
/* Initialize max burst size */
if (!hw->max_burst_size)
ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);

status = ice_init_fltr_mgmt_struct(hw);
if (status)
Expand Down Expand Up @@ -3260,7 +3263,7 @@ ice_set_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
* @tc: TC number
* @q_handle: software queue handle
*/
static struct ice_q_ctx *
struct ice_q_ctx *
ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
{
struct ice_vsi_ctx *vsi;
Expand Down Expand Up @@ -3357,9 +3360,12 @@ ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
node.node_teid = buf->txqs[0].q_teid;
node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
q_ctx->q_handle = q_handle;
q_ctx->q_teid = le32_to_cpu(node.node_teid);

/* add a leaf node into schduler tree queue layer */
/* add a leaf node into scheduler tree queue layer */
status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node);
if (!status)
status = ice_sched_replay_q_bw(pi, q_ctx);

ena_txq_exit:
mutex_unlock(&pi->sched_lock);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle);
void ice_replay_post(struct ice_hw *hw);
void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf);
struct ice_q_ctx *
ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle);
void
ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
u64 *prev_stat, u64 *cur_stat);
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_dcb_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg)
return ret;
}

/**
* ice_dcb_get_tc - Get the TC associated with the queue
* @vsi: ptr to the VSI
* @queue_index: queue number associated with VSI
*/
u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index)
{
return vsi->tx_rings[queue_index]->dcb_tc;
}

/**
* ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC
* @vsi: VSI owner of rings being updated
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_dcb_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
void ice_dcb_rebuild(struct ice_pf *pf);
u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg);
u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg);
u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
void ice_update_dcb_stats(struct ice_pf *pf);
Expand Down Expand Up @@ -42,6 +43,13 @@ static inline u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg __always_unused *dcbcfg)
return 1;
}

static inline u8
ice_dcb_get_tc(struct ice_vsi __always_unused *vsi,
int __always_unused queue_index)
{
return 0;
}

static inline int
ice_init_pf_dcb(struct ice_pf *pf, bool __always_unused locked)
{
Expand Down
43 changes: 43 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3648,6 +3648,48 @@ static void ice_set_rx_mode(struct net_device *netdev)
ice_service_task_schedule(vsi->back);
}

/**
* ice_set_tx_maxrate - NDO callback to set the maximum per-queue bitrate
* @netdev: network interface device structure
* @queue_index: Queue ID
* @maxrate: maximum bandwidth in Mbps
*/
static int
ice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
enum ice_status status;
u16 q_handle;
u8 tc;

/* Validate maxrate requested is within permitted range */
if (maxrate && (maxrate > (ICE_SCHED_MAX_BW / 1000))) {
netdev_err(netdev,
"Invalid max rate %d specified for the queue %d\n",
maxrate, queue_index);
return -EINVAL;
}

q_handle = vsi->tx_rings[queue_index]->q_handle;
tc = ice_dcb_get_tc(vsi, queue_index);

/* Set BW back to default, when user set maxrate to 0 */
if (!maxrate)
status = ice_cfg_q_bw_dflt_lmt(vsi->port_info, vsi->idx, tc,
q_handle, ICE_MAX_BW);
else
status = ice_cfg_q_bw_lmt(vsi->port_info, vsi->idx, tc,
q_handle, ICE_MAX_BW, maxrate * 1000);
if (status) {
netdev_err(netdev,
"Unable to set Tx max rate, error %d\n", status);
return -EIO;
}

return 0;
}

/**
* ice_fdb_add - add an entry to the hardware database
* @ndm: the input from the stack
Expand Down Expand Up @@ -5159,6 +5201,7 @@ static const struct net_device_ops ice_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ice_change_mtu,
.ndo_get_stats64 = ice_get_stats64,
.ndo_set_tx_maxrate = ice_set_tx_maxrate,
.ndo_set_vf_spoofchk = ice_set_vf_spoofchk,
.ndo_set_vf_mac = ice_set_vf_mac,
.ndo_get_vf_config = ice_get_vf_cfg,
Expand Down
Loading

0 comments on commit 1ddef45

Please sign in to comment.