Skip to content

Commit

Permalink
Merge tag 'mlx5-updates-2018-10-18' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2018-10-18

This series provides misc updates to mlx5 core and netdevice driver.

1) From Tariq Toukan: Refactor fragmented buffer struct fields and init flow.

2) From Vlad Buslov, Flow counters cache improvements and fixes follow up.
as a follow up work for the previous series of the mlx5 flow counters,
Vlad provides two fixes:
  2.1) Take fs_counters dellist before addlist
Fixes: 6e5e228 ("net/mlx5: Add new list to store deleted flow counters")
  2.2) Remove counter from idr after removing it from list
Fixes: 12d6066 ("net/mlx5: Add flow counters idr")

From Shay Agroskin,
3) Add FEC set/get FW commands and FEC ethtool callbacks support
4) Add new ethtool statistics to cover errors on rx, such as FEC errors.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 19, 2018
2 parents 7986191 + 4cb4e98 commit 02e6dae
Show file tree
Hide file tree
Showing 10 changed files with 508 additions and 134 deletions.
31 changes: 13 additions & 18 deletions drivers/infiniband/hw/mlx5/cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,

static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf)
{
mlx5_frag_buf_free(dev->mdev, &buf->fbc.frag_buf);
mlx5_frag_buf_free(dev->mdev, &buf->frag_buf);
}

static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe,
Expand Down Expand Up @@ -728,23 +728,20 @@ static int alloc_cq_frag_buf(struct mlx5_ib_dev *dev,
int nent,
int cqe_size)
{
struct mlx5_frag_buf_ctrl *c = &buf->fbc;
struct mlx5_frag_buf *frag_buf = &c->frag_buf;
u32 cqc_buff[MLX5_ST_SZ_DW(cqc)] = {0};
struct mlx5_frag_buf *frag_buf = &buf->frag_buf;
u8 log_wq_stride = 6 + (cqe_size == 128 ? 1 : 0);
u8 log_wq_sz = ilog2(cqe_size);
int err;

MLX5_SET(cqc, cqc_buff, log_cq_size, ilog2(cqe_size));
MLX5_SET(cqc, cqc_buff, cqe_sz, (cqe_size == 128) ? 1 : 0);

mlx5_core_init_cq_frag_buf(&buf->fbc, cqc_buff);

err = mlx5_frag_buf_alloc_node(dev->mdev,
nent * cqe_size,
frag_buf,
dev->mdev->priv.numa_node);
if (err)
return err;

mlx5_init_fbc(frag_buf->frags, log_wq_stride, log_wq_sz, &buf->fbc);

buf->cqe_size = cqe_size;
buf->nent = nent;

Expand Down Expand Up @@ -934,19 +931,19 @@ static int create_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq,

*inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
MLX5_FLD_SZ_BYTES(create_cq_in, pas[0]) *
cq->buf.fbc.frag_buf.npages;
cq->buf.frag_buf.npages;
*cqb = kvzalloc(*inlen, GFP_KERNEL);
if (!*cqb) {
err = -ENOMEM;
goto err_buf;
}

pas = (__be64 *)MLX5_ADDR_OF(create_cq_in, *cqb, pas);
mlx5_fill_page_frag_array(&cq->buf.fbc.frag_buf, pas);
mlx5_fill_page_frag_array(&cq->buf.frag_buf, pas);

cqc = MLX5_ADDR_OF(create_cq_in, *cqb, cq_context);
MLX5_SET(cqc, cqc, log_page_size,
cq->buf.fbc.frag_buf.page_shift -
cq->buf.frag_buf.page_shift -
MLX5_ADAPTER_PAGE_SHIFT);

*index = dev->mdev->priv.uar->index;
Expand Down Expand Up @@ -1365,11 +1362,10 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
cqe_size = 64;
err = resize_kernel(dev, cq, entries, cqe_size);
if (!err) {
struct mlx5_frag_buf_ctrl *c;
struct mlx5_frag_buf *frag_buf = &cq->resize_buf->frag_buf;

c = &cq->resize_buf->fbc;
npas = c->frag_buf.npages;
page_shift = c->frag_buf.page_shift;
npas = frag_buf->npages;
page_shift = frag_buf->page_shift;
}
}

Expand All @@ -1390,8 +1386,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
mlx5_ib_populate_pas(dev, cq->resize_umem, page_shift,
pas, 0);
else
mlx5_fill_page_frag_array(&cq->resize_buf->fbc.frag_buf,
pas);
mlx5_fill_page_frag_array(&cq->resize_buf->frag_buf, pas);

MLX5_SET(modify_cq_in, in,
modify_field_select_resize_field_select.resize_field_select.resize_field_select,
Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/hw/mlx5/mlx5_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ struct mlx5_ib_qp {

struct mlx5_ib_cq_buf {
struct mlx5_frag_buf_ctrl fbc;
struct mlx5_frag_buf frag_buf;
struct ib_umem *umem;
int cqe_size;
int nent;
Expand Down
208 changes: 208 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,211 @@ int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
kfree(out);
return err;
}

static u32 fec_supported_speeds[] = {
10000,
40000,
25000,
50000,
56000,
100000
};

#define MLX5E_FEC_SUPPORTED_SPEEDS ARRAY_SIZE(fec_supported_speeds)

/* get/set FEC admin field for a given speed */
static int mlx5e_fec_admin_field(u32 *pplm,
u8 *fec_policy,
bool write,
u32 speed)
{
switch (speed) {
case 10000:
case 40000:
if (!write)
*fec_policy = MLX5_GET(pplm_reg, pplm,
fec_override_cap_10g_40g);
else
MLX5_SET(pplm_reg, pplm,
fec_override_admin_10g_40g, *fec_policy);
break;
case 25000:
if (!write)
*fec_policy = MLX5_GET(pplm_reg, pplm,
fec_override_admin_25g);
else
MLX5_SET(pplm_reg, pplm,
fec_override_admin_25g, *fec_policy);
break;
case 50000:
if (!write)
*fec_policy = MLX5_GET(pplm_reg, pplm,
fec_override_admin_50g);
else
MLX5_SET(pplm_reg, pplm,
fec_override_admin_50g, *fec_policy);
break;
case 56000:
if (!write)
*fec_policy = MLX5_GET(pplm_reg, pplm,
fec_override_admin_56g);
else
MLX5_SET(pplm_reg, pplm,
fec_override_admin_56g, *fec_policy);
break;
case 100000:
if (!write)
*fec_policy = MLX5_GET(pplm_reg, pplm,
fec_override_admin_100g);
else
MLX5_SET(pplm_reg, pplm,
fec_override_admin_100g, *fec_policy);
break;
default:
return -EINVAL;
}
return 0;
}

/* returns FEC capabilities for a given speed */
static int mlx5e_get_fec_cap_field(u32 *pplm,
u8 *fec_cap,
u32 speed)
{
switch (speed) {
case 10000:
case 40000:
*fec_cap = MLX5_GET(pplm_reg, pplm,
fec_override_admin_10g_40g);
break;
case 25000:
*fec_cap = MLX5_GET(pplm_reg, pplm,
fec_override_cap_25g);
break;
case 50000:
*fec_cap = MLX5_GET(pplm_reg, pplm,
fec_override_cap_50g);
break;
case 56000:
*fec_cap = MLX5_GET(pplm_reg, pplm,
fec_override_cap_56g);
break;
case 100000:
*fec_cap = MLX5_GET(pplm_reg, pplm,
fec_override_cap_100g);
break;
default:
return -EINVAL;
}
return 0;
}

int mlx5e_get_fec_caps(struct mlx5_core_dev *dev, u8 *fec_caps)
{
u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
u32 current_fec_speed;
int err;

if (!MLX5_CAP_GEN(dev, pcam_reg))
return -EOPNOTSUPP;

if (!MLX5_CAP_PCAM_REG(dev, pplm))
return -EOPNOTSUPP;

MLX5_SET(pplm_reg, in, local_port, 1);
err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
if (err)
return err;

err = mlx5e_port_linkspeed(dev, &current_fec_speed);
if (err)
return err;

return mlx5e_get_fec_cap_field(out, fec_caps, current_fec_speed);
}

int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
u8 *fec_configured_mode)
{
u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
u32 link_speed;
int err;

if (!MLX5_CAP_GEN(dev, pcam_reg))
return -EOPNOTSUPP;

if (!MLX5_CAP_PCAM_REG(dev, pplm))
return -EOPNOTSUPP;

MLX5_SET(pplm_reg, in, local_port, 1);
err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
if (err)
return err;

*fec_mode_active = MLX5_GET(pplm_reg, out, fec_mode_active);

if (!fec_configured_mode)
return 0;

err = mlx5e_port_linkspeed(dev, &link_speed);
if (err)
return err;

return mlx5e_fec_admin_field(out, fec_configured_mode, 0, link_speed);
}

int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)
{
bool fec_mode_not_supp_in_speed = false;
u8 no_fec_policy = BIT(MLX5E_FEC_NOFEC);
u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
u32 current_fec_speed;
u8 fec_caps = 0;
int err;
int i;

if (!MLX5_CAP_GEN(dev, pcam_reg))
return -EOPNOTSUPP;

if (!MLX5_CAP_PCAM_REG(dev, pplm))
return -EOPNOTSUPP;

MLX5_SET(pplm_reg, in, local_port, 1);
err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
if (err)
return err;

err = mlx5e_port_linkspeed(dev, &current_fec_speed);
if (err)
return err;

memset(in, 0, sz);
MLX5_SET(pplm_reg, in, local_port, 1);
for (i = 0; i < MLX5E_FEC_SUPPORTED_SPEEDS && !!fec_policy; i++) {
mlx5e_get_fec_cap_field(out, &fec_caps, fec_supported_speeds[i]);
/* policy supported for link speed */
if (!!(fec_caps & fec_policy)) {
mlx5e_fec_admin_field(in, &fec_policy, 1,
fec_supported_speeds[i]);
} else {
if (fec_supported_speeds[i] == current_fec_speed)
return -EOPNOTSUPP;
mlx5e_fec_admin_field(in, &no_fec_policy, 1,
fec_supported_speeds[i]);
fec_mode_not_supp_in_speed = true;
}
}

if (fec_mode_not_supp_in_speed)
mlx5_core_dbg(dev,
"FEC policy 0x%x is not supported for some speeds",
fec_policy);

return mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
}
12 changes: 12 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,16 @@ int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);

int mlx5e_get_fec_caps(struct mlx5_core_dev *dev, u8 *fec_caps);
int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
u8 *fec_configured_mode);
int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy);

enum {
MLX5E_FEC_NOFEC,
MLX5E_FEC_FIRECODE,
MLX5E_FEC_RS_528_514,
};

#endif
Loading

0 comments on commit 02e6dae

Please sign in to comment.