Skip to content

Commit

Permalink
Merge branch 'mlx5-fixes'
Browse files Browse the repository at this point in the history
Saeed Mahameed says:

====================
Mellanox 100G mlx5 fixes for 4.6-rc

This small series provides some bug fixes for mlx5 driver.

A small bug fix for iounmap of a null pointer, which dumps a warning on some archs.

One patch to fix the VXLAN/MLX5_EN dependency issue reported by Arnd.

Two patches to fix the scheduling while atomic issue for ndo_add/del_vxlan_port
NDOs.  The first will add an internal mlx5e workqueue and the second will
delegate vxlan ports add/del requests to that workqueue.

Note: ('net/mlx5: Kconfig: Fix MLX5_EN/VXLAN build issue') is only needed for net
and not net-next as the issue was globally fixed for all device drivers by:
b7aade1 ('vxlan: break dependency with netdev drivers') in net-next.

Applied on top: f27337e ('ip_tunnel: fix preempt warning in ip tunnel creation/updating')
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
davem330 committed May 3, 2016
2 parents 6071bd1 + d8cf2dd commit 3df8f4c
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 29 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ config MLX5_CORE_EN
bool "Mellanox Technologies ConnectX-4 Ethernet support"
depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
select PTP_1588_CLOCK
select VXLAN if MLX5_CORE=y
default n
---help---
Ethernet support in Mellanox Technologies ConnectX-4 NIC.
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ struct mlx5e_priv {
struct mlx5e_vxlan_db vxlan;

struct mlx5e_params params;
struct workqueue_struct *wq;
struct work_struct update_carrier_work;
struct work_struct set_rx_mode_work;
struct delayed_work update_stats_work;
Expand Down
34 changes: 21 additions & 13 deletions drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,8 @@ static void mlx5e_update_stats_work(struct work_struct *work)
mutex_lock(&priv->state_lock);
if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
mlx5e_update_stats(priv);
schedule_delayed_work(dwork,
msecs_to_jiffies(
MLX5E_UPDATE_STATS_INTERVAL));
queue_delayed_work(priv->wq, dwork,
msecs_to_jiffies(MLX5E_UPDATE_STATS_INTERVAL));
}
mutex_unlock(&priv->state_lock);
}
Expand All @@ -280,7 +279,7 @@ static void mlx5e_async_event(struct mlx5_core_dev *mdev, void *vpriv,
switch (event) {
case MLX5_DEV_EVENT_PORT_UP:
case MLX5_DEV_EVENT_PORT_DOWN:
schedule_work(&priv->update_carrier_work);
queue_work(priv->wq, &priv->update_carrier_work);
break;

default:
Expand Down Expand Up @@ -1505,7 +1504,7 @@ int mlx5e_open_locked(struct net_device *netdev)
mlx5e_update_carrier(priv);
mlx5e_timestamp_init(priv);

schedule_delayed_work(&priv->update_stats_work, 0);
queue_delayed_work(priv->wq, &priv->update_stats_work, 0);

return 0;

Expand Down Expand Up @@ -1961,7 +1960,7 @@ static void mlx5e_set_rx_mode(struct net_device *dev)
{
struct mlx5e_priv *priv = netdev_priv(dev);

schedule_work(&priv->set_rx_mode_work);
queue_work(priv->wq, &priv->set_rx_mode_work);
}

static int mlx5e_set_mac(struct net_device *netdev, void *addr)
Expand All @@ -1976,7 +1975,7 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
ether_addr_copy(netdev->dev_addr, saddr->sa_data);
netif_addr_unlock_bh(netdev);

schedule_work(&priv->set_rx_mode_work);
queue_work(priv->wq, &priv->set_rx_mode_work);

return 0;
}
Expand Down Expand Up @@ -2158,7 +2157,7 @@ static void mlx5e_add_vxlan_port(struct net_device *netdev,
if (!mlx5e_vxlan_allowed(priv->mdev))
return;

mlx5e_vxlan_add_port(priv, be16_to_cpu(port));
mlx5e_vxlan_queue_work(priv, sa_family, be16_to_cpu(port), 1);
}

static void mlx5e_del_vxlan_port(struct net_device *netdev,
Expand All @@ -2169,7 +2168,7 @@ static void mlx5e_del_vxlan_port(struct net_device *netdev,
if (!mlx5e_vxlan_allowed(priv->mdev))
return;

mlx5e_vxlan_del_port(priv, be16_to_cpu(port));
mlx5e_vxlan_queue_work(priv, sa_family, be16_to_cpu(port), 0);
}

static netdev_features_t mlx5e_vxlan_features_check(struct mlx5e_priv *priv,
Expand Down Expand Up @@ -2498,10 +2497,14 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)

priv = netdev_priv(netdev);

priv->wq = create_singlethread_workqueue("mlx5e");
if (!priv->wq)
goto err_free_netdev;

err = mlx5_alloc_map_uar(mdev, &priv->cq_uar, false);
if (err) {
mlx5_core_err(mdev, "alloc_map uar failed, %d\n", err);
goto err_free_netdev;
goto err_destroy_wq;
}

err = mlx5_core_alloc_pd(mdev, &priv->pdn);
Expand Down Expand Up @@ -2580,7 +2583,7 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
vxlan_get_rx_port(netdev);

mlx5e_enable_async_events(priv);
schedule_work(&priv->set_rx_mode_work);
queue_work(priv->wq, &priv->set_rx_mode_work);

return priv;

Expand Down Expand Up @@ -2617,6 +2620,9 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
err_unmap_free_uar:
mlx5_unmap_free_uar(mdev, &priv->cq_uar);

err_destroy_wq:
destroy_workqueue(priv->wq);

err_free_netdev:
free_netdev(netdev);

Expand All @@ -2630,9 +2636,9 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)

set_bit(MLX5E_STATE_DESTROYING, &priv->state);

schedule_work(&priv->set_rx_mode_work);
queue_work(priv->wq, &priv->set_rx_mode_work);
mlx5e_disable_async_events(priv);
flush_scheduled_work();
flush_workqueue(priv->wq);
if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) {
netif_device_detach(netdev);
mutex_lock(&priv->state_lock);
Expand All @@ -2655,6 +2661,8 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
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 (!test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state))
free_netdev(netdev);
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/uar.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,10 @@ EXPORT_SYMBOL(mlx5_alloc_map_uar);

void mlx5_unmap_free_uar(struct mlx5_core_dev *mdev, struct mlx5_uar *uar)
{
iounmap(uar->map);
iounmap(uar->bf_map);
if (uar->map)
iounmap(uar->map);
else
iounmap(uar->bf_map);
mlx5_cmd_free_uar(mdev, uar->index);
}
EXPORT_SYMBOL(mlx5_unmap_free_uar);
50 changes: 38 additions & 12 deletions drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,22 @@ struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port)
return vxlan;
}

int mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
static void mlx5e_vxlan_add_port(struct work_struct *work)
{
struct mlx5e_vxlan_work *vxlan_work =
container_of(work, struct mlx5e_vxlan_work, work);
struct mlx5e_priv *priv = vxlan_work->priv;
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
u16 port = vxlan_work->port;
struct mlx5e_vxlan *vxlan;
int err;

err = mlx5e_vxlan_core_add_port_cmd(priv->mdev, port);
if (err)
return err;
if (mlx5e_vxlan_core_add_port_cmd(priv->mdev, port))
goto free_work;

vxlan = kzalloc(sizeof(*vxlan), GFP_KERNEL);
if (!vxlan) {
err = -ENOMEM;
if (!vxlan)
goto err_delete_port;
}

vxlan->udp_port = port;

Expand All @@ -119,13 +120,14 @@ int mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
if (err)
goto err_free;

return 0;
goto free_work;

err_free:
kfree(vxlan);
err_delete_port:
mlx5e_vxlan_core_del_port_cmd(priv->mdev, port);
return err;
free_work:
kfree(vxlan_work);
}

static void __mlx5e_vxlan_core_del_port(struct mlx5e_priv *priv, u16 port)
Expand All @@ -145,12 +147,36 @@ static void __mlx5e_vxlan_core_del_port(struct mlx5e_priv *priv, u16 port)
kfree(vxlan);
}

void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port)
static void mlx5e_vxlan_del_port(struct work_struct *work)
{
if (!mlx5e_vxlan_lookup_port(priv, port))
return;
struct mlx5e_vxlan_work *vxlan_work =
container_of(work, struct mlx5e_vxlan_work, work);
struct mlx5e_priv *priv = vxlan_work->priv;
u16 port = vxlan_work->port;

__mlx5e_vxlan_core_del_port(priv, port);

kfree(vxlan_work);
}

void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, sa_family_t sa_family,
u16 port, int add)
{
struct mlx5e_vxlan_work *vxlan_work;

vxlan_work = kmalloc(sizeof(*vxlan_work), GFP_ATOMIC);
if (!vxlan_work)
return;

if (add)
INIT_WORK(&vxlan_work->work, mlx5e_vxlan_add_port);
else
INIT_WORK(&vxlan_work->work, mlx5e_vxlan_del_port);

vxlan_work->priv = priv;
vxlan_work->port = port;
vxlan_work->sa_family = sa_family;
queue_work(priv->wq, &vxlan_work->work);
}

void mlx5e_vxlan_cleanup(struct mlx5e_priv *priv)
Expand Down
11 changes: 9 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,22 @@ struct mlx5e_vxlan {
u16 udp_port;
};

struct mlx5e_vxlan_work {
struct work_struct work;
struct mlx5e_priv *priv;
sa_family_t sa_family;
u16 port;
};

static inline bool mlx5e_vxlan_allowed(struct mlx5_core_dev *mdev)
{
return (MLX5_CAP_ETH(mdev, tunnel_stateless_vxlan) &&
mlx5_core_is_pf(mdev));
}

void mlx5e_vxlan_init(struct mlx5e_priv *priv);
int mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port);
void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port);
void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, sa_family_t sa_family,
u16 port, int add);
struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port);
void mlx5e_vxlan_cleanup(struct mlx5e_priv *priv);

Expand Down

0 comments on commit 3df8f4c

Please sign in to comment.