Date: Mon, 29 Jul 2013 18:44:52 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r253774 - head/sys/ofed/drivers/net/mlx4 Message-ID: <201307291844.r6TIiqDU088997@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Mon Jul 29 18:44:52 2013 New Revision: 253774 URL: http://svnweb.freebsd.org/changeset/base/253774 Log: Various fixes to the mlxen(4) driver: - Remove an incorrect assertion that can trigger when downing an interface. - Stop the interface during detach to avoid panics when unloading the driver. - A few locking fixes to be more consistent with other FreeBSD drivers: - Protect if_drv_flags with the driver lock, not atomic ops - Hold the driver lock when adjusting multicast state. - Hold the driver lock while adjusting if_capenable. PR: kern/180791 [1,2] Submitted by: Shakar Klein @ Mellanox [1,2] MFC after: 3 days Modified: head/sys/ofed/drivers/net/mlx4/en_netdev.c Modified: head/sys/ofed/drivers/net/mlx4/en_netdev.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/en_netdev.c Mon Jul 29 17:03:42 2013 (r253773) +++ head/sys/ofed/drivers/net/mlx4/en_netdev.c Mon Jul 29 18:44:52 2013 (r253774) @@ -495,11 +495,6 @@ static void mlx4_en_do_get_stats(struct queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); } - if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { - panic("mlx4_en_do_get_stats: Unexpected mac removed for %d\n", - priv->port); - mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; - } mutex_unlock(&mdev->state_lock); } @@ -688,8 +683,8 @@ int mlx4_en_start_port(struct net_device mlx4_en_set_multicast(dev); /* Enable the queues. */ - atomic_clear_int(&dev->if_drv_flags, IFF_DRV_OACTIVE); - atomic_set_int(&dev->if_drv_flags, IFF_DRV_RUNNING); + dev->if_drv_flags &= ~IFF_DRV_OACTIVE; + dev->if_drv_flags |= IFF_DRV_RUNNING; callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT, mlx4_en_watchdog_timeout, priv); @@ -761,7 +756,7 @@ void mlx4_en_stop_port(struct net_device callout_stop(&priv->watchdog_timer); - atomic_clear_int(&dev->if_drv_flags, IFF_DRV_RUNNING); + dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); } static void mlx4_en_restart(struct work_struct *work) @@ -802,19 +797,30 @@ mlx4_en_init(void *arg) { struct mlx4_en_priv *priv; struct mlx4_en_dev *mdev; + + priv = arg; + mdev = priv->mdev; + mutex_lock(&mdev->state_lock); + mlx4_en_init_locked(priv); + mutex_unlock(&mdev->state_lock); +} + +static void +mlx4_en_init_locked(struct mlx4_en_priv *priv) +{ + + struct mlx4_en_dev *mdev; struct ifnet *dev; int i; - priv = arg; dev = priv->dev; mdev = priv->mdev; - mutex_lock(&mdev->state_lock); if (dev->if_drv_flags & IFF_DRV_RUNNING) mlx4_en_stop_port(dev); if (!mdev->device_up) { en_err(priv, "Cannot open - device down/disabled\n"); - goto out; + return; } /* Reset HW statistics and performance counters */ @@ -835,9 +841,6 @@ mlx4_en_init(void *arg) mlx4_en_set_default_moderation(priv); if (mlx4_en_start_port(dev)) en_err(priv, "Failed starting port:%d\n", priv->port); - -out: - mutex_unlock(&mdev->state_lock); } void mlx4_en_free_resources(struct mlx4_en_priv *priv) @@ -927,9 +930,14 @@ void mlx4_en_destroy_netdev(struct net_d if (priv->sysctl) sysctl_ctx_free(&priv->conf_ctx); + mutex_lock(&mdev->state_lock); + mlx4_en_stop_port(dev); + mutex_unlock(&mdev->state_lock); + cancel_delayed_work(&priv->stats_task); /* flush any pending task for this netdev */ flush_workqueue(mdev->workqueue); + callout_drain(&priv->watchdog_timer); /* Detach the netdev so tasks would not attempt to access it */ mutex_lock(&mdev->state_lock); @@ -1091,31 +1099,32 @@ static int mlx4_en_ioctl(struct ifnet *d error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu); break; case SIOCSIFFLAGS: + mutex_lock(&mdev->state_lock); if (dev->if_flags & IFF_UP) { - if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) { - mutex_lock(&mdev->state_lock); + if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) mlx4_en_start_port(dev); - mutex_unlock(&mdev->state_lock); - } else + else mlx4_en_set_multicast(dev); } else { - mutex_lock(&mdev->state_lock); if (dev->if_drv_flags & IFF_DRV_RUNNING) { mlx4_en_stop_port(dev); if_link_state_change(dev, LINK_STATE_DOWN); } - mutex_unlock(&mdev->state_lock); } + mutex_unlock(&mdev->state_lock); break; case SIOCADDMULTI: case SIOCDELMULTI: + mutex_lock(&mdev->state_lock); mlx4_en_set_multicast(dev); + mutex_unlock(&mdev->state_lock); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(dev, ifr, &priv->media, command); break; case SIOCSIFCAP: + mutex_lock(&mdev->state_lock); mask = ifr->ifr_reqcap ^ dev->if_capenable; if (mask & IFCAP_HWCSUM) dev->if_capenable ^= IFCAP_HWCSUM; @@ -1130,7 +1139,8 @@ static int mlx4_en_ioctl(struct ifnet *d if (mask & IFCAP_WOL_MAGIC) dev->if_capenable ^= IFCAP_WOL_MAGIC; if (dev->if_drv_flags & IFF_DRV_RUNNING) - mlx4_en_init(priv); + mlx4_en_init_locked(priv); + mutex_unlock(&mdev->state_lock); VLAN_CAPABILITIES(dev); break; default:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307291844.r6TIiqDU088997>