mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-04 04:06:26 +00:00
Merge branch 'mlx5-fixes'
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:b7aade1548
('vxlan: break dependency with netdev drivers') in net-next. Applied on top:f27337e16f
('ip_tunnel: fix preempt warning in ip tunnel creation/updating') ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
3df8f4c6e9
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
@ -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:
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
@ -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;
|
||||
}
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
@ -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)
|
||||
@ -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)
|
||||
|
@ -39,6 +39,13 @@ 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) &&
|
||||
@ -46,8 +53,8 @@ static inline bool mlx5e_vxlan_allowed(struct mlx5_core_dev *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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user