Skip to content

Commit

Permalink
net/mlx4_en: Resolve bad operstate value
Browse files Browse the repository at this point in the history
Any link state change that's done prior to net device registration
isn't reflected on the state, thus the operational state is left
obsolete, with 'UNKNOWN' status.

To resolve the issue, query link state from FW upon open operations
to ensure operational state is updated.

Fixes: c27a02c ("mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC")
Signed-off-by: Lama Kayal <lkayal@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Lama Kayal authored and David S. Miller committed Sep 19, 2021
1 parent 48514a2 commit 72a3c58
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 19 deletions.
47 changes: 29 additions & 18 deletions drivers/net/ethernet/mellanox/mlx4/en_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,6 @@ static void mlx4_en_do_set_rx_mode(struct work_struct *work)
if (!netif_carrier_ok(dev)) {
if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
if (priv->port_state.link_state) {
priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
netif_carrier_on(dev);
en_dbg(LINK, priv, "Link Up\n");
}
Expand Down Expand Up @@ -1557,26 +1556,36 @@ static void mlx4_en_service_task(struct work_struct *work)
mutex_unlock(&mdev->state_lock);
}

static void mlx4_en_linkstate(struct work_struct *work)
static void mlx4_en_linkstate(struct mlx4_en_priv *priv)
{
struct mlx4_en_port_state *port_state = &priv->port_state;
struct mlx4_en_dev *mdev = priv->mdev;
struct net_device *dev = priv->dev;
bool up;

if (mlx4_en_QUERY_PORT(mdev, priv->port))
port_state->link_state = MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN;

up = port_state->link_state == MLX4_PORT_STATE_DEV_EVENT_PORT_UP;
if (up == netif_carrier_ok(dev))
netif_carrier_event(dev);
if (!up) {
en_info(priv, "Link Down\n");
netif_carrier_off(dev);
} else {
en_info(priv, "Link Up\n");
netif_carrier_on(dev);
}
}

static void mlx4_en_linkstate_work(struct work_struct *work)
{
struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
linkstate_task);
struct mlx4_en_dev *mdev = priv->mdev;
int linkstate = priv->link_state;

mutex_lock(&mdev->state_lock);
/* If observable port state changed set carrier state and
* report to system log */
if (priv->last_link_state != linkstate) {
if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
en_info(priv, "Link Down\n");
netif_carrier_off(priv->dev);
} else {
en_info(priv, "Link Up\n");
netif_carrier_on(priv->dev);
}
}
priv->last_link_state = linkstate;
mlx4_en_linkstate(priv);
mutex_unlock(&mdev->state_lock);
}

Expand Down Expand Up @@ -2079,9 +2088,11 @@ static int mlx4_en_open(struct net_device *dev)
mlx4_en_clear_stats(dev);

err = mlx4_en_start_port(dev);
if (err)
if (err) {
en_err(priv, "Failed starting port:%d\n", priv->port);

goto out;
}
mlx4_en_linkstate(priv);
out:
mutex_unlock(&mdev->state_lock);
return err;
Expand Down Expand Up @@ -3168,7 +3179,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
spin_lock_init(&priv->stats_lock);
INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
INIT_WORK(&priv->restart_task, mlx4_en_restart);
INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate_work);
INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
#ifdef CONFIG_RFS_ACCEL
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,6 @@ struct mlx4_en_priv {

struct mlx4_hwq_resources res;
int link_state;
int last_link_state;
bool port_up;
int port;
int registered;
Expand Down

0 comments on commit 72a3c58

Please sign in to comment.