The following reply was made to PR kern/180791; it has been noted by GNATS.

From: Shahar Klein <shah...@mellanox.com>
To: John Baldwin <j...@freebsd.org>, "bug-follo...@freebsd.org"
        <bug-follo...@freebsd.org>
Cc: Oded Shanoon <od...@mellanox.com>
Subject: RE: kern/180791: [ofed] [patch] Kernel crash on ifdown and
 kldunload mlxen
Date: Mon, 29 Jul 2013 06:46:37 +0000

 Thanks John,
 
 I've reviewed and tested this patch and it's working fine.
 
 Is this patch going to both 10.0 and 9.2?
 
 10x
 Shahar
 
 -----Original Message-----
 From: John Baldwin [mailto:j...@freebsd.org]=20
 Sent: Thursday, July 25, 2013 10:39 PM
 To: bug-follo...@freebsd.org; Shahar Klein
 Subject: Re: kern/180791: [ofed] [patch] Kernel crash on ifdown and kldunlo=
 ad mlxen
 
 Thanks.  One note is that it seems like the state_lock should be held when =
 stop is called.  Also, the callout used for stats should be drained during =
 detach.  (If you use callot_init_mtx() instead of callout_init() then
 callout_stop() under the lock is race-free, though I'd still do the
 callout_drain() during detach to be safe.)
 
 Also, I had some other changes I made to this file to make the locking more=
  consistent with other NIC drivers in the tree.  Can you look at this and t=
 est this patch please?
 
 Index: en_netdev.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 --- en_netdev.c        (revision 253547)
 +++ en_netdev.c        (working copy)
 @@ -495,11 +495,6 @@ static void mlx4_en_do_get_stats(struct work_struc
 =20
                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] =3D 0;
 -      }
        mutex_unlock(&mdev->state_lock);
  }
 =20
 @@ -688,8 +683,8 @@ int mlx4_en_start_port(struct net_device *dev)
        mlx4_en_set_multicast(dev);
 =20
        /* 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 &=3D ~IFF_DRV_OACTIVE;
 +      dev->if_drv_flags |=3D IFF_DRV_RUNNING;
 =20
        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 *dev)
 =20
        callout_stop(&priv->watchdog_timer);
 =20
 -      atomic_clear_int(&dev->if_drv_flags, IFF_DRV_RUNNING);
 +      dev->if_drv_flags &=3D ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
  }
 =20
  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 =3D arg;
 +      mdev =3D 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;
 =20
 -      priv =3D arg;
        dev =3D priv->dev;
        mdev =3D priv->mdev;
 -      mutex_lock(&mdev->state_lock);
        if (dev->if_drv_flags & IFF_DRV_RUNNING)
                mlx4_en_stop_port(dev);
 =20
        if (!mdev->device_up) {
                en_err(priv, "Cannot open - device down/disabled\n");
 -              goto out;
 +              return;
        }
 =20
        /* Reset HW statistics and performance counters */ @@ -835,9 +841,6 @@ 
ml=
 x4_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);
  }
 =20
  void mlx4_en_free_resources(struct mlx4_en_priv *priv) @@ -927,9 +930,14 @=
 @ void mlx4_en_destroy_netdev(struct net_device *dev
        if (priv->sysctl)
                sysctl_ctx_free(&priv->conf_ctx);
 =20
 +      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);
 =20
        /* Detach the netdev so tasks would not attempt to access it */
        mutex_lock(&mdev->state_lock);
 @@ -1091,25 +1099,25 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long
                error =3D -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) =3D=3D 0) {
 -                              mutex_lock(&mdev->state_lock);
 +                      if ((dev->if_drv_flags & IFF_DRV_RUNNING) =3D=3D 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:
 @@ -1116,6 +1124,7 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long
                error =3D ifmedia_ioctl(dev, ifr, &priv->media, command);
                break;
        case SIOCSIFCAP:
 +              mutex_lock(&mdev->state_lock);
                mask =3D ifr->ifr_reqcap ^ dev->if_capenable;
                if (mask & IFCAP_HWCSUM)
                        dev->if_capenable ^=3D IFCAP_HWCSUM;
 @@ -1130,7 +1139,8 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long
                if (mask & IFCAP_WOL_MAGIC)
                        dev->if_capenable ^=3D 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:
 
 
 --
 John Baldwin
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"

Reply via email to