svn commit: r254006 - in stable/9/sys/ofed: drivers/net/mlx4 include/linux

John Baldwin jhb at FreeBSD.org
Tue Aug 6 19:23:59 UTC 2013


Author: jhb
Date: Tue Aug  6 19:23:57 2013
New Revision: 254006
URL: http://svnweb.freebsd.org/changeset/base/254006

Log:
  MFC 253048,253423,253449,253653,253774,253785:
  - Allow mlx4 devices to switch between Ethernet and Infiniband:
    - Fix sysfs attribute handling by using sysctl_handle_string() and
      properly handling trailing newlines in attribute values.
    - Remove check forbidding requests that would result in one port being
      set to Ethernet and the subsequent port being set to IB.
  - Avoid trashing IP fragments by correctly managing hardware checksumming.
  - Fix panics when downing or unloading the mlx4 driver.
  
  PR:		kern/179999, kern/174213, kern/180430, kern/180791

Modified:
  stable/9/sys/ofed/drivers/net/mlx4/en_netdev.c
  stable/9/sys/ofed/drivers/net/mlx4/en_tx.c
  stable/9/sys/ofed/drivers/net/mlx4/main.c
  stable/9/sys/ofed/include/linux/sysfs.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/ofed/drivers/net/mlx4/en_netdev.c
==============================================================================
--- stable/9/sys/ofed/drivers/net/mlx4/en_netdev.c	Tue Aug  6 19:14:02 2013	(r254005)
+++ stable/9/sys/ofed/drivers/net/mlx4/en_netdev.c	Tue Aug  6 19:23:57 2013	(r254006)
@@ -43,6 +43,7 @@
 #include <net/if_vlan_var.h>
 #include <sys/sockio.h>
 
+static void mlx4_en_init_locked(struct mlx4_en_priv *priv);
 static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv);
 
 static void mlx4_en_vlan_rx_add_vid(void *arg, struct net_device *dev, u16 vid)
@@ -495,11 +496,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 +684,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 +757,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 +798,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 +842,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 +931,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 +1100,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 +1140,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:

Modified: stable/9/sys/ofed/drivers/net/mlx4/en_tx.c
==============================================================================
--- stable/9/sys/ofed/drivers/net/mlx4/en_tx.c	Tue Aug  6 19:14:02 2013	(r254005)
+++ stable/9/sys/ofed/drivers/net/mlx4/en_tx.c	Tue Aug  6 19:23:57 2013	(r254006)
@@ -780,8 +780,12 @@ retry:
 	tx_desc->ctrl.srcrb_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
 						MLX4_WQE_CTRL_SOLICITED);
 	if (mb->m_pkthdr.csum_flags & (CSUM_IP|CSUM_TCP|CSUM_UDP)) {
-		tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
-							 MLX4_WQE_CTRL_TCP_UDP_CSUM);
+		if (mb->m_pkthdr.csum_flags & CSUM_IP)
+			tx_desc->ctrl.srcrb_flags |=
+			    cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM);
+		if (mb->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP))
+			tx_desc->ctrl.srcrb_flags |=
+			    cpu_to_be32(MLX4_WQE_CTRL_TCP_UDP_CSUM);
 		priv->port_stats.tx_chksum_offload++;
 	}
 

Modified: stable/9/sys/ofed/drivers/net/mlx4/main.c
==============================================================================
--- stable/9/sys/ofed/drivers/net/mlx4/main.c	Tue Aug  6 19:14:02 2013	(r254005)
+++ stable/9/sys/ofed/drivers/net/mlx4/main.c	Tue Aug  6 19:23:57 2013	(r254006)
@@ -209,9 +209,6 @@ int mlx4_check_port_params(struct mlx4_d
 					 "on this HCA, aborting.\n");
 				return -EINVAL;
 			}
-			if (port_type[i] == MLX4_PORT_TYPE_ETH &&
-			    port_type[i + 1] == MLX4_PORT_TYPE_IB)
-				return -EINVAL;
 		}
 	}
 

Modified: stable/9/sys/ofed/include/linux/sysfs.h
==============================================================================
--- stable/9/sys/ofed/include/linux/sysfs.h	Tue Aug  6 19:14:02 2013	(r254005)
+++ stable/9/sys/ofed/include/linux/sysfs.h	Tue Aug  6 19:23:57 2013	(r254006)
@@ -75,39 +75,42 @@ sysctl_handle_attr(SYSCTL_HANDLER_ARGS)
 	struct kobject *kobj;
 	struct attribute *attr;
 	const struct sysfs_ops *ops;
-	void *buf;
+	char *buf;
 	int error;
 	ssize_t len;
 
 	kobj = arg1;
 	attr = (struct attribute *)arg2;
-	buf = (void *)get_zeroed_page(GFP_KERNEL);
-	len = 1;	/* Copy out a NULL byte at least. */
 	if (kobj->ktype == NULL || kobj->ktype->sysfs_ops == NULL)
 		return (ENODEV);
-	ops = kobj->ktype->sysfs_ops;
+	buf = (char *)get_zeroed_page(GFP_KERNEL);
 	if (buf == NULL)
 		return (ENOMEM);
+	ops = kobj->ktype->sysfs_ops;
 	if (ops->show) {
 		len = ops->show(kobj, attr, buf);
 		/*
-		 * It's valid not to have a 'show' so we just return 1 byte
-		 * of NULL.
+		 * It's valid to not have a 'show' so just return an
+		 * empty string.
 	 	 */
 		if (len < 0) {
 			error = -len;
-			len = 1;
 			if (error != EIO)
 				goto out;
 		}
+
+		/* Trim trailing newline. */
+		len--;
+		buf[len] = '\0';
 	}
-	error = SYSCTL_OUT(req, buf, len);
-	if (error || !req->newptr || ops->store == NULL)
-		goto out;
-	error = SYSCTL_IN(req, buf, PAGE_SIZE);
-	if (error)
+
+	/* Leave one trailing byte to append a newline. */
+	error = sysctl_handle_string(oidp, buf, PAGE_SIZE - 1, req);
+	if (error != 0 || req->newptr == NULL || ops->store == NULL)
 		goto out;
-	len = ops->store(kobj, attr, buf, req->newlen);
+	len = strlcat(buf, "\n", PAGE_SIZE);
+	KASSERT(len < PAGE_SIZE, ("new attribute truncated"));
+	len = ops->store(kobj, attr, buf, len);
 	if (len < 0)
 		error = -len;
 out:


More information about the svn-src-stable-9 mailing list