Skip to content

Commit

Permalink
Merge branch 'mlx4-qcn'
Browse files Browse the repository at this point in the history
Or Gerlitz says:

====================
Add QCN support to the DCB NL layer

This series from Shani Michaeli adds support for the IEEE QCN attribute
to the kernel DCB NL stack, and implementation in the mlx4 driver which
programs the firmware according to the admin directives.

changes from V0:

 - applied feedback from John and added his acked-by to patch #1
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 7, 2015
2 parents 34de26d + 708b869 commit f68a8eb
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 6 deletions.
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mellanox/mlx4/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,15 @@ static struct mlx4_cmd_info cmd_info[] = {
.verify = NULL,
.wrapper = mlx4_ACCESS_REG_wrapper,
},
{
.opcode = MLX4_CMD_CONGESTION_CTRL_OPCODE,
.has_inbox = false,
.has_outbox = false,
.out_is_imm = false,
.encode_slave_id = false,
.verify = NULL,
.wrapper = mlx4_CMD_EPERM_wrapper,
},
/* Native multicast commands are not available for guests */
{
.opcode = MLX4_CMD_QP_ATTACH,
Expand Down
218 changes: 218 additions & 0 deletions drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,49 @@

#include "mlx4_en.h"

/* Definitions for QCN
*/

struct mlx4_congestion_control_mb_prio_802_1_qau_params {
__be32 modify_enable_high;
__be32 modify_enable_low;
__be32 reserved1;
__be32 extended_enable;
__be32 rppp_max_rps;
__be32 rpg_time_reset;
__be32 rpg_byte_reset;
__be32 rpg_threshold;
__be32 rpg_max_rate;
__be32 rpg_ai_rate;
__be32 rpg_hai_rate;
__be32 rpg_gd;
__be32 rpg_min_dec_fac;
__be32 rpg_min_rate;
__be32 max_time_rise;
__be32 max_byte_rise;
__be32 max_qdelta;
__be32 min_qoffset;
__be32 gd_coefficient;
__be32 reserved2[5];
__be32 cp_sample_base;
__be32 reserved3[39];
};

struct mlx4_congestion_control_mb_prio_802_1_qau_statistics {
__be64 rppp_rp_centiseconds;
__be32 reserved1;
__be32 ignored_cnm;
__be32 rppp_created_rps;
__be32 estimated_total_rate;
__be32 max_active_rate_limiter_index;
__be32 dropped_cnms_busy_fw;
__be32 reserved2;
__be32 cnms_handled_successfully;
__be32 min_total_limiters_rate;
__be32 max_total_limiters_rate;
__be32 reserved3[4];
};

static int mlx4_en_dcbnl_ieee_getets(struct net_device *dev,
struct ieee_ets *ets)
{
Expand Down Expand Up @@ -242,6 +285,178 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
return 0;
}

#define RPG_ENABLE_BIT 31
#define CN_TAG_BIT 30

static int mlx4_en_dcbnl_ieee_getqcn(struct net_device *dev,
struct ieee_qcn *qcn)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;
struct mlx4_cmd_mailbox *mailbox_out = NULL;
u64 mailbox_in_dma = 0;
u32 inmod = 0;
int i, err;

if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
return -EOPNOTSUPP;

mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
if (IS_ERR(mailbox_out))
return -ENOMEM;
hw_qcn =
(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)
mailbox_out->buf;

for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
inmod = priv->port | ((1 << i) << 8) |
(MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,
mailbox_out->dma,
inmod, MLX4_CONGESTION_CONTROL_GET_PARAMS,
MLX4_CMD_CONGESTION_CTRL_OPCODE,
MLX4_CMD_TIME_CLASS_C,
MLX4_CMD_NATIVE);
if (err) {
mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
return err;
}

qcn->rpg_enable[i] =
be32_to_cpu(hw_qcn->extended_enable) >> RPG_ENABLE_BIT;
qcn->rppp_max_rps[i] =
be32_to_cpu(hw_qcn->rppp_max_rps);
qcn->rpg_time_reset[i] =
be32_to_cpu(hw_qcn->rpg_time_reset);
qcn->rpg_byte_reset[i] =
be32_to_cpu(hw_qcn->rpg_byte_reset);
qcn->rpg_threshold[i] =
be32_to_cpu(hw_qcn->rpg_threshold);
qcn->rpg_max_rate[i] =
be32_to_cpu(hw_qcn->rpg_max_rate);
qcn->rpg_ai_rate[i] =
be32_to_cpu(hw_qcn->rpg_ai_rate);
qcn->rpg_hai_rate[i] =
be32_to_cpu(hw_qcn->rpg_hai_rate);
qcn->rpg_gd[i] =
be32_to_cpu(hw_qcn->rpg_gd);
qcn->rpg_min_dec_fac[i] =
be32_to_cpu(hw_qcn->rpg_min_dec_fac);
qcn->rpg_min_rate[i] =
be32_to_cpu(hw_qcn->rpg_min_rate);
qcn->cndd_state_machine[i] =
priv->cndd_state[i];
}
mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
return 0;
}

static int mlx4_en_dcbnl_ieee_setqcn(struct net_device *dev,
struct ieee_qcn *qcn)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;
struct mlx4_cmd_mailbox *mailbox_in = NULL;
u64 mailbox_in_dma = 0;
u32 inmod = 0;
int i, err;
#define MODIFY_ENABLE_HIGH_MASK 0xc0000000
#define MODIFY_ENABLE_LOW_MASK 0xffc00000

if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
return -EOPNOTSUPP;

mailbox_in = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
if (IS_ERR(mailbox_in))
return -ENOMEM;

mailbox_in_dma = mailbox_in->dma;
hw_qcn =
(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)mailbox_in->buf;
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
inmod = priv->port | ((1 << i) << 8) |
(MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);

/* Before updating QCN parameter,
* need to set it's modify enable bit to 1
*/

hw_qcn->modify_enable_high = cpu_to_be32(
MODIFY_ENABLE_HIGH_MASK);
hw_qcn->modify_enable_low = cpu_to_be32(MODIFY_ENABLE_LOW_MASK);

hw_qcn->extended_enable = cpu_to_be32(qcn->rpg_enable[i] << RPG_ENABLE_BIT);
hw_qcn->rppp_max_rps = cpu_to_be32(qcn->rppp_max_rps[i]);
hw_qcn->rpg_time_reset = cpu_to_be32(qcn->rpg_time_reset[i]);
hw_qcn->rpg_byte_reset = cpu_to_be32(qcn->rpg_byte_reset[i]);
hw_qcn->rpg_threshold = cpu_to_be32(qcn->rpg_threshold[i]);
hw_qcn->rpg_max_rate = cpu_to_be32(qcn->rpg_max_rate[i]);
hw_qcn->rpg_ai_rate = cpu_to_be32(qcn->rpg_ai_rate[i]);
hw_qcn->rpg_hai_rate = cpu_to_be32(qcn->rpg_hai_rate[i]);
hw_qcn->rpg_gd = cpu_to_be32(qcn->rpg_gd[i]);
hw_qcn->rpg_min_dec_fac = cpu_to_be32(qcn->rpg_min_dec_fac[i]);
hw_qcn->rpg_min_rate = cpu_to_be32(qcn->rpg_min_rate[i]);
priv->cndd_state[i] = qcn->cndd_state_machine[i];
if (qcn->cndd_state_machine[i] == DCB_CNDD_INTERIOR_READY)
hw_qcn->extended_enable |= cpu_to_be32(1 << CN_TAG_BIT);

err = mlx4_cmd(priv->mdev->dev, mailbox_in_dma, inmod,
MLX4_CONGESTION_CONTROL_SET_PARAMS,
MLX4_CMD_CONGESTION_CTRL_OPCODE,
MLX4_CMD_TIME_CLASS_C,
MLX4_CMD_NATIVE);
if (err) {
mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);
return err;
}
}
mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);
return 0;
}

static int mlx4_en_dcbnl_ieee_getqcnstats(struct net_device *dev,
struct ieee_qcn_stats *qcn_stats)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *hw_qcn_stats;
struct mlx4_cmd_mailbox *mailbox_out = NULL;
u64 mailbox_in_dma = 0;
u32 inmod = 0;
int i, err;

if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
return -EOPNOTSUPP;

mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
if (IS_ERR(mailbox_out))
return -ENOMEM;

hw_qcn_stats =
(struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *)
mailbox_out->buf;

for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
inmod = priv->port | ((1 << i) << 8) |
(MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,
mailbox_out->dma, inmod,
MLX4_CONGESTION_CONTROL_GET_STATISTICS,
MLX4_CMD_CONGESTION_CTRL_OPCODE,
MLX4_CMD_TIME_CLASS_C,
MLX4_CMD_NATIVE);
if (err) {
mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
return err;
}
qcn_stats->rppp_rp_centiseconds[i] =
be64_to_cpu(hw_qcn_stats->rppp_rp_centiseconds);
qcn_stats->rppp_created_rps[i] =
be32_to_cpu(hw_qcn_stats->rppp_created_rps);
}
mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
return 0;
}

const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {
.ieee_getets = mlx4_en_dcbnl_ieee_getets,
.ieee_setets = mlx4_en_dcbnl_ieee_setets,
Expand All @@ -252,6 +467,9 @@ const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {

.getdcbx = mlx4_en_dcbnl_getdcbx,
.setdcbx = mlx4_en_dcbnl_setdcbx,
.ieee_getqcn = mlx4_en_dcbnl_ieee_getqcn,
.ieee_setqcn = mlx4_en_dcbnl_ieee_setqcn,
.ieee_getqcnstats = mlx4_en_dcbnl_ieee_getqcnstats,
};

const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops = {
Expand Down
13 changes: 11 additions & 2 deletions drivers/net/ethernet/mellanox/mlx4/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
[18] = "More than 80 VFs support",
[19] = "Performance optimized for limited rule configuration flow steering support",
[20] = "Recoverable error events support",
[21] = "Port Remap support"
[21] = "Port Remap support",
[22] = "QCN support"
};
int i;

Expand Down Expand Up @@ -675,7 +676,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
#define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE 0x7a
#define QUERY_DEV_CAP_ETH_PROT_CTRL_OFFSET 0x7a
#define QUERY_DEV_CAP_ECN_QCN_VER_OFFSET 0x7b
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
Expand Down Expand Up @@ -777,6 +778,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB;
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
dev_cap->fs_max_num_qp_per_entry = field;
MLX4_GET(field, outbox, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
if (field & 0x1)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QCN;
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
Expand Down Expand Up @@ -1149,6 +1153,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
DEV_CAP_EXT_2_FLAG_FSM);
MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);

/* turn off QCN for guests */
MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
field &= 0xfe;
MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ struct mlx4_en_priv {
#ifdef CONFIG_MLX4_EN_DCB
struct ieee_ets ets;
u16 maxrate[IEEE_8021QAZ_MAX_TCS];
enum dcbnl_cndd_states cndd_state[IEEE_8021QAZ_MAX_TCS];
#endif
#ifdef CONFIG_RFS_ACCEL
spinlock_t filters_lock;
Expand Down
13 changes: 13 additions & 0 deletions include/linux/mlx4/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ enum {
MLX4_QP_FLOW_STEERING_ATTACH = 0x65,
MLX4_QP_FLOW_STEERING_DETACH = 0x66,
MLX4_FLOW_STEERING_IB_UC_QP_RANGE = 0x64,

/* Update and read QCN parameters */
MLX4_CMD_CONGESTION_CTRL_OPCODE = 0x68,
};

enum {
Expand Down Expand Up @@ -233,6 +236,16 @@ struct mlx4_config_dev_params {
u8 rx_csum_flags_port_2;
};

enum mlx4_en_congestion_control_algorithm {
MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT = 0,
};

enum mlx4_en_congestion_control_opmod {
MLX4_CONGESTION_CONTROL_GET_PARAMS,
MLX4_CONGESTION_CONTROL_GET_STATISTICS,
MLX4_CONGESTION_CONTROL_SET_PARAMS = 4,
};

struct mlx4_dev;

struct mlx4_cmd_mailbox {
Expand Down
3 changes: 2 additions & 1 deletion include/linux/mlx4/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ enum {
MLX4_DEV_CAP_FLAG2_80_VFS = 1LL << 18,
MLX4_DEV_CAP_FLAG2_FS_A0 = 1LL << 19,
MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT = 1LL << 20,
MLX4_DEV_CAP_FLAG2_PORT_REMAP = 1LL << 21
MLX4_DEV_CAP_FLAG2_PORT_REMAP = 1LL << 21,
MLX4_DEV_CAP_FLAG2_QCN = 1LL << 22,
};

enum {
Expand Down
3 changes: 3 additions & 0 deletions include/net/dcbnl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ struct dcbnl_rtnl_ops {
int (*ieee_setets) (struct net_device *, struct ieee_ets *);
int (*ieee_getmaxrate) (struct net_device *, struct ieee_maxrate *);
int (*ieee_setmaxrate) (struct net_device *, struct ieee_maxrate *);
int (*ieee_getqcn) (struct net_device *, struct ieee_qcn *);
int (*ieee_setqcn) (struct net_device *, struct ieee_qcn *);
int (*ieee_getqcnstats) (struct net_device *, struct ieee_qcn_stats *);
int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_getapp) (struct net_device *, struct dcb_app *);
Expand Down
Loading

0 comments on commit f68a8eb

Please sign in to comment.