|
@@ -272,10 +272,9 @@ static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv)
|
|
|
mlx5e_stats_grps[i].update_stats(priv);
|
|
|
}
|
|
|
|
|
|
-void mlx5e_update_stats_work(struct work_struct *work)
|
|
|
+static 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,
|
|
|
+ struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
|
|
|
update_stats_work);
|
|
|
|
|
|
mutex_lock(&priv->state_lock);
|
|
@@ -283,6 +282,17 @@ void mlx5e_update_stats_work(struct work_struct *work)
|
|
|
mutex_unlock(&priv->state_lock);
|
|
|
}
|
|
|
|
|
|
+void mlx5e_queue_update_stats(struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ if (!priv->profile->update_stats)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (unlikely(test_bit(MLX5E_STATE_DESTROYING, &priv->state)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ queue_work(priv->wq, &priv->update_stats_work);
|
|
|
+}
|
|
|
+
|
|
|
static void mlx5e_async_event(struct mlx5_core_dev *mdev, void *vpriv,
|
|
|
enum mlx5_dev_event event, unsigned long param)
|
|
|
{
|
|
@@ -1789,7 +1799,7 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c,
|
|
|
struct mlx5e_channel_param *cparam)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = c->priv;
|
|
|
- int err, tc, max_nch = priv->profile->max_nch(priv->mdev);
|
|
|
+ int err, tc, max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
|
|
|
|
|
|
for (tc = 0; tc < params->num_tc; tc++) {
|
|
|
int txq_ix = c->ix + tc * max_nch;
|
|
@@ -2429,7 +2439,7 @@ int mlx5e_create_direct_rqts(struct mlx5e_priv *priv)
|
|
|
int err;
|
|
|
int ix;
|
|
|
|
|
|
- for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
|
|
|
+ for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
|
|
|
rqt = &priv->direct_tir[ix].rqt;
|
|
|
err = mlx5e_create_rqt(priv, 1 /*size */, rqt);
|
|
|
if (err)
|
|
@@ -2450,7 +2460,7 @@ void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < priv->profile->max_nch(priv->mdev); i++)
|
|
|
+ for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++)
|
|
|
mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
|
|
|
}
|
|
|
|
|
@@ -2544,7 +2554,7 @@ static void mlx5e_redirect_rqts(struct mlx5e_priv *priv,
|
|
|
mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp);
|
|
|
}
|
|
|
|
|
|
- for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
|
|
|
+ for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
|
|
|
struct mlx5e_redirect_rqt_param direct_rrp = {
|
|
|
.is_rss = false,
|
|
|
{
|
|
@@ -2745,7 +2755,7 @@ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
|
|
|
goto free_in;
|
|
|
}
|
|
|
|
|
|
- for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
|
|
|
+ for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
|
|
|
err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
|
|
|
in, inlen);
|
|
|
if (err)
|
|
@@ -2845,7 +2855,7 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev)
|
|
|
|
|
|
static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
- int max_nch = priv->profile->max_nch(priv->mdev);
|
|
|
+ int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
|
|
|
int i, tc;
|
|
|
|
|
|
for (i = 0; i < max_nch; i++)
|
|
@@ -2957,9 +2967,7 @@ int mlx5e_open_locked(struct net_device *netdev)
|
|
|
if (priv->profile->update_carrier)
|
|
|
priv->profile->update_carrier(priv);
|
|
|
|
|
|
- if (priv->profile->update_stats)
|
|
|
- queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
|
|
|
-
|
|
|
+ mlx5e_queue_update_stats(priv);
|
|
|
return 0;
|
|
|
|
|
|
err_clear_state_opened_flag:
|
|
@@ -3239,7 +3247,7 @@ err_destroy_inner_tirs:
|
|
|
|
|
|
int mlx5e_create_direct_tirs(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
- int nch = priv->profile->max_nch(priv->mdev);
|
|
|
+ int nch = mlx5e_get_netdev_max_channels(priv->netdev);
|
|
|
struct mlx5e_tir *tir;
|
|
|
void *tirc;
|
|
|
int inlen;
|
|
@@ -3292,7 +3300,7 @@ void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc)
|
|
|
|
|
|
void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
- int nch = priv->profile->max_nch(priv->mdev);
|
|
|
+ int nch = mlx5e_get_netdev_max_channels(priv->netdev);
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < nch; i++)
|
|
@@ -3441,7 +3449,7 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
|
|
struct mlx5e_pport_stats *pstats = &priv->stats.pport;
|
|
|
|
|
|
/* update HW stats in background for next time */
|
|
|
- queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
|
|
|
+ mlx5e_queue_update_stats(priv);
|
|
|
|
|
|
if (mlx5e_is_uplink_rep(priv)) {
|
|
|
stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
|
|
@@ -4560,33 +4568,6 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
|
|
|
mlx5e_build_rss_params(params);
|
|
|
}
|
|
|
|
|
|
-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);
|
|
|
-
|
|
|
- priv->mdev = mdev;
|
|
|
- priv->netdev = netdev;
|
|
|
- priv->profile = profile;
|
|
|
- priv->ppriv = ppriv;
|
|
|
- priv->msglevel = MLX5E_MSG_LEVEL;
|
|
|
- priv->max_opened_tc = 1;
|
|
|
-
|
|
|
- mlx5e_build_nic_params(mdev, &priv->channels.params,
|
|
|
- profile->max_nch(mdev), netdev->mtu);
|
|
|
-
|
|
|
- mutex_init(&priv->state_lock);
|
|
|
-
|
|
|
- INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work);
|
|
|
- INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work);
|
|
|
- INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work);
|
|
|
- INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
|
|
|
-
|
|
|
- mlx5e_timestamp_init(priv);
|
|
|
-}
|
|
|
-
|
|
|
static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
@@ -4749,15 +4730,23 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv)
|
|
|
mlx5_core_dealloc_q_counter(priv->mdev, priv->drop_rq_q_counter);
|
|
|
}
|
|
|
|
|
|
-static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
|
|
|
- struct net_device *netdev,
|
|
|
- const struct mlx5e_profile *profile,
|
|
|
- void *ppriv)
|
|
|
+static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
|
|
|
+ struct net_device *netdev,
|
|
|
+ const struct mlx5e_profile *profile,
|
|
|
+ void *ppriv)
|
|
|
{
|
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
|
int err;
|
|
|
|
|
|
- mlx5e_build_nic_netdev_priv(mdev, netdev, profile, ppriv);
|
|
|
+ err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ mlx5e_build_nic_params(mdev, &priv->channels.params,
|
|
|
+ mlx5e_get_netdev_max_channels(netdev), netdev->mtu);
|
|
|
+
|
|
|
+ mlx5e_timestamp_init(priv);
|
|
|
+
|
|
|
err = mlx5e_ipsec_init(priv);
|
|
|
if (err)
|
|
|
mlx5_core_err(mdev, "IPSec initialization failed, %d\n", err);
|
|
@@ -4766,12 +4755,15 @@ static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
|
|
|
mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
|
|
|
mlx5e_build_nic_netdev(netdev);
|
|
|
mlx5e_build_tc2txq_maps(priv);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
|
|
|
{
|
|
|
mlx5e_tls_cleanup(priv);
|
|
|
mlx5e_ipsec_cleanup(priv);
|
|
|
+ mlx5e_netdev_cleanup(priv->netdev, priv);
|
|
|
}
|
|
|
|
|
|
static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
|
|
@@ -4934,7 +4926,6 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
|
|
|
.enable = mlx5e_nic_enable,
|
|
|
.disable = mlx5e_nic_disable,
|
|
|
.update_stats = mlx5e_update_ndo_stats,
|
|
|
- .max_nch = mlx5e_get_max_num_channels,
|
|
|
.update_carrier = mlx5e_update_carrier,
|
|
|
.rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe,
|
|
|
.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
|
|
@@ -4943,13 +4934,53 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
|
|
|
|
|
|
/* mlx5e generic netdev management API (move to en_common.c) */
|
|
|
|
|
|
+/* mlx5e_netdev_init/cleanup must be called from profile->init/cleanup callbacks */
|
|
|
+int mlx5e_netdev_init(struct net_device *netdev,
|
|
|
+ struct mlx5e_priv *priv,
|
|
|
+ struct mlx5_core_dev *mdev,
|
|
|
+ const struct mlx5e_profile *profile,
|
|
|
+ void *ppriv)
|
|
|
+{
|
|
|
+ /* priv init */
|
|
|
+ priv->mdev = mdev;
|
|
|
+ priv->netdev = netdev;
|
|
|
+ priv->profile = profile;
|
|
|
+ priv->ppriv = ppriv;
|
|
|
+ priv->msglevel = MLX5E_MSG_LEVEL;
|
|
|
+ priv->max_opened_tc = 1;
|
|
|
+
|
|
|
+ mutex_init(&priv->state_lock);
|
|
|
+ INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work);
|
|
|
+ INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work);
|
|
|
+ INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work);
|
|
|
+ INIT_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
|
|
|
+
|
|
|
+ priv->wq = create_singlethread_workqueue("mlx5e");
|
|
|
+ if (!priv->wq)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ /* netdev init */
|
|
|
+ netif_carrier_off(netdev);
|
|
|
+
|
|
|
+#ifdef CONFIG_MLX5_EN_ARFS
|
|
|
+ netdev->rx_cpu_rmap = mdev->rmap;
|
|
|
+#endif
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void mlx5e_netdev_cleanup(struct net_device *netdev, struct mlx5e_priv *priv)
|
|
|
+{
|
|
|
+ destroy_workqueue(priv->wq);
|
|
|
+}
|
|
|
+
|
|
|
struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
|
|
|
const struct mlx5e_profile *profile,
|
|
|
+ int nch,
|
|
|
void *ppriv)
|
|
|
{
|
|
|
- int nch = profile->max_nch(mdev);
|
|
|
struct net_device *netdev;
|
|
|
- struct mlx5e_priv *priv;
|
|
|
+ int err;
|
|
|
|
|
|
netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
|
|
|
nch * profile->max_tc,
|
|
@@ -4959,25 +4990,15 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_MLX5_EN_ARFS
|
|
|
- netdev->rx_cpu_rmap = mdev->rmap;
|
|
|
-#endif
|
|
|
-
|
|
|
- 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_cleanup_nic;
|
|
|
+ err = profile->init(mdev, netdev, profile, ppriv);
|
|
|
+ if (err) {
|
|
|
+ mlx5_core_err(mdev, "failed to init mlx5e profile %d\n", err);
|
|
|
+ goto err_free_netdev;
|
|
|
+ }
|
|
|
|
|
|
return netdev;
|
|
|
|
|
|
-err_cleanup_nic:
|
|
|
- if (profile->cleanup)
|
|
|
- profile->cleanup(priv);
|
|
|
+err_free_netdev:
|
|
|
free_netdev(netdev);
|
|
|
|
|
|
return NULL;
|
|
@@ -5023,7 +5044,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv)
|
|
|
|
|
|
profile->cleanup_rx(priv);
|
|
|
profile->cleanup_tx(priv);
|
|
|
- cancel_delayed_work_sync(&priv->update_stats_work);
|
|
|
+ cancel_work_sync(&priv->update_stats_work);
|
|
|
}
|
|
|
|
|
|
void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
|
|
@@ -5031,7 +5052,6 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
|
|
|
const struct mlx5e_profile *profile = priv->profile;
|
|
|
struct net_device *netdev = priv->netdev;
|
|
|
|
|
|
- destroy_workqueue(priv->wq);
|
|
|
if (profile->cleanup)
|
|
|
profile->cleanup(priv);
|
|
|
free_netdev(netdev);
|
|
@@ -5080,6 +5100,7 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
|
|
|
void *rpriv = NULL;
|
|
|
void *priv;
|
|
|
int err;
|
|
|
+ int nch;
|
|
|
|
|
|
err = mlx5e_check_required_hca_cap(mdev);
|
|
|
if (err)
|
|
@@ -5095,7 +5116,8 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, rpriv);
|
|
|
+ nch = mlx5e_get_max_num_channels(mdev);
|
|
|
+ netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, nch, rpriv);
|
|
|
if (!netdev) {
|
|
|
mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
|
|
|
goto err_free_rpriv;
|