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