|
@@ -226,14 +226,14 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
|
|
|
mlx5e_update_sw_counters(priv);
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_update_stats_work(struct work_struct *work)
|
|
|
+void mlx5e_update_stats_work(struct work_struct *work)
|
|
|
{
|
|
|
struct delayed_work *dwork = to_delayed_work(work);
|
|
|
struct mlx5e_priv *priv = container_of(dwork, struct mlx5e_priv,
|
|
|
update_stats_work);
|
|
|
mutex_lock(&priv->state_lock);
|
|
|
if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
|
|
|
- mlx5e_update_stats(priv);
|
|
|
+ priv->profile->update_stats(priv);
|
|
|
queue_delayed_work(priv->wq, dwork,
|
|
|
msecs_to_jiffies(MLX5E_UPDATE_STATS_INTERVAL));
|
|
|
}
|
|
@@ -858,7 +858,7 @@ static int mlx5e_create_cq(struct mlx5e_channel *c,
|
|
|
mcq->comp = mlx5e_completion_event;
|
|
|
mcq->event = mlx5e_cq_error_event;
|
|
|
mcq->irqn = irqn;
|
|
|
- mcq->uar = &priv->cq_uar;
|
|
|
+ mcq->uar = &mdev->mlx5e_res.cq_uar;
|
|
|
|
|
|
for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
|
|
|
struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
|
|
@@ -1036,7 +1036,7 @@ static void mlx5e_build_channeltc_to_txq_map(struct mlx5e_priv *priv, int ix)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < MLX5E_MAX_NUM_TC; i++)
|
|
|
+ for (i = 0; i < priv->profile->max_tc; i++)
|
|
|
priv->channeltc_to_txq_map[ix][i] =
|
|
|
ix + i * priv->params.num_channels;
|
|
|
}
|
|
@@ -1136,7 +1136,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
|
|
|
c->cpu = cpu;
|
|
|
c->pdev = &priv->mdev->pdev->dev;
|
|
|
c->netdev = priv->netdev;
|
|
|
- c->mkey_be = cpu_to_be32(priv->mkey.key);
|
|
|
+ c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key);
|
|
|
c->num_tc = priv->params.num_tc;
|
|
|
|
|
|
if (priv->params.rx_am_enabled)
|
|
@@ -1252,7 +1252,7 @@ static void mlx5e_build_rq_param(struct mlx5e_priv *priv,
|
|
|
MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN);
|
|
|
MLX5_SET(wq, wq, log_wq_stride, ilog2(sizeof(struct mlx5e_rx_wqe)));
|
|
|
MLX5_SET(wq, wq, log_wq_sz, priv->params.log_rq_size);
|
|
|
- MLX5_SET(wq, wq, pd, priv->pdn);
|
|
|
+ MLX5_SET(wq, wq, pd, priv->mdev->mlx5e_res.pdn);
|
|
|
MLX5_SET(rqc, rqc, counter_set_id, priv->q_counter);
|
|
|
|
|
|
param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev);
|
|
@@ -1277,7 +1277,7 @@ static void mlx5e_build_sq_param_common(struct mlx5e_priv *priv,
|
|
|
void *wq = MLX5_ADDR_OF(sqc, sqc, wq);
|
|
|
|
|
|
MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB));
|
|
|
- MLX5_SET(wq, wq, pd, priv->pdn);
|
|
|
+ MLX5_SET(wq, wq, pd, priv->mdev->mlx5e_res.pdn);
|
|
|
|
|
|
param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev);
|
|
|
}
|
|
@@ -1299,7 +1299,7 @@ static void mlx5e_build_common_cq_param(struct mlx5e_priv *priv,
|
|
|
{
|
|
|
void *cqc = param->cqc;
|
|
|
|
|
|
- MLX5_SET(cqc, cqc, uar_page, priv->cq_uar.index);
|
|
|
+ MLX5_SET(cqc, cqc, uar_page, priv->mdev->mlx5e_res.cq_uar.index);
|
|
|
}
|
|
|
|
|
|
static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv,
|
|
@@ -1486,7 +1486,8 @@ static void mlx5e_fill_direct_rqt_rqn(struct mlx5e_priv *priv, void *rqtc,
|
|
|
MLX5_SET(rqtc, rqtc, rq_num[0], rqn);
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_create_rqt(struct mlx5e_priv *priv, int sz, int ix, u32 *rqtn)
|
|
|
+static int mlx5e_create_rqt(struct mlx5e_priv *priv, int sz,
|
|
|
+ int ix, struct mlx5e_rqt *rqt)
|
|
|
{
|
|
|
struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
void *rqtc;
|
|
@@ -1509,34 +1510,36 @@ static int mlx5e_create_rqt(struct mlx5e_priv *priv, int sz, int ix, u32 *rqtn)
|
|
|
else
|
|
|
mlx5e_fill_direct_rqt_rqn(priv, rqtc, ix);
|
|
|
|
|
|
- err = mlx5_core_create_rqt(mdev, in, inlen, rqtn);
|
|
|
+ err = mlx5_core_create_rqt(mdev, in, inlen, &rqt->rqtn);
|
|
|
+ if (!err)
|
|
|
+ rqt->enabled = true;
|
|
|
|
|
|
kvfree(in);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_destroy_rqt(struct mlx5e_priv *priv, u32 rqtn)
|
|
|
+void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt)
|
|
|
{
|
|
|
- mlx5_core_destroy_rqt(priv->mdev, rqtn);
|
|
|
+ rqt->enabled = false;
|
|
|
+ mlx5_core_destroy_rqt(priv->mdev, rqt->rqtn);
|
|
|
+}
|
|
|
+
|
|
|
+static int mlx5e_create_indirect_rqts(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ struct mlx5e_rqt *rqt = &priv->indir_rqt;
|
|
|
+
|
|
|
+ return mlx5e_create_rqt(priv, MLX5E_INDIR_RQT_SIZE, 0, rqt);
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_create_rqts(struct mlx5e_priv *priv)
|
|
|
+int mlx5e_create_direct_rqts(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
- int nch = mlx5e_get_max_num_channels(priv->mdev);
|
|
|
- u32 *rqtn;
|
|
|
+ struct mlx5e_rqt *rqt;
|
|
|
int err;
|
|
|
int ix;
|
|
|
|
|
|
- /* Indirect RQT */
|
|
|
- rqtn = &priv->indir_rqtn;
|
|
|
- err = mlx5e_create_rqt(priv, MLX5E_INDIR_RQT_SIZE, 0, rqtn);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- /* Direct RQTs */
|
|
|
- for (ix = 0; ix < nch; ix++) {
|
|
|
- rqtn = &priv->direct_tir[ix].rqtn;
|
|
|
- err = mlx5e_create_rqt(priv, 1 /*size */, ix, rqtn);
|
|
|
+ for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
|
|
|
+ rqt = &priv->direct_tir[ix].rqt;
|
|
|
+ err = mlx5e_create_rqt(priv, 1 /*size */, ix, rqt);
|
|
|
if (err)
|
|
|
goto err_destroy_rqts;
|
|
|
}
|
|
@@ -1545,24 +1548,11 @@ static int mlx5e_create_rqts(struct mlx5e_priv *priv)
|
|
|
|
|
|
err_destroy_rqts:
|
|
|
for (ix--; ix >= 0; ix--)
|
|
|
- mlx5e_destroy_rqt(priv, priv->direct_tir[ix].rqtn);
|
|
|
-
|
|
|
- mlx5e_destroy_rqt(priv, priv->indir_rqtn);
|
|
|
+ mlx5e_destroy_rqt(priv, &priv->direct_tir[ix].rqt);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_destroy_rqts(struct mlx5e_priv *priv)
|
|
|
-{
|
|
|
- int nch = mlx5e_get_max_num_channels(priv->mdev);
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < nch; i++)
|
|
|
- mlx5e_destroy_rqt(priv, priv->direct_tir[i].rqtn);
|
|
|
-
|
|
|
- mlx5e_destroy_rqt(priv, priv->indir_rqtn);
|
|
|
-}
|
|
|
-
|
|
|
int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz, int ix)
|
|
|
{
|
|
|
struct mlx5_core_dev *mdev = priv->mdev;
|
|
@@ -1598,10 +1588,15 @@ static void mlx5e_redirect_rqts(struct mlx5e_priv *priv)
|
|
|
u32 rqtn;
|
|
|
int ix;
|
|
|
|
|
|
- rqtn = priv->indir_rqtn;
|
|
|
- mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, 0);
|
|
|
+ if (priv->indir_rqt.enabled) {
|
|
|
+ rqtn = priv->indir_rqt.rqtn;
|
|
|
+ mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, 0);
|
|
|
+ }
|
|
|
+
|
|
|
for (ix = 0; ix < priv->params.num_channels; ix++) {
|
|
|
- rqtn = priv->direct_tir[ix].rqtn;
|
|
|
+ if (!priv->direct_tir[ix].rqt.enabled)
|
|
|
+ continue;
|
|
|
+ rqtn = priv->direct_tir[ix].rqt.rqtn;
|
|
|
mlx5e_redirect_rqt(priv, rqtn, 1, ix);
|
|
|
}
|
|
|
}
|
|
@@ -1661,13 +1656,13 @@ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
|
|
|
mlx5e_build_tir_ctx_lro(tirc, priv);
|
|
|
|
|
|
for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
|
|
|
- err = mlx5_core_modify_tir(mdev, priv->indir_tirn[tt], in,
|
|
|
+ err = mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in,
|
|
|
inlen);
|
|
|
if (err)
|
|
|
goto free_in;
|
|
|
}
|
|
|
|
|
|
- for (ix = 0; ix < mlx5e_get_max_num_channels(mdev); ix++) {
|
|
|
+ for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
|
|
|
err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
|
|
|
in, inlen);
|
|
|
if (err)
|
|
@@ -1680,40 +1675,6 @@ free_in:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5e_priv *priv)
|
|
|
-{
|
|
|
- void *in;
|
|
|
- int inlen;
|
|
|
- int err;
|
|
|
- int i;
|
|
|
-
|
|
|
- inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
|
|
|
- in = mlx5_vzalloc(inlen);
|
|
|
- if (!in)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
|
|
|
-
|
|
|
- for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++) {
|
|
|
- err = mlx5_core_modify_tir(priv->mdev, priv->indir_tirn[i], in,
|
|
|
- inlen);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < priv->params.num_channels; i++) {
|
|
|
- err = mlx5_core_modify_tir(priv->mdev,
|
|
|
- priv->direct_tir[i].tirn, in,
|
|
|
- inlen);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- kvfree(in);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int mlx5e_set_mtu(struct mlx5e_priv *priv, u16 mtu)
|
|
|
{
|
|
|
struct mlx5_core_dev *mdev = priv->mdev;
|
|
@@ -1782,6 +1743,7 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev)
|
|
|
int mlx5e_open_locked(struct net_device *netdev)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
+ struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
int num_txqs;
|
|
|
int err;
|
|
|
|
|
@@ -1804,7 +1766,7 @@ int mlx5e_open_locked(struct net_device *netdev)
|
|
|
goto err_clear_state_opened_flag;
|
|
|
}
|
|
|
|
|
|
- err = mlx5e_refresh_tirs_self_loopback_enable(priv);
|
|
|
+ err = mlx5e_refresh_tirs_self_loopback_enable(priv->mdev);
|
|
|
if (err) {
|
|
|
netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
|
|
|
__func__, err);
|
|
@@ -1817,9 +1779,14 @@ int mlx5e_open_locked(struct net_device *netdev)
|
|
|
#ifdef CONFIG_RFS_ACCEL
|
|
|
priv->netdev->rx_cpu_rmap = priv->mdev->rmap;
|
|
|
#endif
|
|
|
+ if (priv->profile->update_stats)
|
|
|
+ queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
|
|
|
|
|
|
- queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
|
|
|
-
|
|
|
+ if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
|
|
|
+ err = mlx5e_add_sqs_fwd_rules(priv);
|
|
|
+ if (err)
|
|
|
+ goto err_close_channels;
|
|
|
+ }
|
|
|
return 0;
|
|
|
|
|
|
err_close_channels:
|
|
@@ -1829,7 +1796,7 @@ err_clear_state_opened_flag:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_open(struct net_device *netdev)
|
|
|
+int mlx5e_open(struct net_device *netdev)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
int err;
|
|
@@ -1844,6 +1811,7 @@ static int mlx5e_open(struct net_device *netdev)
|
|
|
int mlx5e_close_locked(struct net_device *netdev)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
+ struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
|
|
|
/* May already be CLOSED in case a previous configuration operation
|
|
|
* (e.g RX/TX queue size change) that involves close&open failed.
|
|
@@ -1853,6 +1821,9 @@ int mlx5e_close_locked(struct net_device *netdev)
|
|
|
|
|
|
clear_bit(MLX5E_STATE_OPENED, &priv->state);
|
|
|
|
|
|
+ if (MLX5_CAP_GEN(mdev, vport_group_manager))
|
|
|
+ mlx5e_remove_sqs_fwd_rules(priv);
|
|
|
+
|
|
|
mlx5e_timestamp_cleanup(priv);
|
|
|
netif_carrier_off(priv->netdev);
|
|
|
mlx5e_redirect_rqts(priv);
|
|
@@ -1861,7 +1832,7 @@ int mlx5e_close_locked(struct net_device *netdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_close(struct net_device *netdev)
|
|
|
+int mlx5e_close(struct net_device *netdev)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
int err;
|
|
@@ -1920,7 +1891,7 @@ static int mlx5e_create_drop_cq(struct mlx5e_priv *priv,
|
|
|
mcq->comp = mlx5e_completion_event;
|
|
|
mcq->event = mlx5e_cq_error_event;
|
|
|
mcq->irqn = irqn;
|
|
|
- mcq->uar = &priv->cq_uar;
|
|
|
+ mcq->uar = &mdev->mlx5e_res.cq_uar;
|
|
|
|
|
|
cq->priv = priv;
|
|
|
|
|
@@ -1986,7 +1957,7 @@ static int mlx5e_create_tis(struct mlx5e_priv *priv, int tc)
|
|
|
memset(in, 0, sizeof(in));
|
|
|
|
|
|
MLX5_SET(tisc, tisc, prio, tc << 1);
|
|
|
- MLX5_SET(tisc, tisc, transport_domain, priv->tdn);
|
|
|
+ MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.td.tdn);
|
|
|
|
|
|
return mlx5_core_create_tis(mdev, in, sizeof(in), &priv->tisn[tc]);
|
|
|
}
|
|
@@ -1996,12 +1967,12 @@ static void mlx5e_destroy_tis(struct mlx5e_priv *priv, int tc)
|
|
|
mlx5_core_destroy_tis(priv->mdev, priv->tisn[tc]);
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_create_tises(struct mlx5e_priv *priv)
|
|
|
+int mlx5e_create_tises(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
int err;
|
|
|
int tc;
|
|
|
|
|
|
- for (tc = 0; tc < MLX5E_MAX_NUM_TC; tc++) {
|
|
|
+ for (tc = 0; tc < priv->profile->max_tc; tc++) {
|
|
|
err = mlx5e_create_tis(priv, tc);
|
|
|
if (err)
|
|
|
goto err_close_tises;
|
|
@@ -2016,11 +1987,11 @@ err_close_tises:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_destroy_tises(struct mlx5e_priv *priv)
|
|
|
+void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
int tc;
|
|
|
|
|
|
- for (tc = 0; tc < MLX5E_MAX_NUM_TC; tc++)
|
|
|
+ for (tc = 0; tc < priv->profile->max_tc; tc++)
|
|
|
mlx5e_destroy_tis(priv, tc);
|
|
|
}
|
|
|
|
|
@@ -2029,7 +2000,7 @@ static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
|
|
{
|
|
|
void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
|
|
|
|
|
|
- MLX5_SET(tirc, tirc, transport_domain, priv->tdn);
|
|
|
+ MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
|
|
|
|
|
|
#define MLX5_HASH_IP (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
|
|
MLX5_HASH_FIELD_SEL_DST_IP)
|
|
@@ -2046,7 +2017,7 @@ static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
|
|
mlx5e_build_tir_ctx_lro(tirc, priv);
|
|
|
|
|
|
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
|
|
|
- MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqtn);
|
|
|
+ MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
|
|
|
mlx5e_build_tir_ctx_hash(tirc, priv);
|
|
|
|
|
|
switch (tt) {
|
|
@@ -2136,7 +2107,7 @@ static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
|
|
static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
|
|
u32 rqtn)
|
|
|
{
|
|
|
- MLX5_SET(tirc, tirc, transport_domain, priv->tdn);
|
|
|
+ MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
|
|
|
|
|
|
mlx5e_build_tir_ctx_lro(tirc, priv);
|
|
|
|
|
@@ -2145,15 +2116,13 @@ static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
|
|
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
|
|
|
}
|
|
|
|
|
|
-static int mlx5e_create_tirs(struct mlx5e_priv *priv)
|
|
|
+static int mlx5e_create_indirect_tirs(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
- int nch = mlx5e_get_max_num_channels(priv->mdev);
|
|
|
+ struct mlx5e_tir *tir;
|
|
|
void *tirc;
|
|
|
int inlen;
|
|
|
- u32 *tirn;
|
|
|
int err;
|
|
|
u32 *in;
|
|
|
- int ix;
|
|
|
int tt;
|
|
|
|
|
|
inlen = MLX5_ST_SZ_BYTES(create_tir_in);
|
|
@@ -2161,25 +2130,51 @@ static int mlx5e_create_tirs(struct mlx5e_priv *priv)
|
|
|
if (!in)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- /* indirect tirs */
|
|
|
for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
|
|
|
memset(in, 0, inlen);
|
|
|
- tirn = &priv->indir_tirn[tt];
|
|
|
+ tir = &priv->indir_tir[tt];
|
|
|
tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
|
|
|
mlx5e_build_indir_tir_ctx(priv, tirc, tt);
|
|
|
- err = mlx5_core_create_tir(priv->mdev, in, inlen, tirn);
|
|
|
+ err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
|
|
|
if (err)
|
|
|
goto err_destroy_tirs;
|
|
|
}
|
|
|
|
|
|
- /* direct tirs */
|
|
|
+ kvfree(in);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_destroy_tirs:
|
|
|
+ for (tt--; tt >= 0; tt--)
|
|
|
+ mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[tt]);
|
|
|
+
|
|
|
+ kvfree(in);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+int mlx5e_create_direct_tirs(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ int nch = priv->profile->max_nch(priv->mdev);
|
|
|
+ struct mlx5e_tir *tir;
|
|
|
+ void *tirc;
|
|
|
+ int inlen;
|
|
|
+ int err;
|
|
|
+ u32 *in;
|
|
|
+ int ix;
|
|
|
+
|
|
|
+ inlen = MLX5_ST_SZ_BYTES(create_tir_in);
|
|
|
+ in = mlx5_vzalloc(inlen);
|
|
|
+ if (!in)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
for (ix = 0; ix < nch; ix++) {
|
|
|
memset(in, 0, inlen);
|
|
|
- tirn = &priv->direct_tir[ix].tirn;
|
|
|
+ tir = &priv->direct_tir[ix];
|
|
|
tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
|
|
|
mlx5e_build_direct_tir_ctx(priv, tirc,
|
|
|
- priv->direct_tir[ix].rqtn);
|
|
|
- err = mlx5_core_create_tir(priv->mdev, in, inlen, tirn);
|
|
|
+ priv->direct_tir[ix].rqt.rqtn);
|
|
|
+ err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
|
|
|
if (err)
|
|
|
goto err_destroy_ch_tirs;
|
|
|
}
|
|
@@ -2190,27 +2185,28 @@ static int mlx5e_create_tirs(struct mlx5e_priv *priv)
|
|
|
|
|
|
err_destroy_ch_tirs:
|
|
|
for (ix--; ix >= 0; ix--)
|
|
|
- mlx5_core_destroy_tir(priv->mdev, priv->direct_tir[ix].tirn);
|
|
|
-
|
|
|
-err_destroy_tirs:
|
|
|
- for (tt--; tt >= 0; tt--)
|
|
|
- mlx5_core_destroy_tir(priv->mdev, priv->indir_tirn[tt]);
|
|
|
+ mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[ix]);
|
|
|
|
|
|
kvfree(in);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_destroy_tirs(struct mlx5e_priv *priv)
|
|
|
+static void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
- int nch = mlx5e_get_max_num_channels(priv->mdev);
|
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < nch; i++)
|
|
|
- mlx5_core_destroy_tir(priv->mdev, priv->direct_tir[i].tirn);
|
|
|
-
|
|
|
for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
|
|
|
- mlx5_core_destroy_tir(priv->mdev, priv->indir_tirn[i]);
|
|
|
+ mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[i]);
|
|
|
+}
|
|
|
+
|
|
|
+void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ int nch = priv->profile->max_nch(priv->mdev);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < nch; i++)
|
|
|
+ mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[i]);
|
|
|
}
|
|
|
|
|
|
int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd)
|
|
@@ -2284,7 +2280,7 @@ mqprio:
|
|
|
return mlx5e_setup_tc(dev, tc->tc);
|
|
|
}
|
|
|
|
|
|
-static struct rtnl_link_stats64 *
|
|
|
+struct rtnl_link_stats64 *
|
|
|
mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(dev);
|
|
@@ -2892,9 +2888,10 @@ void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params, u8 cq_period_mode)
|
|
|
MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC_FROM_CQE;
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
|
|
|
- struct net_device *netdev,
|
|
|
- int num_channels)
|
|
|
+static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
|
|
|
+ struct net_device *netdev,
|
|
|
+ const struct mlx5e_profile *profile,
|
|
|
+ void *ppriv)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
u32 link_speed = 0;
|
|
@@ -2963,7 +2960,7 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
|
|
|
sizeof(priv->params.toeplitz_hash_key));
|
|
|
|
|
|
mlx5e_build_default_indir_rqt(mdev, priv->params.indirection_rqt,
|
|
|
- MLX5E_INDIR_RQT_SIZE, num_channels);
|
|
|
+ MLX5E_INDIR_RQT_SIZE, profile->max_nch(mdev));
|
|
|
|
|
|
priv->params.lro_wqe_sz =
|
|
|
MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
|
|
@@ -2974,7 +2971,9 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
|
|
|
|
|
|
priv->mdev = mdev;
|
|
|
priv->netdev = netdev;
|
|
|
- priv->params.num_channels = num_channels;
|
|
|
+ priv->params.num_channels = profile->max_nch(mdev);
|
|
|
+ priv->profile = profile;
|
|
|
+ priv->ppriv = ppriv;
|
|
|
|
|
|
#ifdef CONFIG_MLX5_CORE_EN_DCB
|
|
|
mlx5e_ets_init(priv);
|
|
@@ -2999,7 +2998,11 @@ static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_build_netdev(struct net_device *netdev)
|
|
|
+static const struct switchdev_ops mlx5e_switchdev_ops = {
|
|
|
+ .switchdev_port_attr_get = mlx5e_attr_get,
|
|
|
+};
|
|
|
+
|
|
|
+static void mlx5e_build_nic_netdev(struct net_device *netdev)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
struct mlx5_core_dev *mdev = priv->mdev;
|
|
@@ -3080,31 +3083,11 @@ static void mlx5e_build_netdev(struct net_device *netdev)
|
|
|
netdev->priv_flags |= IFF_UNICAST_FLT;
|
|
|
|
|
|
mlx5e_set_netdev_dev_addr(netdev);
|
|
|
-}
|
|
|
-
|
|
|
-static int mlx5e_create_mkey(struct mlx5e_priv *priv, u32 pdn,
|
|
|
- struct mlx5_core_mkey *mkey)
|
|
|
-{
|
|
|
- struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
- struct mlx5_create_mkey_mbox_in *in;
|
|
|
- int err;
|
|
|
-
|
|
|
- in = mlx5_vzalloc(sizeof(*in));
|
|
|
- if (!in)
|
|
|
- return -ENOMEM;
|
|
|
|
|
|
- in->seg.flags = MLX5_PERM_LOCAL_WRITE |
|
|
|
- MLX5_PERM_LOCAL_READ |
|
|
|
- MLX5_ACCESS_MODE_PA;
|
|
|
- in->seg.flags_pd = cpu_to_be32(pdn | MLX5_MKEY_LEN64);
|
|
|
- in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
|
|
|
-
|
|
|
- err = mlx5_core_create_mkey(mdev, mkey, in, sizeof(*in), NULL, NULL,
|
|
|
- NULL);
|
|
|
-
|
|
|
- kvfree(in);
|
|
|
-
|
|
|
- return err;
|
|
|
+#ifdef CONFIG_NET_SWITCHDEV
|
|
|
+ if (MLX5_CAP_GEN(mdev, vport_group_manager))
|
|
|
+ netdev->switchdev_ops = &mlx5e_switchdev_ops;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
static void mlx5e_create_q_counter(struct mlx5e_priv *priv)
|
|
@@ -3134,7 +3117,7 @@ static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv)
|
|
|
struct mlx5_mkey_seg *mkc;
|
|
|
int inlen = sizeof(*in);
|
|
|
u64 npages =
|
|
|
- mlx5e_get_max_num_channels(mdev) * MLX5_CHANNEL_MAX_NUM_MTTS;
|
|
|
+ priv->profile->max_nch(mdev) * MLX5_CHANNEL_MAX_NUM_MTTS;
|
|
|
int err;
|
|
|
|
|
|
in = mlx5_vzalloc(inlen);
|
|
@@ -3149,7 +3132,7 @@ static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv)
|
|
|
MLX5_ACCESS_MODE_MTT;
|
|
|
|
|
|
mkc->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
|
|
|
- mkc->flags_pd = cpu_to_be32(priv->pdn);
|
|
|
+ mkc->flags_pd = cpu_to_be32(mdev->mlx5e_res.pdn);
|
|
|
mkc->len = cpu_to_be64(npages << PAGE_SHIFT);
|
|
|
mkc->xlt_oct_size = cpu_to_be32(mlx5e_get_mtt_octw(npages));
|
|
|
mkc->log2_page_size = PAGE_SHIFT;
|
|
@@ -3162,160 +3145,233 @@ static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
|
|
|
+static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
|
|
|
+ struct net_device *netdev,
|
|
|
+ const struct mlx5e_profile *profile,
|
|
|
+ void *ppriv)
|
|
|
{
|
|
|
- struct net_device *netdev;
|
|
|
- struct mlx5e_priv *priv;
|
|
|
- int nch = mlx5e_get_max_num_channels(mdev);
|
|
|
- int err;
|
|
|
-
|
|
|
- if (mlx5e_check_required_hca_cap(mdev))
|
|
|
- return NULL;
|
|
|
+ struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
|
|
|
- netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
|
|
|
- nch * MLX5E_MAX_NUM_TC,
|
|
|
- nch);
|
|
|
- if (!netdev) {
|
|
|
- mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ mlx5e_build_nic_netdev_priv(mdev, netdev, profile, ppriv);
|
|
|
+ mlx5e_build_nic_netdev(netdev);
|
|
|
+ mlx5e_vxlan_init(priv);
|
|
|
+}
|
|
|
|
|
|
- mlx5e_build_netdev_priv(mdev, netdev, nch);
|
|
|
- mlx5e_build_netdev(netdev);
|
|
|
+static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
|
|
|
|
|
- netif_carrier_off(netdev);
|
|
|
+ mlx5e_vxlan_cleanup(priv);
|
|
|
|
|
|
- priv = netdev_priv(netdev);
|
|
|
+ if (MLX5_CAP_GEN(mdev, vport_group_manager))
|
|
|
+ mlx5_eswitch_unregister_vport_rep(esw, 0);
|
|
|
+}
|
|
|
|
|
|
- priv->wq = create_singlethread_workqueue("mlx5e");
|
|
|
- if (!priv->wq)
|
|
|
- goto err_free_netdev;
|
|
|
+static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
+ int err;
|
|
|
+ int i;
|
|
|
|
|
|
- err = mlx5_alloc_map_uar(mdev, &priv->cq_uar, false);
|
|
|
+ err = mlx5e_create_indirect_rqts(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_err(mdev, "alloc_map uar failed, %d\n", err);
|
|
|
- goto err_destroy_wq;
|
|
|
+ mlx5_core_warn(mdev, "create indirect rqts failed, %d\n", err);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
- err = mlx5_core_alloc_pd(mdev, &priv->pdn);
|
|
|
+ err = mlx5e_create_direct_rqts(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_err(mdev, "alloc pd failed, %d\n", err);
|
|
|
- goto err_unmap_free_uar;
|
|
|
+ mlx5_core_warn(mdev, "create direct rqts failed, %d\n", err);
|
|
|
+ goto err_destroy_indirect_rqts;
|
|
|
}
|
|
|
|
|
|
- err = mlx5_core_alloc_transport_domain(mdev, &priv->tdn);
|
|
|
+ err = mlx5e_create_indirect_tirs(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_err(mdev, "alloc td failed, %d\n", err);
|
|
|
- goto err_dealloc_pd;
|
|
|
+ mlx5_core_warn(mdev, "create indirect tirs failed, %d\n", err);
|
|
|
+ goto err_destroy_direct_rqts;
|
|
|
}
|
|
|
|
|
|
- err = mlx5e_create_mkey(priv, priv->pdn, &priv->mkey);
|
|
|
+ err = mlx5e_create_direct_tirs(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_err(mdev, "create mkey failed, %d\n", err);
|
|
|
- goto err_dealloc_transport_domain;
|
|
|
+ mlx5_core_warn(mdev, "create direct tirs failed, %d\n", err);
|
|
|
+ goto err_destroy_indirect_tirs;
|
|
|
}
|
|
|
|
|
|
- err = mlx5e_create_umr_mkey(priv);
|
|
|
+ err = mlx5e_create_flow_steering(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_err(mdev, "create umr mkey failed, %d\n", err);
|
|
|
- goto err_destroy_mkey;
|
|
|
+ mlx5_core_warn(mdev, "create flow steering failed, %d\n", err);
|
|
|
+ goto err_destroy_direct_tirs;
|
|
|
}
|
|
|
|
|
|
+ err = mlx5e_tc_init(priv);
|
|
|
+ if (err)
|
|
|
+ goto err_destroy_flow_steering;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_destroy_flow_steering:
|
|
|
+ mlx5e_destroy_flow_steering(priv);
|
|
|
+err_destroy_direct_tirs:
|
|
|
+ mlx5e_destroy_direct_tirs(priv);
|
|
|
+err_destroy_indirect_tirs:
|
|
|
+ mlx5e_destroy_indirect_tirs(priv);
|
|
|
+err_destroy_direct_rqts:
|
|
|
+ for (i = 0; i < priv->profile->max_nch(mdev); i++)
|
|
|
+ mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
|
|
|
+err_destroy_indirect_rqts:
|
|
|
+ mlx5e_destroy_rqt(priv, &priv->indir_rqt);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ mlx5e_tc_cleanup(priv);
|
|
|
+ mlx5e_destroy_flow_steering(priv);
|
|
|
+ mlx5e_destroy_direct_tirs(priv);
|
|
|
+ mlx5e_destroy_indirect_tirs(priv);
|
|
|
+ for (i = 0; i < priv->profile->max_nch(priv->mdev); i++)
|
|
|
+ mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
|
|
|
+ mlx5e_destroy_rqt(priv, &priv->indir_rqt);
|
|
|
+}
|
|
|
+
|
|
|
+static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
err = mlx5e_create_tises(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_warn(mdev, "create tises failed, %d\n", err);
|
|
|
- goto err_destroy_umr_mkey;
|
|
|
+ mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
- err = mlx5e_open_drop_rq(priv);
|
|
|
- if (err) {
|
|
|
- mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
|
|
|
- goto err_destroy_tises;
|
|
|
+#ifdef CONFIG_MLX5_CORE_EN_DCB
|
|
|
+ mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets);
|
|
|
+#endif
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void mlx5e_nic_enable(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ struct net_device *netdev = priv->netdev;
|
|
|
+ struct mlx5_core_dev *mdev = priv->mdev;
|
|
|
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
|
|
+ struct mlx5_eswitch_rep rep;
|
|
|
+
|
|
|
+ if (mlx5e_vxlan_allowed(mdev)) {
|
|
|
+ rtnl_lock();
|
|
|
+ udp_tunnel_get_rx_info(netdev);
|
|
|
+ rtnl_unlock();
|
|
|
}
|
|
|
|
|
|
- err = mlx5e_create_rqts(priv);
|
|
|
- if (err) {
|
|
|
- mlx5_core_warn(mdev, "create rqts failed, %d\n", err);
|
|
|
- goto err_close_drop_rq;
|
|
|
+ mlx5e_enable_async_events(priv);
|
|
|
+ queue_work(priv->wq, &priv->set_rx_mode_work);
|
|
|
+
|
|
|
+ if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
|
|
|
+ rep.load = mlx5e_nic_rep_load;
|
|
|
+ rep.unload = mlx5e_nic_rep_unload;
|
|
|
+ rep.vport = 0;
|
|
|
+ rep.priv_data = priv;
|
|
|
+ mlx5_eswitch_register_vport_rep(esw, &rep);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- err = mlx5e_create_tirs(priv);
|
|
|
- if (err) {
|
|
|
- mlx5_core_warn(mdev, "create tirs failed, %d\n", err);
|
|
|
- goto err_destroy_rqts;
|
|
|
+static void mlx5e_nic_disable(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ queue_work(priv->wq, &priv->set_rx_mode_work);
|
|
|
+ mlx5e_disable_async_events(priv);
|
|
|
+}
|
|
|
+
|
|
|
+static const struct mlx5e_profile mlx5e_nic_profile = {
|
|
|
+ .init = mlx5e_nic_init,
|
|
|
+ .cleanup = mlx5e_nic_cleanup,
|
|
|
+ .init_rx = mlx5e_init_nic_rx,
|
|
|
+ .cleanup_rx = mlx5e_cleanup_nic_rx,
|
|
|
+ .init_tx = mlx5e_init_nic_tx,
|
|
|
+ .cleanup_tx = mlx5e_cleanup_nic_tx,
|
|
|
+ .enable = mlx5e_nic_enable,
|
|
|
+ .disable = mlx5e_nic_disable,
|
|
|
+ .update_stats = mlx5e_update_stats,
|
|
|
+ .max_nch = mlx5e_get_max_num_channels,
|
|
|
+ .max_tc = MLX5E_MAX_NUM_TC,
|
|
|
+};
|
|
|
+
|
|
|
+void *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
|
|
|
+ const struct mlx5e_profile *profile, void *ppriv)
|
|
|
+{
|
|
|
+ struct net_device *netdev;
|
|
|
+ struct mlx5e_priv *priv;
|
|
|
+ int nch = profile->max_nch(mdev);
|
|
|
+ int err;
|
|
|
+
|
|
|
+ netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
|
|
|
+ nch * profile->max_tc,
|
|
|
+ nch);
|
|
|
+ if (!netdev) {
|
|
|
+ mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
- err = mlx5e_create_flow_steering(priv);
|
|
|
+ profile->init(mdev, netdev, profile, ppriv);
|
|
|
+
|
|
|
+ netif_carrier_off(netdev);
|
|
|
+
|
|
|
+ priv = netdev_priv(netdev);
|
|
|
+
|
|
|
+ priv->wq = create_singlethread_workqueue("mlx5e");
|
|
|
+ if (!priv->wq)
|
|
|
+ goto err_free_netdev;
|
|
|
+
|
|
|
+ err = mlx5e_create_umr_mkey(priv);
|
|
|
if (err) {
|
|
|
- mlx5_core_warn(mdev, "create flow steering failed, %d\n", err);
|
|
|
- goto err_destroy_tirs;
|
|
|
+ mlx5_core_err(mdev, "create umr mkey failed, %d\n", err);
|
|
|
+ goto err_destroy_wq;
|
|
|
}
|
|
|
|
|
|
- mlx5e_create_q_counter(priv);
|
|
|
-
|
|
|
- mlx5e_init_l2_addr(priv);
|
|
|
+ err = profile->init_tx(priv);
|
|
|
+ if (err)
|
|
|
+ goto err_destroy_umr_mkey;
|
|
|
|
|
|
- mlx5e_vxlan_init(priv);
|
|
|
+ err = mlx5e_open_drop_rq(priv);
|
|
|
+ if (err) {
|
|
|
+ mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
|
|
|
+ goto err_cleanup_tx;
|
|
|
+ }
|
|
|
|
|
|
- err = mlx5e_tc_init(priv);
|
|
|
+ err = profile->init_rx(priv);
|
|
|
if (err)
|
|
|
- goto err_dealloc_q_counters;
|
|
|
+ goto err_close_drop_rq;
|
|
|
|
|
|
-#ifdef CONFIG_MLX5_CORE_EN_DCB
|
|
|
- mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets);
|
|
|
-#endif
|
|
|
+ mlx5e_create_q_counter(priv);
|
|
|
+
|
|
|
+ mlx5e_init_l2_addr(priv);
|
|
|
|
|
|
err = register_netdev(netdev);
|
|
|
if (err) {
|
|
|
mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
|
|
|
- goto err_tc_cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- if (mlx5e_vxlan_allowed(mdev)) {
|
|
|
- rtnl_lock();
|
|
|
- udp_tunnel_get_rx_info(netdev);
|
|
|
- rtnl_unlock();
|
|
|
+ goto err_dealloc_q_counters;
|
|
|
}
|
|
|
|
|
|
- mlx5e_enable_async_events(priv);
|
|
|
- queue_work(priv->wq, &priv->set_rx_mode_work);
|
|
|
+ if (profile->enable)
|
|
|
+ profile->enable(priv);
|
|
|
|
|
|
return priv;
|
|
|
|
|
|
-err_tc_cleanup:
|
|
|
- mlx5e_tc_cleanup(priv);
|
|
|
-
|
|
|
err_dealloc_q_counters:
|
|
|
mlx5e_destroy_q_counter(priv);
|
|
|
- mlx5e_destroy_flow_steering(priv);
|
|
|
-
|
|
|
-err_destroy_tirs:
|
|
|
- mlx5e_destroy_tirs(priv);
|
|
|
-
|
|
|
-err_destroy_rqts:
|
|
|
- mlx5e_destroy_rqts(priv);
|
|
|
+ profile->cleanup_rx(priv);
|
|
|
|
|
|
err_close_drop_rq:
|
|
|
mlx5e_close_drop_rq(priv);
|
|
|
|
|
|
-err_destroy_tises:
|
|
|
- mlx5e_destroy_tises(priv);
|
|
|
+err_cleanup_tx:
|
|
|
+ profile->cleanup_tx(priv);
|
|
|
|
|
|
err_destroy_umr_mkey:
|
|
|
mlx5_core_destroy_mkey(mdev, &priv->umr_mkey);
|
|
|
|
|
|
-err_destroy_mkey:
|
|
|
- mlx5_core_destroy_mkey(mdev, &priv->mkey);
|
|
|
-
|
|
|
-err_dealloc_transport_domain:
|
|
|
- mlx5_core_dealloc_transport_domain(mdev, priv->tdn);
|
|
|
-
|
|
|
-err_dealloc_pd:
|
|
|
- mlx5_core_dealloc_pd(mdev, priv->pdn);
|
|
|
-
|
|
|
-err_unmap_free_uar:
|
|
|
- mlx5_unmap_free_uar(mdev, &priv->cq_uar);
|
|
|
-
|
|
|
err_destroy_wq:
|
|
|
destroy_workqueue(priv->wq);
|
|
|
|
|
@@ -3325,15 +3381,59 @@ err_free_netdev:
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
|
|
|
+static void mlx5e_register_vport_rep(struct mlx5_core_dev *mdev)
|
|
|
{
|
|
|
- struct mlx5e_priv *priv = vpriv;
|
|
|
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
|
|
+ int total_vfs = MLX5_TOTAL_VPORTS(mdev);
|
|
|
+ int vport;
|
|
|
+
|
|
|
+ if (!MLX5_CAP_GEN(mdev, vport_group_manager))
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (vport = 1; vport < total_vfs; vport++) {
|
|
|
+ struct mlx5_eswitch_rep rep;
|
|
|
+
|
|
|
+ rep.load = mlx5e_vport_rep_load;
|
|
|
+ rep.unload = mlx5e_vport_rep_unload;
|
|
|
+ rep.vport = vport;
|
|
|
+ mlx5_eswitch_register_vport_rep(esw, &rep);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void *mlx5e_add(struct mlx5_core_dev *mdev)
|
|
|
+{
|
|
|
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
|
|
+ void *ppriv = NULL;
|
|
|
+ void *ret;
|
|
|
+
|
|
|
+ if (mlx5e_check_required_hca_cap(mdev))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (mlx5e_create_mdev_resources(mdev))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ mlx5e_register_vport_rep(mdev);
|
|
|
+
|
|
|
+ if (MLX5_CAP_GEN(mdev, vport_group_manager))
|
|
|
+ ppriv = &esw->offloads.vport_reps[0];
|
|
|
+
|
|
|
+ ret = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, ppriv);
|
|
|
+ if (!ret) {
|
|
|
+ mlx5e_destroy_mdev_resources(mdev);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ const struct mlx5e_profile *profile = priv->profile;
|
|
|
struct net_device *netdev = priv->netdev;
|
|
|
|
|
|
set_bit(MLX5E_STATE_DESTROYING, &priv->state);
|
|
|
+ if (profile->disable)
|
|
|
+ profile->disable(priv);
|
|
|
|
|
|
- queue_work(priv->wq, &priv->set_rx_mode_work);
|
|
|
- mlx5e_disable_async_events(priv);
|
|
|
flush_workqueue(priv->wq);
|
|
|
if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) {
|
|
|
netif_device_detach(netdev);
|
|
@@ -3342,26 +3442,35 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
|
|
|
unregister_netdev(netdev);
|
|
|
}
|
|
|
|
|
|
- mlx5e_tc_cleanup(priv);
|
|
|
- mlx5e_vxlan_cleanup(priv);
|
|
|
mlx5e_destroy_q_counter(priv);
|
|
|
- mlx5e_destroy_flow_steering(priv);
|
|
|
- mlx5e_destroy_tirs(priv);
|
|
|
- mlx5e_destroy_rqts(priv);
|
|
|
+ profile->cleanup_rx(priv);
|
|
|
mlx5e_close_drop_rq(priv);
|
|
|
- mlx5e_destroy_tises(priv);
|
|
|
+ profile->cleanup_tx(priv);
|
|
|
mlx5_core_destroy_mkey(priv->mdev, &priv->umr_mkey);
|
|
|
- mlx5_core_destroy_mkey(priv->mdev, &priv->mkey);
|
|
|
- mlx5_core_dealloc_transport_domain(priv->mdev, priv->tdn);
|
|
|
- mlx5_core_dealloc_pd(priv->mdev, priv->pdn);
|
|
|
- mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar);
|
|
|
cancel_delayed_work_sync(&priv->update_stats_work);
|
|
|
destroy_workqueue(priv->wq);
|
|
|
+ if (profile->cleanup)
|
|
|
+ profile->cleanup(priv);
|
|
|
|
|
|
if (!test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state))
|
|
|
free_netdev(netdev);
|
|
|
}
|
|
|
|
|
|
+static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
|
|
|
+{
|
|
|
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
|
|
+ int total_vfs = MLX5_TOTAL_VPORTS(mdev);
|
|
|
+ struct mlx5e_priv *priv = vpriv;
|
|
|
+ int vport;
|
|
|
+
|
|
|
+ mlx5e_destroy_netdev(mdev, priv);
|
|
|
+
|
|
|
+ for (vport = 1; vport < total_vfs; vport++)
|
|
|
+ mlx5_eswitch_unregister_vport_rep(esw, vport);
|
|
|
+
|
|
|
+ mlx5e_destroy_mdev_resources(mdev);
|
|
|
+}
|
|
|
+
|
|
|
static void *mlx5e_get_netdev(void *vpriv)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = vpriv;
|
|
@@ -3370,8 +3479,8 @@ static void *mlx5e_get_netdev(void *vpriv)
|
|
|
}
|
|
|
|
|
|
static struct mlx5_interface mlx5e_interface = {
|
|
|
- .add = mlx5e_create_netdev,
|
|
|
- .remove = mlx5e_destroy_netdev,
|
|
|
+ .add = mlx5e_add,
|
|
|
+ .remove = mlx5e_remove,
|
|
|
.event = mlx5e_async_event,
|
|
|
.protocol = MLX5_INTERFACE_PROTOCOL_ETH,
|
|
|
.get_dev = mlx5e_get_netdev,
|