Netdev List
 help / color / mirror / Atom feed
* [PATCH v2 08/16] mlx4_en: Reporting HW revision in ethtool -i
From: Yevgeny Petrilin @ 2011-03-23  8:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp, eugenia


HW revision is derived from device ID and rev id.

Signed-off-by: Eugenia Emantayev <eugenia@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/infiniband/hw/mlx4/main.c |    1 -
 drivers/net/mlx4/en_ethtool.c     |   15 ++++++++++++++-
 drivers/net/mlx4/main.c           |    2 ++
 drivers/net/mlx4/mlx4_en.h        |    3 +++
 include/linux/mlx4/device.h       |    2 +-
 5 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index c7a6213..66e3eec 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -721,7 +721,6 @@ static int init_node_data(struct mlx4_ib_dev *dev)
 	if (err)
 		goto out;
 
-	dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index c1f351f..62ace6c 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -45,7 +45,20 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 
-	sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
+	switch (mdev->dev->rev_id) {
+	case 0xa0:
+		if (dev->dev_id >= MLX4_EN_CX3_LOW_ID && dev->dev_id <= MLX4_EN_CX3_HIGH_ID)
+			sprintf(drvinfo->driver, DRV_NAME " (%s_CX-3)", mdev->dev->board_id);
+		else
+			sprintf(drvinfo->driver, DRV_NAME " (%s_CX)", mdev->dev->board_id);
+		break;
+	case 0xb0:
+		sprintf(drvinfo->driver, DRV_NAME " (%s_CX-2)", mdev->dev->board_id);
+		break;
+	default:
+		sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
+		break;
+	}
 	strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
 	sprintf(drvinfo->fw_version, "%d.%d.%d",
 		(u16) (mdev->dev->caps.fw_ver >> 32),
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 42d4fb4..5bebb88 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -1139,6 +1139,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	INIT_LIST_HEAD(&priv->pgdir_list);
 	mutex_init(&priv->pgdir_mutex);
 
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id);
+
 	/*
 	 * Now reset the HCA before we touch the PCI capabilities or
 	 * attempt a firmware command, since a boot ROM may have left
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 07aea8d..ad4df66 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -216,6 +216,9 @@ struct mlx4_en_tx_desc {
 
 #define MLX4_EN_USE_SRQ		0x01000000
 
+#define MLX4_EN_CX3_LOW_ID	0x1000
+#define MLX4_EN_CX3_HIGH_ID	0x1005
+
 struct mlx4_en_rx_alloc {
 	struct page *page;
 	u16 offset;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 2460356..fe2a3a3 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -422,7 +422,7 @@ struct mlx4_dev {
 	unsigned long		flags;
 	struct mlx4_caps	caps;
 	struct radix_tree_root	qp_table_tree;
-	u32			rev_id;
+	u8			rev_id;
 	char			board_id[MLX4_BOARD_ID_LEN];
 };
 
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 07/16] mlx4: Wake on LAN support
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp, igory


The driver queries the FW for WOL support.
Ethtool get/set_wol is implemented accordingly.
Only magic packets are supported at the time.

Signed-off-by: Igor Yarovinsky <igory@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_ethtool.c |   62 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx4/fw.c         |   20 +++++++++++++
 drivers/net/mlx4/fw.h         |    1 +
 drivers/net/mlx4/main.c       |    1 +
 drivers/net/mlx4/mlx4_en.h    |    7 ++++
 include/linux/mlx4/device.h   |    4 ++
 6 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 8cfe858..c1f351f 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -131,8 +131,65 @@ static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
 static void mlx4_en_get_wol(struct net_device *netdev,
 			    struct ethtool_wolinfo *wol)
 {
-	wol->supported = 0;
-	wol->wolopts = 0;
+	struct mlx4_en_priv *priv = netdev_priv(netdev);
+	int err = 0;
+	u64 config = 0;
+
+	if (!priv->mdev->dev->caps.wol) {
+		wol->supported = 0;
+		wol->wolopts = 0;
+		return;
+	}
+
+	err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+	if (err) {
+		en_err(priv, "Failed to get WoL information\n");
+		return;
+	}
+
+	if (config & MLX4_EN_WOL_MAGIC)
+		wol->supported = WAKE_MAGIC;
+	else
+		wol->supported = 0;
+
+	if (config & MLX4_EN_WOL_ENABLED)
+		wol->wolopts = WAKE_MAGIC;
+	else
+		wol->wolopts = 0;
+}
+
+static int mlx4_en_set_wol(struct net_device *netdev,
+			    struct ethtool_wolinfo *wol)
+{
+	struct mlx4_en_priv *priv = netdev_priv(netdev);
+	u64 config = 0;
+	int err = 0;
+
+	if (!priv->mdev->dev->caps.wol)
+		return -EOPNOTSUPP;
+
+	if (wol->supported & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+	if (err) {
+		en_err(priv, "Failed to get WoL info, unable to modify\n");
+		return err;
+	}
+
+	if (wol->wolopts & WAKE_MAGIC) {
+		config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
+				MLX4_EN_WOL_MAGIC;
+	} else {
+		config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
+		config |= MLX4_EN_WOL_DO_MODIFY;
+	}
+
+	err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
+	if (err)
+		en_err(priv, "Failed to set WoL information\n");
+
+	return err;
 }
 
 static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
@@ -442,6 +499,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
 	.get_ethtool_stats = mlx4_en_get_ethtool_stats,
 	.self_test = mlx4_en_self_test,
 	.get_wol = mlx4_en_get_wol,
+	.set_wol = mlx4_en_set_wol,
 	.get_msglevel = mlx4_en_get_msglevel,
 	.set_msglevel = mlx4_en_set_msglevel,
 	.get_coalesce = mlx4_en_get_coalesce,
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 5de1db8..fd1c51b 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -276,6 +276,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev_cap->udp_rss = field & 0x1;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
 	dev_cap->loopback_support = field & 0x1;
+	dev_cap->wol = field & 0x40;
 	MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
 	dev_cap->reserved_uars = field >> 4;
@@ -908,3 +909,22 @@ int mlx4_NOP(struct mlx4_dev *dev)
 	/* Input modifier of 0x1f means "finish as soon as possible." */
 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
 }
+
+#define MLX4_WOL_SETUP_MODE (5 << 28)
+int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
+{
+	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
+
+	return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
+			    MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A);
+}
+EXPORT_SYMBOL_GPL(mlx4_wol_read);
+
+int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
+{
+	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
+
+	return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
+					MLX4_CMD_TIME_CLASS_A);
+}
+EXPORT_SYMBOL_GPL(mlx4_wol_write);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 65cc72e..f7b9cc2 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -80,6 +80,7 @@ struct mlx4_dev_cap {
 	u16 stat_rate_support;
 	int udp_rss;
 	int loopback_support;
+	int wol;
 	u32 flags;
 	int reserved_uars;
 	int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 517ca34..42d4fb4 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -227,6 +227,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
 	dev->caps.udp_rss	     = dev_cap->udp_rss;
 	dev->caps.loopback_support   = dev_cap->loopback_support;
+	dev->caps.wol		     = dev_cap->wol;
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
 
 	dev->caps.log_num_macs  = log_num_mac;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 2db245f..07aea8d 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -479,6 +479,13 @@ struct mlx4_en_priv {
 	int mc_addrs_cnt;
 	struct mlx4_en_stat_out_mbox hw_stats;
 	int vids[128];
+	bool wol;
+};
+
+enum mlx4_en_wol {
+	MLX4_EN_WOL_MAGIC = (1ULL << 61),
+	MLX4_EN_WOL_ENABLED = (1ULL << 62),
+	MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
 };
 
 
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 7838082..2460356 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -251,6 +251,7 @@ struct mlx4_caps {
 	u16			stat_rate_support;
 	int			udp_rss;
 	int			loopback_support;
+	int			wol;
 	u8			port_width_cap[MLX4_MAX_PORTS + 1];
 	int			max_gso_sz;
 	int                     reserved_qps_cnt[MLX4_NUM_QP_REGION];
@@ -535,4 +536,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev);
 int mlx4_assign_eq(struct mlx4_dev *dev, char* name , int* vector);
 void mlx4_release_eq(struct mlx4_dev *dev, int vec);
 
+int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port);
+int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port);
+
 #endif /* MLX4_DEVICE_H */
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 06/16] mlx4_en: using new mlx4 interrupt scheme
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp, markuze


Each RX ring will have its own interrupt vector, and TX rings will share one
(we mostly use polling for TX completions).
The vectors are assigned first time device is opened, and its name includes
the interface name and ring number.

Signed-off-by: Markuze Alex <markuze@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_cq.c      |   38 +++++++++++++++++++++++++++++++-------
 drivers/net/mlx4/en_ethtool.c |    2 +-
 drivers/net/mlx4/en_main.c    |   20 +++++++++++---------
 drivers/net/mlx4/en_netdev.c  |   18 ++++++++++++++----
 drivers/net/mlx4/mlx4_en.h    |    7 +++++--
 5 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/drivers/net/mlx4/en_cq.c b/drivers/net/mlx4/en_cq.c
index 21786ad..ec4b6d0 100644
--- a/drivers/net/mlx4/en_cq.c
+++ b/drivers/net/mlx4/en_cq.c
@@ -51,13 +51,10 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
 	int err;
 
 	cq->size = entries;
-	if (mode == RX) {
+	if (mode == RX)
 		cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
-		cq->vector   = ring % mdev->dev->caps.num_comp_vectors;
-	} else {
+	else
 		cq->buf_size = sizeof(struct mlx4_cqe);
-		cq->vector   = 0;
-	}
 
 	cq->ring = ring;
 	cq->is_tx = mode;
@@ -80,7 +77,8 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
 int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
-	int err;
+	int err = 0;
+	char name[25];
 
 	cq->dev = mdev->pndev[priv->port];
 	cq->mcq.set_ci_db  = cq->wqres.db.db;
@@ -89,6 +87,29 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
 	*cq->mcq.arm_db    = 0;
 	memset(cq->buf, 0, cq->buf_size);
 
+	if (cq->is_tx == RX) {
+		if (mdev->dev->caps.comp_pool) {
+			if (!cq->vector) {
+				sprintf(name , "%s-rx-%d", priv->dev->name, cq->ring);
+				if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) {
+					cq->vector = (cq->ring + 1 + priv->port) %
+						mdev->dev->caps.num_comp_vectors;
+					mlx4_warn(mdev, "Failed Assigning an EQ to "
+						  "%s_rx-%d ,Falling back to legacy EQ's\n",
+						  priv->dev->name, cq->ring);
+				}
+			}
+		} else {
+			cq->vector = (cq->ring + 1 + priv->port) %
+				mdev->dev->caps.num_comp_vectors;
+		}
+	} else {
+		if (!cq->vector || !mdev->dev->caps.comp_pool) {
+			/*Fallback to legacy pool in case of error*/
+			cq->vector   = 0;
+		}
+	}
+
 	if (!cq->is_tx)
 		cq->size = priv->rx_ring[cq->ring].actual_size;
 
@@ -112,12 +133,15 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
 	return 0;
 }
 
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+			bool reserve_vectors)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
 
 	mlx4_en_unmap_buffer(&cq->wqres.buf);
 	mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
+	if (priv->mdev->dev->caps.comp_pool && cq->vector && !reserve_vectors)
+		mlx4_release_eq(priv->mdev->dev, cq->vector);
 	cq->buf_size = 0;
 	cq->buf = NULL;
 }
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 056152b..8cfe858 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -388,7 +388,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
 		mlx4_en_stop_port(dev);
 	}
 
-	mlx4_en_free_resources(priv);
+	mlx4_en_free_resources(priv, true);
 
 	priv->prof->tx_ring_size = tx_size;
 	priv->prof->rx_ring_size = rx_size;
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 1ff6ca6..29aaa43 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -241,16 +241,18 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
 		mdev->port_cnt++;
 
-	/* If we did not receive an explicit number of Rx rings, default to
-	 * the number of completion vectors populated by the mlx4_core */
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
-		mlx4_info(mdev, "Using %d tx rings for port:%d\n",
-			  mdev->profile.prof[i].tx_ring_num, i);
-		mdev->profile.prof[i].rx_ring_num = min_t(int,
-			roundup_pow_of_two(dev->caps.num_comp_vectors),
-			MAX_RX_RINGS);
-		mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
-			  mdev->profile.prof[i].rx_ring_num, i);
+		if (!dev->caps.comp_pool) {
+			mdev->profile.prof[i].rx_ring_num =
+				rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
+							   min_t(int,
+								 dev->caps.num_comp_vectors,
+								 MAX_RX_RINGS)));
+		} else {
+			mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
+				min_t(int, dev->caps.comp_pool/
+				      dev->caps.num_ports - 1 , MAX_MSIX_P_PORT - 1));
+		}
 	}
 
 	/* Create our own workqueue for reset/multicast tasks
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 5727bf5..f6ed315 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -557,6 +557,7 @@ int mlx4_en_start_port(struct net_device *dev)
 	int err = 0;
 	int i;
 	int j;
+	char name[32];
 
 	if (priv->port_up) {
 		en_dbg(DRV, priv, "start port called while port already up\n");
@@ -601,10 +602,19 @@ int mlx4_en_start_port(struct net_device *dev)
 		goto cq_err;
 	}
 
+	if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
+		sprintf(name , "%s-tx", priv->dev->name);
+		if (mlx4_assign_eq(mdev->dev , name, &priv->tx_vector)) {
+			mlx4_warn(mdev, "Failed Assigning an EQ to "
+					"%s_tx ,Falling back to legacy "
+					"EQ's\n", priv->dev->name);
+		}
+	}
 	/* Configure tx cq's and rings */
 	for (i = 0; i < priv->tx_ring_num; i++) {
 		/* Configure cq */
 		cq = &priv->tx_cq[i];
+		cq->vector = priv->tx_vector;
 		err = mlx4_en_activate_cq(priv, cq);
 		if (err) {
 			en_err(priv, "Failed allocating Tx CQ\n");
@@ -819,7 +829,7 @@ static int mlx4_en_close(struct net_device *dev)
 	return 0;
 }
 
-void mlx4_en_free_resources(struct mlx4_en_priv *priv)
+void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors)
 {
 	int i;
 
@@ -827,14 +837,14 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv)
 		if (priv->tx_ring[i].tx_info)
 			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
 		if (priv->tx_cq[i].buf)
-			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+			mlx4_en_destroy_cq(priv, &priv->tx_cq[i], reserve_vectors);
 	}
 
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		if (priv->rx_ring[i].rx_info)
 			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
 		if (priv->rx_cq[i].buf)
-			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
+			mlx4_en_destroy_cq(priv, &priv->rx_cq[i], reserve_vectors);
 	}
 }
 
@@ -896,7 +906,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
 	mdev->pndev[priv->port] = NULL;
 	mutex_unlock(&mdev->state_lock);
 
-	mlx4_en_free_resources(priv);
+	mlx4_en_free_resources(priv, false);
 	free_netdev(dev);
 }
 
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 5387c4e..2db245f 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -62,6 +62,7 @@
 #define MLX4_EN_PAGE_SHIFT	12
 #define MLX4_EN_PAGE_SIZE	(1 << MLX4_EN_PAGE_SHIFT)
 #define MAX_RX_RINGS		16
+#define MIN_RX_RINGS		4
 #define TXBB_SIZE		64
 #define HEADROOM		(2048 / TXBB_SIZE + 1)
 #define STAMP_STRIDE		64
@@ -462,6 +463,7 @@ struct mlx4_en_priv {
 	u16 log_rx_info;
 
 	struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
+	int tx_vector;
 	struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
 	struct mlx4_en_cq tx_cq[MAX_TX_RINGS];
 	struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
@@ -487,12 +489,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 int mlx4_en_start_port(struct net_device *dev);
 void mlx4_en_stop_port(struct net_device *dev);
 
-void mlx4_en_free_resources(struct mlx4_en_priv *priv);
+void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors);
 int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
 
 int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
 		      int entries, int ring, enum cq_type mode);
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+			bool reserve_vectors);
 int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 05/16] mlx4: Changing interrupt scheme
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp, markuze


Adding a pool of MSI-X vectors and EQs that can be used explicitly by mlx4_core
customers (mlx4_ib, mlx4_en). The consumers will assign their own names to the
interrupt vectors. Those vectors are not opened at mlx4 device initialization,
opened by demand.
Changed the max number of possible EQs according to the new scheme, no longer relies on
on number of cores.
The new functionality is exposed through mlx4_assign_eq() and mlx4_release_eq().
Customers that do not use the new API will get completion vectors as before.

Signed-off-by: Markuze Alex <markuze@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/cq.c       |    2 +-
 drivers/net/mlx4/eq.c       |  107 ++++++++++++++++++++++++++++++++++++++++--
 drivers/net/mlx4/main.c     |   20 +++++++-
 drivers/net/mlx4/mlx4.h     |    6 ++
 drivers/net/mlx4/profile.c  |    4 +-
 include/linux/mlx4/device.h |    8 +++
 6 files changed, 134 insertions(+), 13 deletions(-)

diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index 7cd34e9..bd8ef9f 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -198,7 +198,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
 	u64 mtt_addr;
 	int err;
 
-	if (vector >= dev->caps.num_comp_vectors)
+	if (vector > dev->caps.num_comp_vectors + dev->caps.comp_pool)
 		return -EINVAL;
 
 	cq->vector = vector;
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 552d0fc..506cfd0 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -42,7 +42,7 @@
 #include "fw.h"
 
 enum {
-	MLX4_IRQNAME_SIZE	= 64
+	MLX4_IRQNAME_SIZE	= 32
 };
 
 enum {
@@ -317,8 +317,8 @@ static int mlx4_num_eq_uar(struct mlx4_dev *dev)
 	 * we need to map, take the difference of highest index and
 	 * the lowest index we'll use and add 1.
 	 */
-	return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs) / 4 -
-		dev->caps.reserved_eqs / 4 + 1;
+	return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs +
+		 dev->caps.comp_pool)/4 - dev->caps.reserved_eqs/4 + 1;
 }
 
 static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
@@ -496,16 +496,32 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
 static void mlx4_free_irqs(struct mlx4_dev *dev)
 {
 	struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table;
-	int i;
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int	i, vec;
 
 	if (eq_table->have_irq)
 		free_irq(dev->pdev->irq, dev);
+
 	for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
 		if (eq_table->eq[i].have_irq) {
 			free_irq(eq_table->eq[i].irq, eq_table->eq + i);
 			eq_table->eq[i].have_irq = 0;
 		}
 
+	for (i = 0; i < dev->caps.comp_pool; i++) {
+		/*
+		 * Freeing the assigned irq's
+		 * all bits should be 0, but we need to validate
+		 */
+		if (priv->msix_ctl.pool_bm & 1ULL << i) {
+			/* NO need protecting*/
+			vec = dev->caps.num_comp_vectors + 1 + i;
+			free_irq(priv->eq_table.eq[vec].irq,
+				 &priv->eq_table.eq[vec]);
+		}
+	}
+
+
 	kfree(eq_table->irq_names);
 }
 
@@ -578,7 +594,8 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
 		(priv->eq_table.inta_pin < 32 ? 4 : 0);
 
 	priv->eq_table.irq_names =
-		kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1),
+		kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1 +
+					     dev->caps.comp_pool),
 			GFP_KERNEL);
 	if (!priv->eq_table.irq_names) {
 		err = -ENOMEM;
@@ -601,6 +618,22 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
 	if (err)
 		goto err_out_comp;
 
+	/*if additional completion vectors poolsize is 0 this loop will not run*/
+	for (i = dev->caps.num_comp_vectors + 1;
+	      i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) {
+
+		err = mlx4_create_eq(dev, dev->caps.num_cqs -
+					  dev->caps.reserved_cqs +
+					  MLX4_NUM_SPARE_EQE,
+				     (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
+				     &priv->eq_table.eq[i]);
+		if (err) {
+			--i;
+			goto err_out_unmap;
+		}
+	}
+
+
 	if (dev->flags & MLX4_FLAG_MSI_X) {
 		const char *eq_name;
 
@@ -686,7 +719,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
 
 	mlx4_free_irqs(dev);
 
-	for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
+	for (i = 0; i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i)
 		mlx4_free_eq(dev, &priv->eq_table.eq[i]);
 
 	mlx4_unmap_clr_int(dev);
@@ -743,3 +776,65 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
 	return err;
 }
 EXPORT_SYMBOL(mlx4_test_interrupts);
+
+int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector)
+{
+
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int vec = 0, err = 0, i;
+
+	spin_lock(&priv->msix_ctl.pool_lock);
+	for (i = 0; !vec && i < dev->caps.comp_pool; i++) {
+		if (~priv->msix_ctl.pool_bm & 1ULL << i) {
+			priv->msix_ctl.pool_bm |= 1ULL << i;
+			vec = dev->caps.num_comp_vectors + 1 + i;
+			snprintf(priv->eq_table.irq_names +
+					vec * MLX4_IRQNAME_SIZE,
+					MLX4_IRQNAME_SIZE, "%s", name);
+			err = request_irq(priv->eq_table.eq[vec].irq,
+					  mlx4_msi_x_interrupt, 0,
+					  &priv->eq_table.irq_names[vec<<5],
+					  priv->eq_table.eq + vec);
+			if (err) {
+				/*zero out bit by fliping it*/
+				priv->msix_ctl.pool_bm ^= 1 << i;
+				vec = 0;
+				continue;
+				/*we dont want to break here*/
+			}
+			eq_set_ci(&priv->eq_table.eq[vec], 1);
+		}
+	}
+	spin_unlock(&priv->msix_ctl.pool_lock);
+
+	if (vec) {
+		*vector = vec;
+	} else {
+		*vector = 0;
+		err = (i == dev->caps.comp_pool) ? -ENOSPC : err;
+	}
+	return err;
+}
+EXPORT_SYMBOL(mlx4_assign_eq);
+
+void mlx4_release_eq(struct mlx4_dev *dev, int vec)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	/*bm index*/
+	int i = vec - dev->caps.num_comp_vectors - 1;
+
+	if (likely(i >= 0)) {
+		/*sanity check , making sure were not trying to free irq's
+		  Belonging to a legacy EQ*/
+		spin_lock(&priv->msix_ctl.pool_lock);
+		if (priv->msix_ctl.pool_bm & 1ULL << i) {
+			free_irq(priv->eq_table.eq[vec].irq,
+				 &priv->eq_table.eq[vec]);
+			priv->msix_ctl.pool_bm &= ~(1ULL << i);
+		}
+		spin_unlock(&priv->msix_ctl.pool_lock);
+	}
+
+}
+EXPORT_SYMBOL(mlx4_release_eq);
+
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 2765a3c..517ca34 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -969,13 +969,15 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct msix_entry *entries;
-	int nreq;
+	int nreq = min_t(int, dev->caps.num_ports *
+			 min_t(int, num_online_cpus() + 1, MAX_MSIX_P_PORT)
+				+ MSIX_LEGACY_SZ, MAX_MSIX);
 	int err;
 	int i;
 
 	if (msi_x) {
 		nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
-			     num_possible_cpus() + 1);
+			     nreq);
 		entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
 		if (!entries)
 			goto no_msi;
@@ -998,7 +1000,15 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 			goto no_msi;
 		}
 
-		dev->caps.num_comp_vectors = nreq - 1;
+		if (nreq <
+		    MSIX_LEGACY_SZ + dev->caps.num_ports * MIN_MSIX_P_PORT) {
+			/*Working in legacy mode , all EQ's shared*/
+			dev->caps.comp_pool           = 0;
+			dev->caps.num_comp_vectors = nreq - 1;
+		} else {
+			dev->caps.comp_pool           = nreq - MSIX_LEGACY_SZ;
+			dev->caps.num_comp_vectors = MSIX_LEGACY_SZ - 1;
+		}
 		for (i = 0; i < nreq; ++i)
 			priv->eq_table.eq[i].irq = entries[i].vector;
 
@@ -1010,6 +1020,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 
 no_msi:
 	dev->caps.num_comp_vectors = 1;
+	dev->caps.comp_pool	   = 0;
 
 	for (i = 0; i < 2; ++i)
 		priv->eq_table.eq[i].irq = dev->pdev->irq;
@@ -1151,6 +1162,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (err)
 		goto err_close;
 
+	priv->msix_ctl.pool_bm = 0;
+	spin_lock_init(&priv->msix_ctl.pool_lock);
+
 	mlx4_enable_msi_x(dev);
 
 	err = mlx4_setup_hca(dev);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 0da5bb7..67ee8da 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -282,6 +282,11 @@ struct mlx4_sense {
 	struct delayed_work	sense_poll;
 };
 
+struct mlx4_msix_ctl {
+	u64		pool_bm;
+	spinlock_t	pool_lock;
+};
+
 struct mlx4_priv {
 	struct mlx4_dev		dev;
 
@@ -313,6 +318,7 @@ struct mlx4_priv {
 	struct mlx4_port_info	port[MLX4_MAX_PORTS + 1];
 	struct mlx4_sense       sense;
 	struct mutex		port_mutex;
+	struct mlx4_msix_ctl	msix_ctl;
 };
 
 static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c
index e749f82..b967647 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/mlx4/profile.c
@@ -107,9 +107,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
 	profile[MLX4_RES_AUXC].num    = request->num_qp;
 	profile[MLX4_RES_SRQ].num     = request->num_srq;
 	profile[MLX4_RES_CQ].num      = request->num_cq;
-	profile[MLX4_RES_EQ].num      = min_t(unsigned, dev_cap->max_eqs,
-					      dev_cap->reserved_eqs +
-					      num_possible_cpus() + 1);
+	profile[MLX4_RES_EQ].num      = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
 	profile[MLX4_RES_DMPT].num    = request->num_mpt;
 	profile[MLX4_RES_CMPT].num    = MLX4_NUM_CMPTS;
 	profile[MLX4_RES_MTT].num     = request->num_mtt;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 0492146..7838082 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -39,6 +39,11 @@
 
 #include <asm/atomic.h>
 
+#define MAX_MSIX_P_PORT		17
+#define MAX_MSIX		64
+#define MSIX_LEGACY_SZ		4
+#define MIN_MSIX_P_PORT		5
+
 enum {
 	MLX4_FLAG_MSI_X		= 1 << 0,
 	MLX4_FLAG_OLD_PORT_CMDS	= 1 << 1,
@@ -223,6 +228,7 @@ struct mlx4_caps {
 	int			num_eqs;
 	int			reserved_eqs;
 	int			num_comp_vectors;
+	int			comp_pool;
 	int			num_mpts;
 	int			num_mtt_segs;
 	int			mtts_per_seg;
@@ -526,5 +532,7 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
 int mlx4_SYNC_TPT(struct mlx4_dev *dev);
 int mlx4_test_interrupts(struct mlx4_dev *dev);
+int mlx4_assign_eq(struct mlx4_dev *dev, char* name , int* vector);
+void mlx4_release_eq(struct mlx4_dev *dev, int vec);
 
 #endif /* MLX4_DEVICE_H */
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 04/16] mlx4_en: bringing link up when registering netdevice
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_netdev.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index b1180dd..5727bf5 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1069,6 +1069,23 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
 	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
 
+	/* Configure port */
+	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+				    MLX4_EN_MIN_MTU,
+				    0, 0, 0, 0);
+	if (err) {
+		en_err(priv, "Failed setting port general configurations "
+		       "for port %d, with error %d\n", priv->port, err);
+		goto out;
+	}
+
+	/* Init port */
+	en_warn(priv, "Initializing port\n");
+	err = mlx4_INIT_PORT(mdev->dev, priv->port);
+	if (err) {
+		en_err(priv, "Failed Initializing port\n");
+		goto out;
+	}
 	priv->registered = 1;
 	mlx4_en_set_default_moderation(priv);
 	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 03/16] mlx4_en: optimize adaptive moderation algorithm for better latency
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_netdev.c |   18 +++++-------------
 drivers/net/mlx4/mlx4_en.h   |    1 +
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 56627c2..b1180dd 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -417,7 +417,6 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
 	unsigned long avg_pkt_size;
 	unsigned long rx_packets;
 	unsigned long rx_bytes;
-	unsigned long rx_byte_diff;
 	unsigned long tx_packets;
 	unsigned long tx_pkt_diff;
 	unsigned long rx_pkt_diff;
@@ -441,25 +440,20 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
 	rx_pkt_diff = ((unsigned long) (rx_packets -
 					priv->last_moder_packets));
 	packets = max(tx_pkt_diff, rx_pkt_diff);
-	rx_byte_diff = rx_bytes - priv->last_moder_bytes;
-	rx_byte_diff = rx_byte_diff ? rx_byte_diff : 1;
 	rate = packets * HZ / period;
 	avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
 				 priv->last_moder_bytes)) / packets : 0;
 
 	/* Apply auto-moderation only when packet rate exceeds a rate that
 	 * it matters */
-	if (rate > MLX4_EN_RX_RATE_THRESH) {
+	if (rate > MLX4_EN_RX_RATE_THRESH && avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
 		/* If tx and rx packet rates are not balanced, assume that
 		 * traffic is mainly BW bound and apply maximum moderation.
 		 * Otherwise, moderate according to packet rate */
-		if (2 * tx_pkt_diff > 3 * rx_pkt_diff &&
-		    rx_pkt_diff / rx_byte_diff <
-		    MLX4_EN_SMALL_PKT_SIZE)
-			moder_time = priv->rx_usecs_low;
-		else if (2 * rx_pkt_diff > 3 * tx_pkt_diff)
+		if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
+		    2 * rx_pkt_diff > 3 * tx_pkt_diff) {
 			moder_time = priv->rx_usecs_high;
-		else {
+		} else {
 			if (rate < priv->pkt_rate_low)
 				moder_time = priv->rx_usecs_low;
 			else if (rate > priv->pkt_rate_high)
@@ -471,9 +465,7 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
 					priv->rx_usecs_low;
 		}
 	} else {
-		/* When packet rate is low, use default moderation rather than
-		 * 0 to prevent interrupt storms if traffic suddenly increases */
-		moder_time = priv->rx_usecs;
+		moder_time = priv->rx_usecs_low;
 	}
 
 	en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index dfed6a0..5387c4e 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -124,6 +124,7 @@ enum {
 #define MLX4_EN_RX_SIZE_THRESH		1024
 #define MLX4_EN_RX_RATE_THRESH		(1000000 / MLX4_EN_RX_COAL_TIME_HIGH)
 #define MLX4_EN_SAMPLE_INTERVAL		0
+#define MLX4_EN_AVG_PKT_SMALL		256
 
 #define MLX4_EN_AUTO_CONF	0xffff
 
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 02/16]  mlx4_en: moderation parameters are not reseted.
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


Instead of reseting the module parameters each ifup or mtu change,
they are being set once at device initialization
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_netdev.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 897f576..56627c2 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -801,7 +801,6 @@ static int mlx4_en_open(struct net_device *dev)
 		priv->rx_ring[i].packets = 0;
 	}
 
-	mlx4_en_set_default_moderation(priv);
 	err = mlx4_en_start_port(dev);
 	if (err)
 		en_err(priv, "Failed starting port:%d\n", priv->port);
@@ -932,7 +931,6 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
 			en_dbg(DRV, priv, "Change MTU called with card down!?\n");
 		} else {
 			mlx4_en_stop_port(dev);
-			mlx4_en_set_default_moderation(priv);
 			err = mlx4_en_start_port(dev);
 			if (err) {
 				en_err(priv, "Failed restarting port:%d\n",
@@ -1080,6 +1078,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
 
 	priv->registered = 1;
+	mlx4_en_set_default_moderation(priv);
 	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
 	return 0;
 
-- 
1.6.0.2






^ permalink raw reply related

* [PATCH v2 01/16] mlx4_en: going out of range of TX rings when reporting stats
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_port.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index 7f5a322..a2b0bc4 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -206,7 +206,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 	}
 	stats->tx_packets = 0;
 	stats->tx_bytes = 0;
-	for (i = 0; i <= priv->tx_ring_num; i++) {
+	for (i = 0; i < priv->tx_ring_num; i++) {
 		stats->tx_packets += priv->tx_ring[i].packets;
 		stats->tx_bytes += priv->tx_ring[i].bytes;
 	}
-- 
1.6.0.2







^ permalink raw reply related

* [PATCH v2 00/16] mlx4_en: driver updates
From: Yevgeny Petrilin @ 2011-03-23  8:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp

Hello David,

This is the second round for patches originally sent on March 07.

Changes from previous round (after getting the feedbacks):
1. Renamed IRQ name for TX rings.
2. Changed error message when failing to map BlueFlame area.
3. Removed drivers/infiniband/hw/mlx4/ parts of steering changes, those need to be applied with Raw QP support.

Thanks,
Yevgeny


^ permalink raw reply

* 2.6.39-rc: WARNING: at __ip_select_ident+0xd3/0xf0()
From: Alexander Beregalov @ 2011-03-23  7:14 UTC (permalink / raw)
  To: Linux Kernel Mailing List, netdev

Hi

I do not know how to reproduce it.

WARNING: at include/net/inetpeer.h:102 __ip_select_ident+0xd3/0xf0()
Hardware name:
Modules linked in: hwmon_vid sata_sil i2c_nforce2
Pid: 0, comm: swapper Not tainted 2.6.38-07035-g6447f55d #1
Call Trace:
 [<c102ad5d>] warn_slowpath_common+0x6d/0xa0
 [<c13070c3>] ? __ip_select_ident+0xd3/0xf0
 [<c13070c3>] ? __ip_select_ident+0xd3/0xf0
 [<c102adad>] warn_slowpath_null+0x1d/0x20
 [<c13070c3>] __ip_select_ident+0xd3/0xf0
 [<c130df4c>] __ip_make_skb+0x25c/0x360
 [<c130d807>] ? ip_append_data+0x67/0xa0
 [<c132f980>] ? icmp_glue_bits+0x0/0x60
 [<c130e0b4>] ip_push_pending_frames+0x14/0x30
 [<c132f95c>] icmp_push_reply+0xdc/0x100
 [<c13306a8>] icmp_send+0x408/0x4a0
 [<c132ca61>] ? __udp4_lib_lookup.clone.49+0x171/0x2d0
 [<c132d877>] __udp4_lib_rcv+0x487/0x6a0
 [<c13058c0>] ? ip_route_input_common+0x0/0xa00
 [<c132daa2>] udp_rcv+0x12/0x20
 [<c13084bc>] ip_local_deliver+0x9c/0x140
 [<c130846d>] ? ip_local_deliver+0x4d/0x140
 [<c13087c6>] ip_rcv+0x266/0x560
 [<c12e92b3>] __netif_receive_skb+0x393/0x400
 [<c12e8fe4>] ? __netif_receive_skb+0xc4/0x400
 [<c12e9472>] netif_receive_skb+0x42/0x50
 [<c12e94b7>] napi_skb_finish+0x37/0x50
 [<c12eadf3>] napi_gro_receive+0xb3/0xc0
 [<c128d76f>] e1000_receive_skb.clone.34+0x3f/0x60
 [<c128dfcf>] e1000_clean_rx_irq+0x27f/0x4b0
 [<c1055be1>] ? __lock_acquire+0x441/0x19a0
 [<c128d249>] e1000_clean+0x1e9/0x570
 [<c13697fc>] ? _raw_spin_lock+0x5c/0x70
 [<c12e9778>] net_rx_action+0xe8/0x170
 [<c102ffe7>] __do_softirq+0x77/0x110
 [<c102ff70>] ? __do_softirq+0x0/0x110
 <IRQ>  [<c1030246>] ? irq_exit+0x76/0x90
 [<c1003823>] ? do_IRQ+0x43/0xb0
 [<c136f5ee>] ? common_interrupt+0x2e/0x34
 [<c100755f>] ? default_idle+0x2f/0x60
 [<c10015d6>] ? cpu_idle+0x36/0x60
 [<c135f2e5>] ? rest_init+0xa5/0xb0
 [<c135f240>] ? rest_init+0x0/0xb0
 [<c163c663>] ? start_kernel+0x277/0x27e
 [<c163c174>] ? unknown_bootoption+0x0/0x19f
 [<c163c071>] ? i386_start_kernel+0x71/0x77

^ permalink raw reply

* Re: [PATCH 02/36] scsi,rcu: convert call_rcu(fc_rport_free_rcu) to kfree_rcu()
From: Paul E. McKenney @ 2011-03-23  6:50 UTC (permalink / raw)
  To: Robert Love
  Cc: Lai Jiangshan, Ingo Molnar, Jens Axboe, James E.J. Bottomley,
	Neil Horman, David S. Miller, Alexey Kuznetsov,
	Pekka Savola (ipv6), James Morris, Hideaki YOSHIFUJI,
	Patrick McHardy, Eric Dumazet, Stephen Hemminger, Tejun Heo,
	Jarek Poplawski, linux-kernel@vger.kernel.org,
	devel@open-fcoe.org, linux-scsi@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <1300814913.19083.427.camel@fritz>

On Tue, Mar 22, 2011 at 10:28:33AM -0700, Robert Love wrote:
> On Thu, 2011-03-17 at 20:41 -0700, Lai Jiangshan wrote:
> > 
> > The rcu callback fc_rport_free_rcu() just calls a kfree(),
> > so we use kfree_rcu() instead of the call_rcu(fc_rport_free_rcu).
> > 
> > Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
> > ---
> >  drivers/scsi/libfc/fc_rport.c |   14 +-------------
> >  1 files changed, 1 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
> > index a7175ad..29abab0 100644
> > --- a/drivers/scsi/libfc/fc_rport.c
> > +++ b/drivers/scsi/libfc/fc_rport.c
> > @@ -151,18 +151,6 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
> >  }
> >  
> >  /**
> > - * fc_rport_free_rcu() - Free a remote port
> > - * @rcu: The rcu_head structure inside the remote port
> > - */
> > -static void fc_rport_free_rcu(struct rcu_head *rcu)
> > -{
> > -	struct fc_rport_priv *rdata;
> > -
> > -	rdata = container_of(rcu, struct fc_rport_priv, rcu);
> > -	kfree(rdata);
> > -}
> > -
> > -/**
> >   * fc_rport_destroy() - Free a remote port after last reference is released
> >   * @kref: The remote port's kref
> >   */
> > @@ -171,7 +159,7 @@ static void fc_rport_destroy(struct kref *kref)
> >  	struct fc_rport_priv *rdata;
> >  
> >  	rdata = container_of(kref, struct fc_rport_priv, kref);
> > -	call_rcu(&rdata->rcu, fc_rport_free_rcu);
> > +	kfree_rcu(rdata, rcu);
> 
> I think this last line should be:
> 
> kfree_rcu(rdata, &rdata->rcu);

Hello, Robert,

I believe that it is correct as is.  The kfree_rcu() definition is as
follows:

#define kfree_rcu(ptr, rcu_head)					\
	__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))

Then __kfree_rcu() encodes the offset into the rcu_head so that it can
be handled properly at the end of the grace period.

							Thanx, Paul

^ permalink raw reply

* [BUG] net_sched: failed bisection
From: Eric Dumazet @ 2011-03-23  6:45 UTC (permalink / raw)
  To: Stephen Hemminger, David Miller; +Cc: Fabio Checconi, netdev
In-Reply-To: <1300034690.2761.29.camel@edumazet-laptop>

Le dimanche 13 mars 2011 à 17:44 +0100, Eric Dumazet a écrit :
> Le dimanche 13 mars 2011 à 12:34 +0100, Eric Dumazet a écrit :
> > Le mercredi 09 mars 2011 à 11:02 -0800, Stephen Hemminger a écrit :
> > > This is an implementation of the Quick Fair Queue scheduler developed
> > > by Fabio Checconi. The same algorithm is already implemented in ipfw
> > > in FreeBSD. Fabio had an earlier version developed on Linux, I just
> > > cleaned it up.  Thanks to Eric Dumazet for doing the testing and
> > > finding bugs.
> > > 
> > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> > > 
> > 
> > Hi Stephen
> > 
> > My stress tests run fine on this version, please send it to David and
> > netdev and feel free to add my :
> > 
> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> > 
> 
> Ah well, no... sorry
> 
> After a while, I restarted some udpflood tests and no packet was going
> through my dummy0 device. So I wanted to restart my qfq_setup script and
> it froze :
> 
> root      9265 97.0  0.0  2056  440 pts/1    R+   17:41   0:29 tc qdisc del dev dummy0 root
> root      9268  0.0  0.0  2452  760 pts/0    R+   17:42   0:00 ps auxw
> 
> a bit later :
> 
> root      9265 99.3  0.0  2056  440 pts/1    R+   17:41   2:43 tc qdisc del dev dummy0 root
> 
> 

Hi guys

QFQ scheduler update :

While polishing QFQ scheduler, and tracking a bug in it, I finally
replaced in my tc scripts "QFQ experimental" by "SFQ rock solid" and
found I could have a hang in some situations :(

I made a bisection and found :

# git bisect good
7a6362800cb7d1d618a697a650c7aaed3eb39320 is the first bad commit

It seems I am stuck...

# git bisect log
git bisect start
# bad: [c360d5b53a7fec44ae4402e1f13fc888f57ddc3b] Merge branch 'master'
of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
git bisect bad c360d5b53a7fec44ae4402e1f13fc888f57ddc3b
# good: [07a2039b8eb0af4ff464efd3dfd95de5c02648c6] Linux 2.6.30
git bisect good 07a2039b8eb0af4ff464efd3dfd95de5c02648c6
# good: [2ec8c6bb5d8f3a62a79f463525054bae1e3d4487] Merge branch 'master'
of /home/davem/src/GIT/linux-2.6/
git bisect good 2ec8c6bb5d8f3a62a79f463525054bae1e3d4487
# good: [e0e170bd7ded2ec16e2813d63c0faff43193fde8] Merge branch 'next'
of git://git.monstr.eu/linux-2.6-microblaze
git bisect good e0e170bd7ded2ec16e2813d63c0faff43193fde8
# good: [40c73abbb37e399eba274fe49e520ffa3dd65bdb] Merge branch
'for_linus' of
git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6
git bisect good 40c73abbb37e399eba274fe49e520ffa3dd65bdb
# good: [4b66fef9b591b95f447aea12242a1133deb0bd22] mcast: net_device dev
not used
git bisect good 4b66fef9b591b95f447aea12242a1133deb0bd22
# bad: [7a6362800cb7d1d618a697a650c7aaed3eb39320] Merge
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
git bisect bad 7a6362800cb7d1d618a697a650c7aaed3eb39320
# good: [971f115a50afbe409825c9f3399d5a3b9aca4381] Merge branch
'usb-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
git bisect good 971f115a50afbe409825c9f3399d5a3b9aca4381
# good: [5917def58ab9f5848f2d1da835a33a490d0c8c69] staging/easycap:
reduce code nesting in easycap_sound.c
git bisect good 5917def58ab9f5848f2d1da835a33a490d0c8c69
# good: [6445ced8670f37cfc2c5e24a9de9b413dbfc788d] Merge branch
'staging-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
git bisect good 6445ced8670f37cfc2c5e24a9de9b413dbfc788d
# good: [da91981bee8de20bcd06ee0dbddd53d62d23b1bd] ipv4: Use flowi4 in
ipmr code.
git bisect good da91981bee8de20bcd06ee0dbddd53d62d23b1bd
# good: [106af2c99a5249b809aaed45b8353ac087821f4a] Merge branch 'master'
of
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
into for-davem
git bisect good 106af2c99a5249b809aaed45b8353ac087821f4a
# good: [638be344593b66ccca6802c6076a5b3d9200829d] Phonet: fix
aligned-mode pipe socket buffer header reserve
git bisect good 638be344593b66ccca6802c6076a5b3d9200829d
# good: [c337ffb68e1e71bad069b14d2246fa1e0c31699c] Merge branch 'master'
of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
git bisect good c337ffb68e1e71bad069b14d2246fa1e0c31699c
# good: [ee0caa79569a9c44febc18480beef4847aa8cecd] Merge branch 'master'
of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
git bisect good ee0caa79569a9c44febc18480beef4847aa8cecd
# good: [0bd80dad57d82676ee484fb1f9aa4c5e8b5bc469] net: get rid of
multiple bond-related netdevice->priv_flags
git bisect good 0bd80dad57d82676ee484fb1f9aa4c5e8b5bc469
# good: [8a4eb5734e8d1dc60a8c28576bbbdfdcc643626d] net: introduce
rx_handler results and logic around that
git bisect good 8a4eb5734e8d1dc60a8c28576bbbdfdcc643626d
# good: [ceda86a108671294052cbf51660097b6534672f5] bonding: enable
netpoll without checking link status
git bisect good ceda86a108671294052cbf51660097b6534672f5

Any idea how we can find the problem ?

Script to reproduce the problem :


modprobe dummy

ifconfig dummy0 10.2.2.254 netmask 255.255.255.0 up

for i in `seq 1 240`
do
 arp -H ether -i dummy0 -s 10.2.2.$i 00:00:0c:07:ac:$(printf %02x $i)
done


DEV=dummy0
RATE="rate 40Mbit"
TNETS="10.2.2.0/25"
ALLOT="allot 20000"


tc qdisc del dev dummy0 root 2>/dev/null


tc qdisc add dev $DEV root handle 1: est 1sec 8sec cbq avpkt 1000 rate 100Mbit \
	bandwidth 100Mbit
tc class add dev $DEV parent 1: classid 1:1 \
	est 1sec 8sec cbq allot 10000 mpu 64 \
	rate 100Mbit prio 1 avpkt 1500 bounded

# output to test nets :  40 Mbit limit
tc class add dev $DEV parent 1:1 classid 1:11 \
	est 1sec 8sec cbq $ALLOT mpu 64      \
	$RATE prio 2 avpkt 1400 bounded

tc qdisc add dev $DEV parent 1:11 handle 11:  \
	est 1sec 8sec sfq


for privnet in $TNETS
do
	tc filter add dev $DEV parent 1: protocol ip prio 100 u32 \
		match ip dst $privnet flowid 1:11
done

tc filter add dev $DEV parent 1: protocol ip prio 100 u32 \
	match ip protocol 0 0x00 flowid 1:1


iperf -u -c 10.2.2.1 -P 32 -l 50
iperf -u -c 10.2.2.1 -P 32 -l 50
iperf -u -c 10.2.2.1 -P 32 -l 50
tc -s -d qdisc show dev dummy0



^ permalink raw reply

* [PATCH 1/1] solos-pci: Don't clear open VCs when we detect carrier state (or state changes)
From: Philip Prindeville @ 2011-03-23  6:12 UTC (permalink / raw)
  To: Netdev

Initialize device state to UP, as is done for Ethernet.  If firmware supports communicating carrier state to us, we'll be notified then, and we can indicate it via atm_dev_signal_change().

In any case: (1) higher level protocols will detect a dead link, and (2) loss of carrier is not a reason to tear down the VCs... this is overly zealous.

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
---

  drivers/atm/solos-pci.c |    3 +--
  1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 265bbdf..cd0ff66 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -383,7 +383,6 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
  	/* Anything but 'Showtime' is down */
  	if (strcmp(state_str, "Showtime")) {
  		atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
-		atm_dev_release_vccs(card->atmdev[port]);
  		dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
  		return 0;
  	}
@@ -1246,7 +1245,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
  		card->atmdev[i]->ci_range.vci_bits = 16;
  		card->atmdev[i]->dev_data = card;
  		card->atmdev[i]->phy_data = (void *)(unsigned long)i;
-		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
+		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);

  		skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
  		if (!skb) {



^ permalink raw reply related

* Re: [BUG] VPN broken in net-next
From: David Miller @ 2011-03-23  4:56 UTC (permalink / raw)
  To: ja; +Cc: shemminger, netdev
In-Reply-To: <alpine.LFD.2.00.1103041013360.1452@ja.ssi.bg>

From: Julian Anastasov <ja@ssi.bg>
Date: Fri, 4 Mar 2011 10:39:55 +0200 (EET)

> On Thu, 3 Mar 2011, David Miller wrote:
> 
>> I suspect that even if we need to handle prefixes, we can still use
>> the hash for optimistic lookup, and fallback to a local table FIB
>> inspection if that fails.
> 
> 	Yes, as ip_route_output_slow uses __ip_dev_find for
> fl4_src there should be some kind of fallback to local table,
> so that traffic from 127.0.0.2 to 127.0.0.3 or other local
> subnets on loopback can work. Another option is to use
> inet_addr_onlink but I suspect people can add many addresses
> on loopback: inet_addr_onlink(loopback_indev, addr, 0)

I just got back to this, sorry for taking so long :-)

Here is the patch I've come up with and will commit to
net-2.6, thanks!

--------------------
ipv4: Fallback to FIB local table in __ip_dev_find().

In commit 9435eb1cf0b76b323019cebf8d16762a50a12a19
("ipv4: Implement __ip_dev_find using new interface address hash.")
we reimplemented __ip_dev_find() so that it doesn't have to
do a full FIB table lookup.

Instead, it consults a hash table of addresses configured to
interfaces.

This works identically to the old code in all except one case,
and that is for loopback subnets.

The old code would match the loopback device for any IP address
that falls within a subnet configured to the loopback device.

Handle this corner case by doing the FIB lookup.

We could implement this via inet_addr_onlink() but:

1) Someone could configure many addresses to loopback and
   inet_addr_onlink() is a simple list traversal.

2) We know the old code works.

Reported-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/devinet.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index d5a4553..5345b0b 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -64,6 +64,8 @@
 #include <net/rtnetlink.h>
 #include <net/net_namespace.h>
 
+#include "fib_lookup.h"
+
 static struct ipv4_devconf ipv4_devconf = {
 	.data = {
 		[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1,
@@ -151,6 +153,20 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
 			break;
 		}
 	}
+	if (!result) {
+		struct flowi4 fl4 = { .daddr = addr };
+		struct fib_result res = { 0 };
+		struct fib_table *local;
+
+		/* Fallback to FIB local table so that communication
+		 * over loopback subnets work.
+		 */
+		local = fib_get_table(net, RT_TABLE_LOCAL);
+		if (local &&
+		    !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) &&
+		    res.type == RTN_LOCAL)
+			result = FIB_RES_DEV(res);
+	}
 	if (result && devref)
 		dev_hold(result);
 	rcu_read_unlock();
-- 
1.7.4.1


^ permalink raw reply related

* Re: [RFC][PATCH]: e1000e: If ASPM L0s needs to be disabled, do it prior to enabling device
From: Jeff Kirsher @ 2011-03-23  4:08 UTC (permalink / raw)
  To: Naga Chumbalkar; +Cc: davem, netdev, bruce.w.allan
In-Reply-To: <20110322194437.3043.97757.sendpatchset@nchumbalkar.americas.hpqcorp.net>

On Tue, Mar 22, 2011 at 12:48, Naga Chumbalkar
<nagananda.chumbalkar@hp.com> wrote:
> If ASPM L0s needs to be disabled due to HW errata, do it prior to
> "enabling" the device. This way if the kernel ever defaults its
> aspm_policy to POLICY_POWERSAVE, then the e1000e driver will get a
> chance to disable ASPM on the misbehaving device *prior* to calling
> pci_enable_device_mem(). This will be useful in situations
> where the BIOS indicates ASPM support on the server by clearing the
> ACPI FADT "ASPM Controls" bit.
>
> Note:
> The kernel (2.6.38) currently uses the BIOS "default" as its aspm_policy.
> However, Linux distros can diverge from that and set the default to "powersave".
>
> Signed-off-by: Naga Chumbalkar <nagananda.chumbalkar@hp.com>
> Cc: Bruce Allan <bruce.w.allan@intel.com>
>
> ---
>  drivers/net/e1000e/82571.c  |   10 +++++-----
>  drivers/net/e1000e/e1000.h  |    1 +
>  drivers/net/e1000e/netdev.c |   25 +++++++++++++++++++++----
>  3 files changed, 27 insertions(+), 9 deletions(-)
>

I have added this patch to my queue of e1000e patches.

-- 
Cheers,
Jeff

^ permalink raw reply

* Re: [PATCH v2] tcp: avoid cwnd moderation in undo
From: David Miller @ 2011-03-23  2:37 UTC (permalink / raw)
  To: ycheng; +Cc: ilpo.jarvinen, nanditad, netdev
In-Reply-To: <1300136223-855-1-git-send-email-ycheng@google.com>

From: Yuchung Cheng <ycheng@google.com>
Date: Mon, 14 Mar 2011 13:57:03 -0700

> In the current undo logic, cwnd is moderated after it was restored
> to the value prior entering fast-recovery. It was moderated first
> in tcp_try_undo_recovery then again in tcp_complete_cwr.
> 
> Since the undo indicates recovery was false, these moderations
> are not necessary. If the undo is triggered when most of the
> outstanding data have been acknowledged, the (restored) cwnd is
> falsely pulled down to a small value.
> 
> This patch removes these cwnd moderations if cwnd is undone
>   a) during fast-recovery
> 	b) by receiving DSACKs past fast-recovery
> 
> Signed-off-by: Yuchung Cheng <ycheng@google.com>

Applied, thank you.

I followed it up with this tidy up:

--------------------
tcp: Make undo_ssthresh arg to tcp_undo_cwr() a bool.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/tcp_input.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e72af7e..bef9f04 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2659,7 +2659,7 @@ static void DBGUNDO(struct sock *sk, const char *msg)
 #define DBGUNDO(x...) do { } while (0)
 #endif
 
-static void tcp_undo_cwr(struct sock *sk, const int undo_ssthresh)
+static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 
@@ -2698,7 +2698,7 @@ static int tcp_try_undo_recovery(struct sock *sk)
 		 * or our original transmission succeeded.
 		 */
 		DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans");
-		tcp_undo_cwr(sk, 1);
+		tcp_undo_cwr(sk, true);
 		if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
 			mib_idx = LINUX_MIB_TCPLOSSUNDO;
 		else
@@ -2725,7 +2725,7 @@ static void tcp_try_undo_dsack(struct sock *sk)
 
 	if (tp->undo_marker && !tp->undo_retrans) {
 		DBGUNDO(sk, "D-SACK");
-		tcp_undo_cwr(sk, 1);
+		tcp_undo_cwr(sk, true);
 		tp->undo_marker = 0;
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO);
 	}
@@ -2778,7 +2778,7 @@ static int tcp_try_undo_partial(struct sock *sk, int acked)
 		tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1);
 
 		DBGUNDO(sk, "Hoe");
-		tcp_undo_cwr(sk, 0);
+		tcp_undo_cwr(sk, false);
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO);
 
 		/* So... Do not make Hoe's retransmit yet.
@@ -2807,7 +2807,7 @@ static int tcp_try_undo_loss(struct sock *sk)
 
 		DBGUNDO(sk, "partial loss");
 		tp->lost_out = 0;
-		tcp_undo_cwr(sk, 1);
+		tcp_undo_cwr(sk, true);
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO);
 		inet_csk(sk)->icsk_retransmits = 0;
 		tp->undo_marker = 0;
@@ -3496,7 +3496,7 @@ static void tcp_undo_spur_to_response(struct sock *sk, int flag)
 	if (flag & FLAG_ECE)
 		tcp_ratehalving_spur_to_response(sk);
 	else
-		tcp_undo_cwr(sk, 1);
+		tcp_undo_cwr(sk, true);
 }
 
 /* F-RTO spurious RTO detection algorithm (RFC4138)
-- 
1.7.4.1


^ permalink raw reply related

* Re: [PATCH] netfilter: h323: bug in parsing of ASN1 SEQOF field
From: David Miller @ 2011-03-23  2:33 UTC (permalink / raw)
  To: dsterba; +Cc: netdev, linux-kernel, stable, netfilter-, kaber
In-Reply-To: <1300794929-1541-1-git-send-email-dsterba@suse.cz>

From: David Sterba <dsterba@suse.cz>
Date: Tue, 22 Mar 2011 12:55:29 +0100

> Static analyzer of clang found a dead store which appears to be a bug in
> reading count of items in SEQOF field, only the lower byte of word is
> stored. This may lead to corrupted read and communication shutdown.
> 
> The bug has been in the module since it's first inclusion into linux
> kernel.
> 
> Signed-off-by: David Sterba <dsterba@suse.cz>

Please send netfilter patches to the listed netfilter maintainer
and appropriate mailing lists.  I've added them to the CC:

Otherwise your patch will not be looked at by the right people.

> CC: David Miller <davem@davemloft.net>
> CC: netdev@vger.kernel.org
> CC: stable@kernel.org
> ---
>  net/netfilter/nf_conntrack_h323_asn1.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
> index 8678823..bcd5ed6 100644
> --- a/net/netfilter/nf_conntrack_h323_asn1.c
> +++ b/net/netfilter/nf_conntrack_h323_asn1.c
> @@ -631,7 +631,7 @@ static int decode_seqof(bitstr_t *bs, const struct field_t *f,
>  		CHECK_BOUND(bs, 2);
>  		count = *bs->cur++;
>  		count <<= 8;
> -		count = *bs->cur++;
> +		count += *bs->cur++;
>  		break;
>  	case SEMI:
>  		BYTE_ALIGN(bs);
> -- 
> 1.7.4.1.176.g501cc
> 

^ permalink raw reply

* Re: [PATCH v2] net/unix: Add secdata to unix_stream msgs
From: David Miller @ 2011-03-23  2:32 UTC (permalink / raw)
  To: pekane52; +Cc: linux-kernel, netdev, cxzhang, sds, jmorris, eparis
In-Reply-To: <1300840717-4413-1-git-send-email-pekane52@gmail.com>

From: Pat Kane <pekane52@gmail.com>
Date: Tue, 22 Mar 2011 19:38:37 -0500

> The unix_dgram routines add secdata to socket messages,
> but the unix_stream routines do not. I have added the
> two missing lines of code.
> 
> Signed-off-by: Pat Kane <pekane52@gmail.com>

The security hooks appear to be only intended to operate on datagram
sockets, and as such I think the omission of UNIX stream sockets was
very much on purpose.

The SELINUX hook implementations even have "_dgram()" in their names.

Catherine Zhang added to CC: as she last made modifications to these
hooks.

> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 1663e1a..8753cdd 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1642,6 +1642,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
>  		max_level = err + 1;
>  		fds_sent = true;
>  
> +		unix_get_secdata(siocb->scm, skb);
> +
>  		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
>  		if (err) {
>  			kfree_skb(skb);
> @@ -1930,6 +1932,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
>  		} else {
>  			/* Copy credentials */
>  			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
> +			unix_set_secdata(siocb->scm, skb);
>  			check_creds = 1;
>  		}
>  
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 2/2] virtio_net: remove send completion interrupts and avoid TX queue overrun through packet drop
From: Shirley Ma @ 2011-03-23  2:26 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Herbert Xu, rusty, davem, kvm, netdev
In-Reply-To: <20110322113649.GA17071@redhat.com>

On Tue, 2011-03-22 at 13:36 +0200, Michael S. Tsirkin wrote:
> diff --git a/drivers/virtio/virtio_ring.c
> b/drivers/virtio/virtio_ring.c
> index cc2f73e..6106017 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -185,11 +185,6 @@ int virtqueue_add_buf_gfp(struct virtqueue *_vq,
>         if (vq->num_free < out + in) {
>                 pr_debug("Can't add buf len %i - avail = %i\n",
>                          out + in, vq->num_free);
> -               /* FIXME: for historical reasons, we force a notify
> here if
> -                * there are outgoing parts to the buffer.  Presumably
> the
> -                * host should service the ring ASAP. */
> -               if (out)
> -                       vq->notify(&vq->vq);
>                 END_USE(vq);
>                 return -ENOSPC;
>         }
> 

With simply removing the notify here, it does help the case when TX
overrun hits too often, for example for 1K message size, the single
TCP_STREAM performance improved from 2.xGb/s to 4.xGb/s.

Thanks
Shirley


^ permalink raw reply

* Re: [PATCH] bridge: Fix possibly wrong MLD queries' ethernet source address
From: David Miller @ 2011-03-23  2:26 UTC (permalink / raw)
  To: linus.luessing; +Cc: JBeulich, shemminger, bridge, netdev
In-Reply-To: <1300830032-6727-2-git-send-email-linus.luessing@web.de>

From: Linus Lüssing <linus.luessing@web.de>
Date: Tue, 22 Mar 2011 22:40:32 +0100

> The ipv6_dev_get_saddr() is currently called with an uninitialized
> destination address. Although in tests it usually seemed to nevertheless
> always fetch the right source address, there seems to be a possible race
> condition.
> 
> Therefore this commit changes this, first setting the destination
> address and only after that fetching the source address.
> 
> Reported-by: Jan Beulich <JBeulich@novell.com>
> Signed-off-by: Linus Lüssing <linus.luessing@web.de>

Applied, thank you!

^ permalink raw reply

* Re: [PATCHv2] net: davinci_emac:Fix translation logic for buffer descriptor
From: David Miller @ 2011-03-23  2:25 UTC (permalink / raw)
  To: nsekhar; +Cc: srk, netdev, davinci-linux-open-source, sshtylyov
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB593024C47D8B1@dbde02.ent.ti.com>

From: "Nori, Sekhar" <nsekhar@ti.com>
Date: Tue, 22 Mar 2011 20:10:01 +0530

> On Tue, Mar 22, 2011 at 18:01:03, Govindarajan, Sriramakrishnan wrote:
>> With recent changes to the driver(switch to new cpdma layer),
>> the support for buffer descriptor address translation logic
>> is broken. This affects platforms where the physical address of
>> the descriptors as seen by the DMA engine is different from the
>> physical address.
>> 
>> Original Patch adding translation logic support:
>> Commit: ad021ae8862209864dc8ebd3b7d3a55ce84b9ea2
>> 
>> Signed-off-by: Sriramakrishnan A G <srk@ti.com>
>> ---
>> Addresses review comments from Sergei. Generated against tip of Linus tree.
> 
> Just tested this patch on DM6446 EVM. Successfully
> tried an NFS boot.
> 
> Tested-By: Sekhar Nori <nsekhar@ti.com>

Patch applied, thanks everyone.

^ permalink raw reply

* Re: [PATCH 1/1] ipv6: ip6_route_output does not modify sk parameter, so make it const
From: David Miller @ 2011-03-23  2:17 UTC (permalink / raw)
  To: fw; +Cc: netdev
In-Reply-To: <1300831292-25378-1-git-send-email-fw@strlen.de>

From: Florian Westphal <fw@strlen.de>
Date: Tue, 22 Mar 2011 23:01:32 +0100

> This avoids explicit cast to avoid 'discards qualifiers'
> compiler warning in a netfilter patch that i've been working on.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>

Applied, thanks a lot Florian.

^ permalink raw reply

* Re: [patch net-2.6] bonding: fix rx_handler locking
From: David Miller @ 2011-03-23  2:16 UTC (permalink / raw)
  To: panweiping3; +Cc: jpirko, netdev, nicolas.2p.debian, andy, fubar
In-Reply-To: <4D8955CE.7040808@gmail.com>

From: Weiping Pan <panweiping3@gmail.com>
Date: Wed, 23 Mar 2011 10:07:10 +0800

> On 03/22/2011 08:38 PM, Jiri Pirko wrote:
>> This prevents possible race between bond_enslave and bond_handle_frame
>> as reported by Nicolas by moving rx_handler register/unregister.
>> slave->bond is added to hold pointer to master bonding sructure. That
>> way dev->master is no longer used in bond_handler_frame.
>> Also, this removes "BUG: scheduling while atomic" message
>>
>> Reported-by: Nicolas de Pesloüan<nicolas.2p.debian@gmail.com>
>> Signed-off-by: Jiri Pirko<jpirko@redhat.com>
 ...
> I test this patch with VirtualBox, no kernel panic occurs.

Thanks a lot Weiping.

Once I have test confirmwation from Nicolas I will apply this patch.

^ permalink raw reply

* Re: [patch net-2.6] bonding: fix rx_handler locking
From: Weiping Pan @ 2011-03-23  2:07 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, nicolas.2p.debian, andy, fubar
In-Reply-To: <1300797492-16128-1-git-send-email-jpirko@redhat.com>

On 03/22/2011 08:38 PM, Jiri Pirko wrote:
> This prevents possible race between bond_enslave and bond_handle_frame
> as reported by Nicolas by moving rx_handler register/unregister.
> slave->bond is added to hold pointer to master bonding sructure. That
> way dev->master is no longer used in bond_handler_frame.
> Also, this removes "BUG: scheduling while atomic" message
>
> Reported-by: Nicolas de Pesloüan<nicolas.2p.debian@gmail.com>
> Signed-off-by: Jiri Pirko<jpirko@redhat.com>
> ---
>   drivers/net/bonding/bond_main.c |   56 +++++++++++++++++++++-----------------
>   drivers/net/bonding/bonding.h   |    1 +
>   2 files changed, 32 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 338bea1..16d6fe9 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -1482,21 +1482,16 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
>   {
>   	struct sk_buff *skb = *pskb;
>   	struct slave *slave;
> -	struct net_device *bond_dev;
>   	struct bonding *bond;
>
> -	slave = bond_slave_get_rcu(skb->dev);
> -	bond_dev = ACCESS_ONCE(slave->dev->master);
> -	if (unlikely(!bond_dev))
> -		return RX_HANDLER_PASS;
> -
>   	skb = skb_share_check(skb, GFP_ATOMIC);
>   	if (unlikely(!skb))
>   		return RX_HANDLER_CONSUMED;
>
>   	*pskb = skb;
>
> -	bond = netdev_priv(bond_dev);
> +	slave = bond_slave_get_rcu(skb->dev);
> +	bond = slave->bond;
>
>   	if (bond->params.arp_interval)
>   		slave->dev->last_rx = jiffies;
> @@ -1505,10 +1500,10 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
>   		return RX_HANDLER_EXACT;
>   	}
>
> -	skb->dev = bond_dev;
> +	skb->dev = bond->dev;
>
>   	if (bond->params.mode == BOND_MODE_ALB&&
> -	    bond_dev->priv_flags&  IFF_BRIDGE_PORT&&
> +	    bond->dev->priv_flags&  IFF_BRIDGE_PORT&&
>   	skb->pkt_type == PACKET_HOST) {
>
>   		if (unlikely(skb_cow_head(skb,
> @@ -1516,7 +1511,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
>   			kfree_skb(skb);
>   			return RX_HANDLER_CONSUMED;
>   		}
> -		memcpy(eth_hdr(skb)->h_dest, bond_dev->dev_addr, ETH_ALEN);
> +		memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
>   	}
>
>   	return RX_HANDLER_ANOTHER;
> @@ -1698,20 +1693,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
>   		pr_debug("Error %d calling netdev_set_bond_master\n", res);
>   		goto err_restore_mac;
>   	}
> -	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
> -					 new_slave);
> -	if (res) {
> -		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
> -		goto err_unset_master;
> -	}
>
>   	/* open the slave since the application closed it */
>   	res = dev_open(slave_dev);
>   	if (res) {
>   		pr_debug("Opening slave %s failed\n", slave_dev->name);
> -		goto err_unreg_rxhandler;
> +		goto err_unset_master;
>   	}
>
> +	new_slave->bond = bond;
>   	new_slave->dev = slave_dev;
>   	slave_dev->priv_flags |= IFF_BONDING;
>
> @@ -1907,6 +1897,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
>   	if (res)
>   		goto err_close;
>
> +	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
> +					 new_slave);
> +	if (res) {
> +		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
> +		goto err_dest_symlinks;
> +	}
> +
>   	pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
>   		bond_dev->name, slave_dev->name,
>   		bond_is_active_slave(new_slave) ? "n active" : " backup",
> @@ -1916,13 +1913,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
>   	return 0;
>
>   /* Undo stages on error */
> +err_dest_symlinks:
> +	bond_destroy_slave_symlinks(bond_dev, slave_dev);
> +
>   err_close:
>   	dev_close(slave_dev);
>
> -err_unreg_rxhandler:
> -	netdev_rx_handler_unregister(slave_dev);
> -	synchronize_net();
> -
>   err_unset_master:
>   	netdev_set_bond_master(slave_dev, NULL);
>
> @@ -1988,6 +1984,14 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
>   		return -EINVAL;
>   	}
>
> +	/* unregister rx_handler early so bond_handle_frame wouldn't be called
> +	 * for this slave anymore.
> +	 */
> +	netdev_rx_handler_unregister(slave_dev);
> +	write_unlock_bh(&bond->lock);
> +	synchronize_net();
> +	write_lock_bh(&bond->lock);
> +
>   	if (!bond->params.fail_over_mac) {
>   		if (!compare_ether_addr(bond_dev->dev_addr, slave->perm_hwaddr)&&
>   		bond->slave_cnt>  1)
> @@ -2104,8 +2108,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
>   		netif_addr_unlock_bh(bond_dev);
>   	}
>
> -	netdev_rx_handler_unregister(slave_dev);
> -	synchronize_net();
>   	netdev_set_bond_master(slave_dev, NULL);
>
>   	slave_disable_netpoll(slave);
> @@ -2186,6 +2188,12 @@ static int bond_release_all(struct net_device *bond_dev)
>   		 */
>   		write_unlock_bh(&bond->lock);
>
> +		/* unregister rx_handler early so bond_handle_frame wouldn't
> +		 * be called for this slave anymore.
> +		 */
> +		netdev_rx_handler_unregister(slave_dev);
> +		synchronize_net();
> +
>   		if (bond_is_lb(bond)) {
>   			/* must be called only after the slave
>   			 * has been detached from the list
> @@ -2217,8 +2225,6 @@ static int bond_release_all(struct net_device *bond_dev)
>   			netif_addr_unlock_bh(bond_dev);
>   		}
>
> -		netdev_rx_handler_unregister(slave_dev);
> -		synchronize_net();
>   		netdev_set_bond_master(slave_dev, NULL);
>
>   		slave_disable_netpoll(slave);
> diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
> index 6b26962..90736cb 100644
> --- a/drivers/net/bonding/bonding.h
> +++ b/drivers/net/bonding/bonding.h
> @@ -187,6 +187,7 @@ struct slave {
>   	struct net_device *dev; /* first - useful for panic debug */
>   	struct slave *next;
>   	struct slave *prev;
> +	struct bonding *bond; /* our master */
>   	int    delay;
>   	unsigned long jiffies;
>   	unsigned long last_arp_rx;
Hi,
I test this patch with VirtualBox, no kernel panic occurs.
git log 08351fc6a75731226e1112fc7254542bd3a2912e

[root@localhost ~]# vboxmanage showvminfo server |grep ^NIC
NIC 1:           MAC: 0800273A4DBD, Attachment: Bridged Interface 
'eth0', Cable connected: on, Trace: off (file: none), Type: 82540EM, 
Reported speed: 0 Mbps, Boot priority: 0
NIC 2:           MAC: 080027B5FCD1, Attachment: Bridged Interface 
'eth0', Cable connected: on, Trace: off (file: none), Type: 82540EM, 
Reported speed: 0 Mbps, Boot priority: 0
NIC 3:           MAC: 080027C77BFC, Attachment: Bridged Interface 
'eth0', Cable connected: on, Trace: off (file: none), Type: 82540EM, 
Reported speed: 0 Mbps, Boot priority: 0
NIC 4:           MAC: 080027261BDB, Attachment: Bridged Interface 
'eth0', Cable connected: on, Trace: off (file: none), Type: 82540EM, 
Reported speed: 0 Mbps, Boot priority: 0
NIC 5:           disabled
NIC 6:           disabled
NIC 7:           disabled
NIC 8:           disabled


Here is my test case.

#! /bin/sh
ifconfig eth9 down
NUM=0
for i in {1..100}
do
     modprobe -r bonding
     modprobe bonding max_bonds=0
     echo +bond0 > /sys/class/net/bonding_masters
     echo +bond1 > /sys/class/net/bonding_masters
     echo +eth9 > /sys/class/net/bond1/bonding/slaves
     echo $i " PASS"
     (( NUM += 1))
done

echo $NUM " PASS"

Hope it will be useful for you.
thanks
Weiping Pan



^ permalink raw reply

* [PATCH v2] net/unix: Add secdata to unix_stream msgs
From: Pat Kane @ 2011-03-23  0:38 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev, Pat Kane

The unix_dgram routines add secdata to socket messages,
but the unix_stream routines do not. I have added the
two missing lines of code.

Signed-off-by: Pat Kane <pekane52@gmail.com>
---
 net/unix/af_unix.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 1663e1a..8753cdd 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1642,6 +1642,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		max_level = err + 1;
 		fds_sent = true;
 
+		unix_get_secdata(siocb->scm, skb);
+
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 		if (err) {
 			kfree_skb(skb);
@@ -1930,6 +1932,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 		} else {
 			/* Copy credentials */
 			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
+			unix_set_secdata(siocb->scm, skb);
 			check_creds = 1;
 		}
 
-- 
1.7.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox