Commit 72a3c58d authored by Lama Kayal's avatar Lama Kayal Committed by David S. Miller

net/mlx4_en: Resolve bad operstate value

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: c27a02cd ("mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC")
Signed-off-by: default avatarLama Kayal <lkayal@nvidia.com>
Signed-off-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 48514a22
...@@ -1269,7 +1269,6 @@ static void mlx4_en_do_set_rx_mode(struct work_struct *work) ...@@ -1269,7 +1269,6 @@ static void mlx4_en_do_set_rx_mode(struct work_struct *work)
if (!netif_carrier_ok(dev)) { if (!netif_carrier_ok(dev)) {
if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
if (priv->port_state.link_state) { if (priv->port_state.link_state) {
priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
netif_carrier_on(dev); netif_carrier_on(dev);
en_dbg(LINK, priv, "Link Up\n"); en_dbg(LINK, priv, "Link Up\n");
} }
...@@ -1557,26 +1556,36 @@ static void mlx4_en_service_task(struct work_struct *work) ...@@ -1557,26 +1556,36 @@ static void mlx4_en_service_task(struct work_struct *work)
mutex_unlock(&mdev->state_lock); 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_priv *priv = container_of(work, struct mlx4_en_priv, struct mlx4_en_port_state *port_state = &priv->port_state;
linkstate_task);
struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_dev *mdev = priv->mdev;
int linkstate = priv->link_state; struct net_device *dev = priv->dev;
bool up;
mutex_lock(&mdev->state_lock); if (mlx4_en_QUERY_PORT(mdev, priv->port))
/* If observable port state changed set carrier state and port_state->link_state = MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN;
* report to system log */
if (priv->last_link_state != linkstate) { up = port_state->link_state == MLX4_PORT_STATE_DEV_EVENT_PORT_UP;
if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) { if (up == netif_carrier_ok(dev))
netif_carrier_event(dev);
if (!up) {
en_info(priv, "Link Down\n"); en_info(priv, "Link Down\n");
netif_carrier_off(priv->dev); netif_carrier_off(dev);
} else { } else {
en_info(priv, "Link Up\n"); en_info(priv, "Link Up\n");
netif_carrier_on(priv->dev); netif_carrier_on(dev);
}
} }
priv->last_link_state = linkstate; }
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;
mutex_lock(&mdev->state_lock);
mlx4_en_linkstate(priv);
mutex_unlock(&mdev->state_lock); mutex_unlock(&mdev->state_lock);
} }
...@@ -2079,9 +2088,11 @@ static int mlx4_en_open(struct net_device *dev) ...@@ -2079,9 +2088,11 @@ static int mlx4_en_open(struct net_device *dev)
mlx4_en_clear_stats(dev); mlx4_en_clear_stats(dev);
err = mlx4_en_start_port(dev); err = mlx4_en_start_port(dev);
if (err) if (err) {
en_err(priv, "Failed starting port:%d\n", priv->port); en_err(priv, "Failed starting port:%d\n", priv->port);
goto out;
}
mlx4_en_linkstate(priv);
out: out:
mutex_unlock(&mdev->state_lock); mutex_unlock(&mdev->state_lock);
return err; return err;
...@@ -3168,7 +3179,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, ...@@ -3168,7 +3179,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
spin_lock_init(&priv->stats_lock); spin_lock_init(&priv->stats_lock);
INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
INIT_WORK(&priv->restart_task, mlx4_en_restart); 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->stats_task, mlx4_en_do_get_stats);
INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
......
...@@ -552,7 +552,6 @@ struct mlx4_en_priv { ...@@ -552,7 +552,6 @@ struct mlx4_en_priv {
struct mlx4_hwq_resources res; struct mlx4_hwq_resources res;
int link_state; int link_state;
int last_link_state;
bool port_up; bool port_up;
int port; int port;
int registered; int registered;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment