Netdev List
 help / color / mirror / Atom feed
* [PATCH 4/8] netdev: octeon_mgmt: Improve ethtool_ops.
From: David Daney @ 2012-08-21 18:45 UTC (permalink / raw)
  To: linux-mips, ralf, David S. Miller, netdev; +Cc: linux-kernel, David Daney
In-Reply-To: <1345574712-21444-1-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney@cavium.com>

Correctly show no link when the interface is down, and return
-EOPNOTSUPP for things that don't work.  This quiets the ethtool
program when run on down interfaces.

Signed-off-by: David Daney <david.daney@cavium.com>
---
 drivers/net/ethernet/octeon/octeon_mgmt.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index 687a6a0..cf06cf2 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -1379,7 +1379,7 @@ static int octeon_mgmt_get_settings(struct net_device *netdev,
 	if (p->phydev)
 		return phy_ethtool_gset(p->phydev, cmd);
 
-	return -EINVAL;
+	return -EOPNOTSUPP;
 }
 
 static int octeon_mgmt_set_settings(struct net_device *netdev,
@@ -1393,14 +1393,28 @@ static int octeon_mgmt_set_settings(struct net_device *netdev,
 	if (p->phydev)
 		return phy_ethtool_sset(p->phydev, cmd);
 
-	return -EINVAL;
+	return -EOPNOTSUPP;
+}
+
+static int octeon_mgmt_nway_reset(struct net_device *dev)
+{
+	struct octeon_mgmt *p = netdev_priv(dev);
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (p->phydev)
+		return phy_start_aneg(p->phydev);
+
+	return -EOPNOTSUPP;
 }
 
 static const struct ethtool_ops octeon_mgmt_ethtool_ops = {
 	.get_drvinfo = octeon_mgmt_get_drvinfo,
-	.get_link = ethtool_op_get_link,
 	.get_settings = octeon_mgmt_get_settings,
-	.set_settings = octeon_mgmt_set_settings
+	.set_settings = octeon_mgmt_set_settings,
+	.nway_reset = octeon_mgmt_nway_reset,
+	.get_link = ethtool_op_get_link,
 };
 
 static const struct net_device_ops octeon_mgmt_ops = {
-- 
1.7.11.4

^ permalink raw reply related

* [PATCH 3/8] netdev: octeon_mgmt: Add hardware timestamp support.
From: David Daney @ 2012-08-21 18:45 UTC (permalink / raw)
  To: linux-mips, ralf, David S. Miller, netdev
  Cc: linux-kernel, Chad Reese, David Daney
In-Reply-To: <1345574712-21444-1-git-send-email-ddaney.cavm@gmail.com>

From: Chad Reese <kreese@caviumnetworks.com>

Octeon cn6XXX models have timestamp support on the mgmt ports, so hook
it up.

Signed-off-by: Chad Reese <kreese@caviumnetworks.com>
Signed-off-by: David Daney <david.daney@cavium.com>
---
 drivers/net/ethernet/octeon/octeon_mgmt.c | 157 +++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index c4df1ab..687a6a0 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -10,6 +10,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/capability.h>
+#include <linux/net_tstamp.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
@@ -114,6 +115,7 @@ struct octeon_mgmt {
 	u64 agl_prt_ctl;
 	int port;
 	int irq;
+	bool has_rx_tstamp;
 	u64 *tx_ring;
 	dma_addr_t tx_ring_handle;
 	unsigned int tx_next;
@@ -238,6 +240,28 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
 	}
 }
 
+static ktime_t ptp_to_ktime(u64 ptptime)
+{
+	ktime_t ktimebase;
+	u64 ptpbase;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/* Fill the icache with the code */
+	ktime_get_real();
+	/* Flush all pending operations */
+	mb();
+	/* Read the time and PTP clock as close together as
+	 * possible. It is important that this sequence take the same
+	 * amount of time to reduce jitter
+	 */
+	ktimebase = ktime_get_real();
+	ptpbase = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_HI);
+	local_irq_restore(flags);
+
+	return ktime_sub_ns(ktimebase, ptpbase - ptptime);
+}
+
 static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
 {
 	union cvmx_mixx_orcnt mix_orcnt;
@@ -277,6 +301,20 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
 
 		dma_unmap_single(p->dev, re.s.addr, re.s.len,
 				 DMA_TO_DEVICE);
+
+		/* Read the hardware TX timestamp if one was recorded */
+		if (unlikely(re.s.tstamp)) {
+			struct skb_shared_hwtstamps ts;
+			/* Read the timestamp */
+			u64 ns = cvmx_read_csr(CVMX_MIXX_TSTAMP(p->port));
+			/* Remove the timestamp from the FIFO */
+			cvmx_write_csr(CVMX_MIXX_TSCTL(p->port), 0);
+			/* Tell the kernel about the timestamp */
+			ts.syststamp = ptp_to_ktime(ns);
+			ts.hwtstamp = ns_to_ktime(ns);
+			skb_tstamp_tx(skb, &ts);
+		}
+
 		dev_kfree_skb_any(skb);
 		cleaned++;
 
@@ -377,6 +415,16 @@ static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
 		/* A good packet, send it up. */
 		skb_put(skb, re.s.len);
 good:
+		/* Process the RX timestamp if it was recorded */
+		if (p->has_rx_tstamp) {
+			/* The first 8 bytes are the timestamp */
+			u64 ns = *(u64 *)skb->data;
+			struct skb_shared_hwtstamps *ts;
+			ts = skb_hwtstamps(skb);
+			ts->hwtstamp = ns_to_ktime(ns);
+			ts->syststamp = ptp_to_ktime(ns);
+			__skb_pull(skb, 8);
+		}
 		skb->protocol = eth_type_trans(skb, netdev);
 		netdev->stats.rx_packets++;
 		netdev->stats.rx_bytes += skb->len;
@@ -661,18 +709,114 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int octeon_mgmt_ioctl(struct net_device *netdev,
-			     struct ifreq *rq, int cmd)
+static int octeon_mgmt_ioctl_hwtstamp(struct net_device *netdev,
+				      struct ifreq *rq, int cmd)
 {
 	struct octeon_mgmt *p = netdev_priv(netdev);
+	struct hwtstamp_config config;
+	union cvmx_mio_ptp_clock_cfg ptp;
+	union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl;
+	bool have_hw_timestamps = false;
+
+	if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+		return -EFAULT;
 
-	if (!netif_running(netdev))
+	if (config.flags) /* reserved for future extensions */
 		return -EINVAL;
 
-	if (!p->phydev)
+	/* Check the status of hardware for tiemstamps */
+	if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+		/* Get the current state of the PTP clock */
+		ptp.u64 = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_CFG);
+		if (!ptp.s.ext_clk_en) {
+			/* The clock has not been configured to use an
+			 * external source.  Program it to use the main clock
+			 * reference.
+			 */
+			u64 clock_comp = (NSEC_PER_SEC << 32) /	octeon_get_io_clock_rate();
+			if (!ptp.s.ptp_en)
+				cvmx_write_csr(CVMX_MIO_PTP_CLOCK_COMP, clock_comp);
+			pr_info("PTP Clock: Using sclk reference at %lld Hz\n",
+				(NSEC_PER_SEC << 32) / clock_comp);
+		} else {
+			/* The clock is already programmed to use a GPIO */
+			u64 clock_comp = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_COMP);
+			pr_info("PTP Clock: Using GPIO %d at %lld Hz\n",
+				ptp.s.ext_clk_in,
+				(NSEC_PER_SEC << 32) / clock_comp);
+		}
+
+		/* Enable the clock if it wasn't done already */
+		if (!ptp.s.ptp_en) {
+			ptp.s.ptp_en = 1;
+			cvmx_write_csr(CVMX_MIO_PTP_CLOCK_CFG, ptp.u64);
+		}
+		have_hw_timestamps = true;
+	}
+
+	if (!have_hw_timestamps)
 		return -EINVAL;
 
-	return phy_mii_ioctl(p->phydev, rq, cmd);
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+	case HWTSTAMP_TX_ON:
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		p->has_rx_tstamp = false;
+		rxx_frm_ctl.u64 = cvmx_read_csr(p->agl + AGL_GMX_RX_FRM_CTL);
+		rxx_frm_ctl.s.ptp_mode = 0;
+		cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		p->has_rx_tstamp = have_hw_timestamps;
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		if (p->has_rx_tstamp) {
+			rxx_frm_ctl.u64 = cvmx_read_csr(p->agl + AGL_GMX_RX_FRM_CTL);
+			rxx_frm_ctl.s.ptp_mode = 1;
+			cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
+		}
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (copy_to_user(rq->ifr_data, &config, sizeof(config)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int octeon_mgmt_ioctl(struct net_device *netdev,
+			     struct ifreq *rq, int cmd)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return octeon_mgmt_ioctl_hwtstamp(netdev, rq, cmd);
+	default:
+		if (p->phydev)
+			return phy_mii_ioctl(p->phydev, rq, cmd);
+		return -EINVAL;
+	}
 }
 
 static void octeon_mgmt_disable_link(struct octeon_mgmt *p)
@@ -1052,6 +1196,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
 	/* Enable packet I/O. */
 
 	rxx_frm_ctl.u64 = 0;
+	rxx_frm_ctl.s.ptp_mode = p->has_rx_tstamp ? 1 : 0;
 	rxx_frm_ctl.s.pre_align = 1;
 	/*
 	 * When set, disables the length check for non-min sized pkts
@@ -1155,6 +1300,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
 	int rv = NETDEV_TX_BUSY;
 
 	re.d64 = 0;
+	re.s.tstamp = ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) != 0);
 	re.s.len = skb->len;
 	re.s.addr = dma_map_single(p->dev, skb->data,
 				   skb->len,
@@ -1293,6 +1439,7 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
 
 	p->netdev = netdev;
 	p->dev = &pdev->dev;
+	p->has_rx_tstamp = false;
 
 	data = of_get_property(pdev->dev.of_node, "cell-index", &len);
 	if (data && len == sizeof(*data)) {
-- 
1.7.11.4

^ permalink raw reply related

* [PATCH 2/8] netdev: octeon_mgmt: Add support for 1Gig ports.
From: David Daney @ 2012-08-21 18:45 UTC (permalink / raw)
  To: linux-mips, ralf, David S. Miller, netdev; +Cc: linux-kernel, David Daney
In-Reply-To: <1345574712-21444-1-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney@cavium.com>

The original hardware only supported 10M and 100M.  Later versions
added 1G support.  Here we update the driver to make use of this.

Also minor logic clean-ups for testing PHY registration error codes
and TX complete high water marks.

Signed-off-by: David Daney <david.daney@cavium.com>
---
 drivers/net/ethernet/octeon/octeon_mgmt.c | 328 +++++++++++++++++++++++-------
 1 file changed, 255 insertions(+), 73 deletions(-)

diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index c42bbb1..c4df1ab 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2009 Cavium Networks
+ * Copyright (C) 2009-2012 Cavium, Inc
  */
 
 #include <linux/platform_device.h>
@@ -93,6 +93,7 @@ union mgmt_port_ring_entry {
 #define AGL_GMX_RX_ADR_CAM4		0x1a0
 #define AGL_GMX_RX_ADR_CAM5		0x1a8
 
+#define AGL_GMX_TX_CLK			0x208
 #define AGL_GMX_TX_STATS_CTL		0x268
 #define AGL_GMX_TX_CTL			0x270
 #define AGL_GMX_TX_STAT0		0x280
@@ -110,6 +111,7 @@ struct octeon_mgmt {
 	struct net_device *netdev;
 	u64 mix;
 	u64 agl;
+	u64 agl_prt_ctl;
 	int port;
 	int irq;
 	u64 *tx_ring;
@@ -131,6 +133,7 @@ struct octeon_mgmt {
 	spinlock_t lock;
 	unsigned int last_duplex;
 	unsigned int last_link;
+	unsigned int last_speed;
 	struct device *dev;
 	struct napi_struct napi;
 	struct tasklet_struct tx_clean_tasklet;
@@ -140,6 +143,8 @@ struct octeon_mgmt {
 	resource_size_t mix_size;
 	resource_size_t agl_phys;
 	resource_size_t agl_size;
+	resource_size_t agl_prt_ctl_phys;
+	resource_size_t agl_prt_ctl_size;
 };
 
 static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
@@ -488,7 +493,7 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
 	mix_ctl.s.reset = 1;
 	cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
 	cvmx_read_csr(p->mix + MIX_CTL);
-	cvmx_wait(64);
+	octeon_io_clk_delay(64);
 
 	mix_bist.u64 = cvmx_read_csr(p->mix + MIX_BIST);
 	if (mix_bist.u64)
@@ -670,39 +675,148 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
 	return phy_mii_ioctl(p->phydev, rq, cmd);
 }
 
+static void octeon_mgmt_disable_link(struct octeon_mgmt *p)
+{
+	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+
+	/* Disable GMX before we make any changes. */
+	prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
+	prtx_cfg.s.en = 0;
+	prtx_cfg.s.tx_en = 0;
+	prtx_cfg.s.rx_en = 0;
+	cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
+
+	if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+		int i;
+		for (i = 0; i < 10; i++) {
+			prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
+			if (prtx_cfg.s.tx_idle == 1 || prtx_cfg.s.rx_idle == 1)
+				break;
+			mdelay(1);
+			i++;
+		}
+	}
+}
+
+static void octeon_mgmt_enable_link(struct octeon_mgmt *p)
+{
+	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+
+	/* Restore the GMX enable state only if link is set */
+	prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
+	prtx_cfg.s.tx_en = 1;
+	prtx_cfg.s.rx_en = 1;
+	prtx_cfg.s.en = 1;
+	cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
+}
+
+static void octeon_mgmt_update_link(struct octeon_mgmt *p)
+{
+	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+
+	prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
+
+	if (!p->phydev->link)
+		prtx_cfg.s.duplex = 1;
+	else
+		prtx_cfg.s.duplex = p->phydev->duplex;
+
+	switch (p->phydev->speed) {
+	case 10:
+		prtx_cfg.s.speed = 0;
+		prtx_cfg.s.slottime = 0;
+
+		if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+			prtx_cfg.s.burst = 1;
+			prtx_cfg.s.speed_msb = 1;
+		}
+		break;
+	case 100:
+		prtx_cfg.s.speed = 0;
+		prtx_cfg.s.slottime = 0;
+
+		if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+			prtx_cfg.s.burst = 1;
+			prtx_cfg.s.speed_msb = 0;
+		}
+		break;
+	case 1000:
+		/* 1000 MBits is only supported on 6XXX chips */
+		if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+			prtx_cfg.s.speed = 1;
+			prtx_cfg.s.speed_msb = 0;
+			/* Only matters for half-duplex */
+			prtx_cfg.s.slottime = 1;
+			prtx_cfg.s.burst = p->phydev->duplex;
+		}
+		break;
+	case 0:  /* No link */
+	default:
+		break;
+	}
+
+	/* Write the new GMX setting with the port still disabled. */
+	cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
+
+	/* Read GMX CFG again to make sure the config is completed. */
+	prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
+
+	if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+		union cvmx_agl_gmx_txx_clk agl_clk;
+		union cvmx_agl_prtx_ctl prtx_ctl;
+
+		prtx_ctl.u64 = cvmx_read_csr(p->agl_prt_ctl);
+		agl_clk.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_CLK);
+		/* MII (both speeds) and RGMII 1000 speed. */
+		agl_clk.s.clk_cnt = 1;
+		if (prtx_ctl.s.mode == 0) { /* RGMII mode */
+			if (p->phydev->speed == 10)
+				agl_clk.s.clk_cnt = 50;
+			else if (p->phydev->speed == 100)
+				agl_clk.s.clk_cnt = 5;
+		}
+		cvmx_write_csr(p->agl + AGL_GMX_TX_CLK, agl_clk.u64);
+	}
+}
+
 static void octeon_mgmt_adjust_link(struct net_device *netdev)
 {
 	struct octeon_mgmt *p = netdev_priv(netdev);
-	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
 	unsigned long flags;
 	int link_changed = 0;
 
+	if (!p->phydev)
+		return;
+
 	spin_lock_irqsave(&p->lock, flags);
-	if (p->phydev->link) {
-		if (!p->last_link)
-			link_changed = 1;
-		if (p->last_duplex != p->phydev->duplex) {
-			p->last_duplex = p->phydev->duplex;
-			prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
-			prtx_cfg.s.duplex = p->phydev->duplex;
-			cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
-		}
-	} else {
-		if (p->last_link)
-			link_changed = -1;
+
+
+	if (!p->phydev->link && p->last_link)
+		link_changed = -1;
+
+	if (p->phydev->link
+	    && (p->last_duplex != p->phydev->duplex
+		|| p->last_link != p->phydev->link
+		|| p->last_speed != p->phydev->speed)) {
+		octeon_mgmt_disable_link(p);
+		link_changed = 1;
+		octeon_mgmt_update_link(p);
+		octeon_mgmt_enable_link(p);
 	}
+
 	p->last_link = p->phydev->link;
+	p->last_speed = p->phydev->speed;
+	p->last_duplex = p->phydev->duplex;
+
 	spin_unlock_irqrestore(&p->lock, flags);
 
 	if (link_changed != 0) {
 		if (link_changed > 0) {
-			netif_carrier_on(netdev);
 			pr_info("%s: Link is up - %d/%s\n", netdev->name,
 				p->phydev->speed,
 				DUPLEX_FULL == p->phydev->duplex ?
 				"Full" : "Half");
 		} else {
-			netif_carrier_off(netdev);
 			pr_info("%s: Link is down\n", netdev->name);
 		}
 	}
@@ -722,12 +836,8 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
 				   octeon_mgmt_adjust_link, 0,
 				   PHY_INTERFACE_MODE_MII);
 
-	if (IS_ERR(p->phydev)) {
-		p->phydev = NULL;
-		return -1;
-	}
-
-	phy_start_aneg(p->phydev);
+	if (p->phydev == NULL)
+		return -ENODEV;
 
 	return 0;
 }
@@ -735,12 +845,10 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
 static int octeon_mgmt_open(struct net_device *netdev)
 {
 	struct octeon_mgmt *p = netdev_priv(netdev);
-	int port = p->port;
 	union cvmx_mixx_ctl mix_ctl;
 	union cvmx_agl_gmx_inf_mode agl_gmx_inf_mode;
 	union cvmx_mixx_oring1 oring1;
 	union cvmx_mixx_iring1 iring1;
-	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
 	union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl;
 	union cvmx_mixx_irhwm mix_irhwm;
 	union cvmx_mixx_orhwm mix_orhwm;
@@ -787,9 +895,31 @@ static int octeon_mgmt_open(struct net_device *netdev)
 		} while (mix_ctl.s.reset);
 	}
 
-	agl_gmx_inf_mode.u64 = 0;
-	agl_gmx_inf_mode.s.en = 1;
-	cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
+	if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) {
+		agl_gmx_inf_mode.u64 = 0;
+		agl_gmx_inf_mode.s.en = 1;
+		cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
+	}
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
+		|| OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+		/*
+		 * Force compensation values, as they are not
+		 * determined properly by HW
+		 */
+		union cvmx_agl_gmx_drv_ctl drv_ctl;
+
+		drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL);
+		if (p->port) {
+			drv_ctl.s.byp_en1 = 1;
+			drv_ctl.s.nctl1 = 6;
+			drv_ctl.s.pctl1 = 6;
+		} else {
+			drv_ctl.s.byp_en = 1;
+			drv_ctl.s.nctl = 6;
+			drv_ctl.s.pctl = 6;
+		}
+		cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64);
+	}
 
 	oring1.u64 = 0;
 	oring1.s.obase = p->tx_ring_handle >> 3;
@@ -801,11 +931,6 @@ static int octeon_mgmt_open(struct net_device *netdev)
 	iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
 	cvmx_write_csr(p->mix + MIX_IRING1, iring1.u64);
 
-	/* Disable packet I/O. */
-	prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
-	prtx_cfg.s.en = 0;
-	cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
-
 	memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
 	octeon_mgmt_set_mac_address(netdev, &sa);
 
@@ -821,27 +946,70 @@ static int octeon_mgmt_open(struct net_device *netdev)
 	mix_ctl.s.nbtarb = 0;       /* Arbitration mode */
 	/* MII CB-request FIFO programmable high watermark */
 	mix_ctl.s.mrq_hwm = 1;
+#ifdef __LITTLE_ENDIAN
+	mix_ctl.s.lendian = 1;
+#endif
 	cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
 
-	if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
-	    || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
-		/*
-		 * Force compensation values, as they are not
-		 * determined properly by HW
-		 */
-		union cvmx_agl_gmx_drv_ctl drv_ctl;
+	/* Read the PHY to find the mode of the interface. */
+	if (octeon_mgmt_init_phy(netdev)) {
+		dev_err(p->dev, "Cannot initialize PHY on MIX%d.\n", p->port);
+		goto err_noirq;
+	}
 
-		drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL);
-		if (port) {
-			drv_ctl.s.byp_en1 = 1;
-			drv_ctl.s.nctl1 = 6;
-			drv_ctl.s.pctl1 = 6;
-		} else {
-			drv_ctl.s.byp_en = 1;
-			drv_ctl.s.nctl = 6;
-			drv_ctl.s.pctl = 6;
+	/* Set the mode of the interface, RGMII/MII. */
+	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) && p->phydev) {
+		union cvmx_agl_prtx_ctl agl_prtx_ctl;
+		int rgmii_mode = (p->phydev->supported &
+				  (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)) != 0;
+
+		agl_prtx_ctl.u64 = cvmx_read_csr(p->agl_prt_ctl);
+		agl_prtx_ctl.s.mode = rgmii_mode ? 0 : 1;
+		cvmx_write_csr(p->agl_prt_ctl,	agl_prtx_ctl.u64);
+
+		/* MII clocks counts are based on the 125Mhz
+		 * reference, which has an 8nS period. So our delays
+		 * need to be multiplied by this factor.
+		 */
+#define NS_PER_PHY_CLK 8
+
+		/* Take the DLL and clock tree out of reset */
+		agl_prtx_ctl.u64 = cvmx_read_csr(p->agl_prt_ctl);
+		agl_prtx_ctl.s.clkrst = 0;
+		if (rgmii_mode) {
+			agl_prtx_ctl.s.dllrst = 0;
+			agl_prtx_ctl.s.clktx_byp = 0;
 		}
-		cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64);
+		cvmx_write_csr(p->agl_prt_ctl,	agl_prtx_ctl.u64);
+		cvmx_read_csr(p->agl_prt_ctl); /* Force write out before wait */
+
+		/* Wait for the DLL to lock. External 125 MHz
+		 * reference clock must be stable at this point.
+		 */
+		ndelay(256 * NS_PER_PHY_CLK);
+
+		/* Enable the interface */
+		agl_prtx_ctl.u64 = cvmx_read_csr(p->agl_prt_ctl);
+		agl_prtx_ctl.s.enable = 1;
+		cvmx_write_csr(p->agl_prt_ctl, agl_prtx_ctl.u64);
+
+		/* Read the value back to force the previous write */
+		agl_prtx_ctl.u64 = cvmx_read_csr(p->agl_prt_ctl);
+
+		/* Enable the compensation controller */
+		agl_prtx_ctl.s.comp = 1;
+		agl_prtx_ctl.s.drv_byp = 0;
+		cvmx_write_csr(p->agl_prt_ctl,	agl_prtx_ctl.u64);
+		/* Force write out before wait. */
+		cvmx_read_csr(p->agl_prt_ctl);
+
+		/* For compensation state to lock. */
+		ndelay(1040 * NS_PER_PHY_CLK);
+
+		/* Some Ethernet switches cannot handle standard
+		 * Interframe Gap, increase to 16 bytes.
+		 */
+		cvmx_write_csr(CVMX_AGL_GMX_TX_IFG, 0x88);
 	}
 
 	octeon_mgmt_rx_fill_ring(netdev);
@@ -872,7 +1040,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
 
 	/* Interrupt when we have 1 or more packets to clean.  */
 	mix_orhwm.u64 = 0;
-	mix_orhwm.s.orhwm = 1;
+	mix_orhwm.s.orhwm = 0;
 	cvmx_write_csr(p->mix + MIX_ORHWM, mix_orhwm.u64);
 
 	/* Enable receive and transmit interrupts */
@@ -881,7 +1049,6 @@ static int octeon_mgmt_open(struct net_device *netdev)
 	mix_intena.s.othena = 1;
 	cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
 
-
 	/* Enable packet I/O. */
 
 	rxx_frm_ctl.u64 = 0;
@@ -912,26 +1079,20 @@ static int octeon_mgmt_open(struct net_device *netdev)
 	rxx_frm_ctl.s.pre_chk = 1;
 	cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
 
-	/* Enable the AGL block */
-	agl_gmx_inf_mode.u64 = 0;
-	agl_gmx_inf_mode.s.en = 1;
-	cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
-
-	/* Configure the port duplex and enables */
-	prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
-	prtx_cfg.s.tx_en = 1;
-	prtx_cfg.s.rx_en = 1;
-	prtx_cfg.s.en = 1;
-	p->last_duplex = 1;
-	prtx_cfg.s.duplex = p->last_duplex;
-	cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
+	/* Configure the port duplex, speed and enables */
+	octeon_mgmt_disable_link(p);
+	if (p->phydev)
+		octeon_mgmt_update_link(p);
+	octeon_mgmt_enable_link(p);
 
 	p->last_link = 0;
-	netif_carrier_off(netdev);
-
-	if (octeon_mgmt_init_phy(netdev)) {
-		dev_err(p->dev, "Cannot initialize PHY.\n");
-		goto err_noirq;
+	p->last_speed = 0;
+	/* PHY is not present in simulator. The carrier is enabled
+	 * while initializing the phy for simulator, leave it enabled.
+	 */
+	if (p->phydev) {
+		netif_carrier_off(netdev);
+		phy_start_aneg(p->phydev);
 	}
 
 	netif_wake_queue(netdev);
@@ -961,6 +1122,7 @@ static int octeon_mgmt_stop(struct net_device *netdev)
 
 	if (p->phydev)
 		phy_disconnect(p->phydev);
+	p->phydev = NULL;
 
 	netif_carrier_off(netdev);
 
@@ -1033,6 +1195,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
 	/* Ring the bell.  */
 	cvmx_write_csr(p->mix + MIX_ORING2, 1);
 
+	netdev->trans_start = jiffies;
 	rv = NETDEV_TX_OK;
 out:
 	octeon_mgmt_update_tx_stats(netdev);
@@ -1098,9 +1261,9 @@ static const struct net_device_ops octeon_mgmt_ops = {
 	.ndo_open =			octeon_mgmt_open,
 	.ndo_stop =			octeon_mgmt_stop,
 	.ndo_start_xmit =		octeon_mgmt_xmit,
-	.ndo_set_rx_mode = 		octeon_mgmt_set_rx_filtering,
+	.ndo_set_rx_mode =		octeon_mgmt_set_rx_filtering,
 	.ndo_set_mac_address =		octeon_mgmt_set_mac_address,
-	.ndo_do_ioctl = 		octeon_mgmt_ioctl,
+	.ndo_do_ioctl =			octeon_mgmt_ioctl,
 	.ndo_change_mtu =		octeon_mgmt_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller =		octeon_mgmt_poll_controller,
@@ -1115,6 +1278,7 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
 	const u8 *mac;
 	struct resource *res_mix;
 	struct resource *res_agl;
+	struct resource *res_agl_prt_ctl;
 	int len;
 	int result;
 
@@ -1161,10 +1325,19 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	res_agl_prt_ctl = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+	if (res_agl_prt_ctl == NULL) {
+		dev_err(&pdev->dev, "no 'reg' resource\n");
+		result = -ENXIO;
+		goto err;
+	}
+
 	p->mix_phys = res_mix->start;
 	p->mix_size = resource_size(res_mix);
 	p->agl_phys = res_agl->start;
 	p->agl_size = resource_size(res_agl);
+	p->agl_prt_ctl_phys = res_agl_prt_ctl->start;
+	p->agl_prt_ctl_size = resource_size(res_agl_prt_ctl);
 
 
 	if (!devm_request_mem_region(&pdev->dev, p->mix_phys, p->mix_size,
@@ -1183,10 +1356,18 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	if (!devm_request_mem_region(&pdev->dev, p->agl_prt_ctl_phys,
+				     p->agl_prt_ctl_size, res_agl_prt_ctl->name)) {
+		result = -ENXIO;
+		dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+			res_agl_prt_ctl->name);
+		goto err;
+	}
 
 	p->mix = (u64)devm_ioremap(&pdev->dev, p->mix_phys, p->mix_size);
 	p->agl = (u64)devm_ioremap(&pdev->dev, p->agl_phys, p->agl_size);
-
+	p->agl_prt_ctl = (u64)devm_ioremap(&pdev->dev, p->agl_prt_ctl_phys,
+					   p->agl_prt_ctl_size);
 	spin_lock_init(&p->lock);
 
 	skb_queue_head_init(&p->tx_list);
@@ -1209,6 +1390,7 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
 	pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
 
+	netif_carrier_off(netdev);
 	result = register_netdev(netdev);
 	if (result)
 		goto err;
-- 
1.7.11.4

^ permalink raw reply related

* [PATCH 1/8] MIPS: Octeon: Add octeon_io_clk_delay() function.
From: David Daney @ 2012-08-21 18:45 UTC (permalink / raw)
  To: linux-mips, ralf, David S. Miller, netdev; +Cc: linux-kernel, David Daney
In-Reply-To: <1345574712-21444-1-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <ddaney@caviumnetworks.com>

Also cleanup and fix octeon_init_cvmcount()

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/cavium-octeon/csrc-octeon.c | 93 ++++++++++++++++++++++++-----------
 arch/mips/cavium-octeon/setup.c       |  3 +-
 arch/mips/include/asm/octeon/octeon.h |  1 +
 3 files changed, 66 insertions(+), 31 deletions(-)

diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
index ce6483a..0219395 100644
--- a/arch/mips/cavium-octeon/csrc-octeon.c
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -4,7 +4,7 @@
  * for more details.
  *
  * Copyright (C) 2007 by Ralf Baechle
- * Copyright (C) 2009, 2010 Cavium Networks, Inc.
+ * Copyright (C) 2009, 2012 Cavium, Inc.
  */
 #include <linux/clocksource.h>
 #include <linux/export.h>
@@ -18,6 +18,33 @@
 #include <asm/octeon/cvmx-ipd-defs.h>
 #include <asm/octeon/cvmx-mio-defs.h>
 
+
+static u64 f;
+static u64 rdiv;
+static u64 sdiv;
+static u64 octeon_udelay_factor;
+static u64 octeon_ndelay_factor;
+
+void __init octeon_setup_delays(void)
+{
+	octeon_udelay_factor = octeon_get_clock_rate() / 1000000;
+	/*
+	 * For __ndelay we divide by 2^16, so the factor is multiplied
+	 * by the same amount.
+	 */
+	octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull;
+
+	preset_lpj = octeon_get_clock_rate() / HZ;
+
+	if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
+		union cvmx_mio_rst_boot rst_boot;
+		rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
+		rdiv = rst_boot.s.c_mul;	/* CPU clock */
+		sdiv = rst_boot.s.pnr_mul;	/* I/O clock */
+		f = (0x8000000000000000ull / sdiv) * 2;
+	}
+}
+
 /*
  * Set the current core's cvmcount counter to the value of the
  * IPD_CLK_COUNT.  We do this on all cores as they are brought
@@ -30,17 +57,6 @@ void octeon_init_cvmcount(void)
 {
 	unsigned long flags;
 	unsigned loops = 2;
-	u64 f = 0;
-	u64 rdiv = 0;
-	u64 sdiv = 0;
-	if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
-		union cvmx_mio_rst_boot rst_boot;
-		rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
-		rdiv = rst_boot.s.c_mul;	/* CPU clock */
-		sdiv = rst_boot.s.pnr_mul;	/* I/O clock */
-		f = (0x8000000000000000ull / sdiv) * 2;
-	}
-
 
 	/* Clobber loops so GCC will not unroll the following while loop. */
 	asm("" : "+r" (loops));
@@ -57,9 +73,9 @@ void octeon_init_cvmcount(void)
 			if (f != 0) {
 				asm("dmultu\t%[cnt],%[f]\n\t"
 				    "mfhi\t%[cnt]"
-				    : [cnt] "+r" (ipd_clk_count),
-				      [f] "=r" (f)
-				    : : "hi", "lo");
+				    : [cnt] "+r" (ipd_clk_count)
+				    : [f] "r" (f)
+				    : "hi", "lo");
 			}
 		}
 		write_c0_cvmcount(ipd_clk_count);
@@ -109,21 +125,6 @@ void __init plat_time_init(void)
 	clocksource_register_hz(&clocksource_mips, octeon_get_clock_rate());
 }
 
-static u64 octeon_udelay_factor;
-static u64 octeon_ndelay_factor;
-
-void __init octeon_setup_delays(void)
-{
-	octeon_udelay_factor = octeon_get_clock_rate() / 1000000;
-	/*
-	 * For __ndelay we divide by 2^16, so the factor is multiplied
-	 * by the same amount.
-	 */
-	octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull;
-
-	preset_lpj = octeon_get_clock_rate() / HZ;
-}
-
 void __udelay(unsigned long us)
 {
 	u64 cur, end, inc;
@@ -163,3 +164,35 @@ void __delay(unsigned long loops)
 		cur = read_c0_cvmcount();
 }
 EXPORT_SYMBOL(__delay);
+
+
+/**
+ * octeon_io_clk_delay - wait for a given number of io clock cycles to pass.
+ *
+ * We scale the wait by the clock ratio, and then wait for the
+ * corresponding number of core clocks.
+ *
+ * @count: The number of clocks to wait.
+ */
+void octeon_io_clk_delay(unsigned long count)
+{
+	u64 cur, end;
+
+	cur = read_c0_cvmcount();
+	if (rdiv != 0) {
+		end = count * rdiv;
+		if (f != 0) {
+			asm("dmultu\t%[cnt],%[f]\n\t"
+				"mfhi\t%[cnt]"
+				: [cnt] "+r" (end)
+				: [f] "r" (f)
+				: "hi", "lo");
+		}
+		end = cur + end;
+	} else {
+		end = cur + count;
+	}
+	while (end > cur)
+		cur = read_c0_cvmcount();
+}
+EXPORT_SYMBOL(octeon_io_clk_delay);
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 919b0fb..04dd8ff 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -548,6 +548,8 @@ void __init prom_init(void)
 	}
 #endif
 
+	octeon_setup_delays();
+
 	/*
 	 * BIST should always be enabled when doing a soft reset. L2
 	 * Cache locking for instance is not cleared unless BIST is
@@ -611,7 +613,6 @@ void __init prom_init(void)
 	mips_hpt_frequency = octeon_get_clock_rate();
 
 	octeon_init_cvmcount();
-	octeon_setup_delays();
 
 	_machine_restart = octeon_restart;
 	_machine_halt = octeon_halt;
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index a31288e..96e58a5 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -52,6 +52,7 @@ extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
 
 extern void octeon_init_cvmcount(void);
 extern void octeon_setup_delays(void);
+extern void octeon_io_clk_delay(unsigned long);
 
 #define OCTEON_ARGV_MAX_ARGS	64
 #define OCTOEN_SERIAL_LEN	20
-- 
1.7.11.4

^ permalink raw reply related

* [PATCH 0/8] netdev/MIPS: Improvements to octeon_mgmt Ethernet driver.
From: David Daney @ 2012-08-21 18:45 UTC (permalink / raw)
  To: linux-mips, ralf, David S. Miller, netdev; +Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

Recent additions to the OCTEON SoC family have included enhancements
to the MIX (octeon_mgmt) Ethernet hardware.  These include:

o 1Gig support (up from 100M).

o Hardware timestamping for PTP.

Here we add support for these two features as well as some ethtool
improvements and cleanup of the MAC address handling.

Patch 1/8 is a prerequisite for the rest, and lives in the MIPS
architecture part of the tree.  Since octeon_mgmt devices are only
found in OCTEON SoCs we could merge the whole set via Ralf's tree, or
get Ralf to affix his Acked-by and have it go via the netdev tree.


Chad Reese (1):
  netdev: octeon_mgmt: Add hardware timestamp support.

David Daney (7):
  MIPS: Octeon: Add octeon_io_clk_delay() function.
  netdev: octeon_mgmt: Add support for 1Gig ports.
  netdev: octeon_mgmt: Improve ethtool_ops.
  netdev: octeon_mgmt: Set the parent device.
  netdev: octeon_mgmt: Cleanup and modernize MAC address handling.
  netdev: octeon_mgmt: Remove some useless 'inline'
  netdev: octeon_mgmt: Make multi-line comment style consistent.

 arch/mips/cavium-octeon/csrc-octeon.c     |  93 +++--
 arch/mips/cavium-octeon/setup.c           |   3 +-
 arch/mips/include/asm/octeon/octeon.h     |   1 +
 drivers/net/ethernet/octeon/octeon_mgmt.c | 554 ++++++++++++++++++++++++------
 4 files changed, 512 insertions(+), 139 deletions(-)

-- 
1.7.11.4

^ permalink raw reply

* Re: [PATCH v6] bonding support for IPv6 transmit hashing
From: Jeremy Brookman @ 2012-08-21 18:11 UTC (permalink / raw)
  To: linux, netdev
In-Reply-To: <20120702.224351.1587084404665143719.davem@davemloft.net>

> You should use a mix of tabs, as necessary, to get things to line up
> how I told you they need to line up.

Unless I'm missing something, this change doesn't seem to have made it
through to the kernel tip, but we could really use this bugfix. Is it
in a repository I didn't notice, or not yet through the review?  If
it's not through the review, is any help needed to get it there?

Regards,

Jeremy Brookman

^ permalink raw reply

* Re: Do I need to skb_put() Ethernet frames to a minimum of 60 bytes?
From: Ben Hutchings @ 2012-08-21 18:07 UTC (permalink / raw)
  To: Arvid Brodin; +Cc: Nicolas Ferre, netdev@vger.kernel.org
In-Reply-To: <5033C6B0.4060508@xdin.com>

On Tue, 2012-08-21 at 17:34 +0000, Arvid Brodin wrote:
> On 2012-08-14 22:35, Ben Hutchings wrote:
> > On Tue, 2012-08-14 at 18:53 +0000, Arvid Brodin wrote:
> >> Hi,
> >>
> >> If I create an sk_buff with a payload of less than 28 bytes (ethheader + data),
> >> and send it using the cadence/macb (Ethernet) driver, I get
> >>
> >> eth0: TX underrun, resetting buffers
> >>
> >> Now I know the minimum Ethernet frame size is 64 bytes (including the 4-byte
> >> FCS), but whose responsibility is it to pad the frame to this size if necessary?
> >> Mine or the driver's - i.e. should I just skb_put() to the minimum size or
> >> should I report the underrun as a driver bug?
> > 
> > If the hardware doesn't pad frames automatically then it's the driver's
> > reponsibility to do so.
> > 
> 
> Nicolas, can you take a look at this? At the moment I'm using the following change
> in macb.c to avoid TX underruns on short packages:
> 
> --- a/drivers/net/ethernet/cadence/macb.c	2012-05-04 19:14:41.927719667 +0200
> +++ b/drivers/net/ethernet/cadence/macb.c	2012-08-21 19:22:40.063739049 +0200
> @@ -618,6 +618,7 @@ static void macb_poll_controller(struct
>  }
>  #endif
> 
> +#define MIN_ETHFRAME_LEN	60

<linux/etherdevice.h> already names this as ETH_ZLEN, by the way.

>  static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  {
>  	struct macb *bp = netdev_priv(dev);
> @@ -635,6 +636,12 @@ static int macb_start_xmit(struct sk_buf
>  	printk("\n");
>  #endif
> 
> +	if (skb->len < MIN_ETHFRAME_LEN) {
> +		/* Pad skb to minium Ethernet frame size */
> +		if (skb_tailroom(skb) >= MIN_ETHFRAME_LEN - skb->len)
> +			memset(skb_put(skb, MIN_ETHFRAME_LEN - skb->len), 0,
> +						MIN_ETHFRAME_LEN - skb->len);
> +	}
>  	len = skb->len;
>  	spin_lock_irqsave(&bp->lock, flags);
> 
> 
> ... but as you can see this is limited to linear skbs which has been allocated with
> enough tailroom. Perhaps there are better ways to fix the problem?

skb_padto() should be all you need.  Note that it frees the skb on
failure, so you must just return NETDEV_TX_OK then.

Ben.

> (Maybe the hardware
> is actually doing the padding already and the problem has to do with the way the DMA
> transfer is set up?)

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: IP fragmentation broken in 3.6-rc ?
From: Sylvain Munaut @ 2012-08-21 17:44 UTC (permalink / raw)
  Cc: netdev
In-Reply-To: <1345560131.5158.500.camel@edumazet-glaptop>

Hi,

> Following patch should help :
>
> diff --git a/include/net/dst.h b/include/net/dst.h
> index 621e351..a04aa37 100644
> --- a/include/net/dst.h
> +++ b/include/net/dst.h
> @@ -435,7 +435,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
>         if (expires == 0)
>                 expires = 1;
>
> -       if (dst->expires == 0 || time_before(expires, dst->expires))
> +       if (dst->expires == 0 || time_after(expires, dst->expires))
>                 dst->expires = expires;
>  }

Yes, this fixes it for me too . ( 2h without issues on 2 different machines )

But that line has been in the kernel for _years_ ... so I'm not sure
what's going on there ...


Cheers,

    Sylvain

^ permalink raw reply

* Re: Do I need to skb_put() Ethernet frames to a minimum of 60 bytes?
From: Eric Dumazet @ 2012-08-21 17:42 UTC (permalink / raw)
  To: Arvid Brodin; +Cc: Nicolas Ferre, Ben Hutchings, netdev@vger.kernel.org
In-Reply-To: <5033C6B0.4060508@xdin.com>

On Tue, 2012-08-21 at 17:34 +0000, Arvid Brodin wrote:

> Nicolas, can you take a look at this? At the moment I'm using the following change
> in macb.c to avoid TX underruns on short packages:
> 
> --- a/drivers/net/ethernet/cadence/macb.c	2012-05-04 19:14:41.927719667 +0200
> +++ b/drivers/net/ethernet/cadence/macb.c	2012-08-21 19:22:40.063739049 +0200
> @@ -618,6 +618,7 @@ static void macb_poll_controller(struct
>  }
>  #endif
> 
> +#define MIN_ETHFRAME_LEN	60
>  static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  {
>  	struct macb *bp = netdev_priv(dev);
> @@ -635,6 +636,12 @@ static int macb_start_xmit(struct sk_buf
>  	printk("\n");
>  #endif
> 
> +	if (skb->len < MIN_ETHFRAME_LEN) {
> +		/* Pad skb to minium Ethernet frame size */
> +		if (skb_tailroom(skb) >= MIN_ETHFRAME_LEN - skb->len)
> +			memset(skb_put(skb, MIN_ETHFRAME_LEN - skb->len), 0,
> +						MIN_ETHFRAME_LEN - skb->len);
> +	}
>  	len = skb->len;
>  	spin_lock_irqsave(&bp->lock, flags);
> 
> 
> ... but as you can see this is limited to linear skbs which has been allocated with
> enough tailroom. Perhaps there are better ways to fix the problem? (Maybe the hardware
> is actually doing the padding already and the problem has to do with the way the DMA
> transfer is set up?)
> 

other net drivers use skb_padto() for this ...

^ permalink raw reply

* Re: Do I need to skb_put() Ethernet frames to a minimum of 60 bytes?
From: Arvid Brodin @ 2012-08-21 17:34 UTC (permalink / raw)
  To: Nicolas Ferre; +Cc: Ben Hutchings, netdev@vger.kernel.org
In-Reply-To: <1344976557.2690.43.camel@bwh-desktop.uk.solarflarecom.com>

On 2012-08-14 22:35, Ben Hutchings wrote:
> On Tue, 2012-08-14 at 18:53 +0000, Arvid Brodin wrote:
>> Hi,
>>
>> If I create an sk_buff with a payload of less than 28 bytes (ethheader + data),
>> and send it using the cadence/macb (Ethernet) driver, I get
>>
>> eth0: TX underrun, resetting buffers
>>
>> Now I know the minimum Ethernet frame size is 64 bytes (including the 4-byte
>> FCS), but whose responsibility is it to pad the frame to this size if necessary?
>> Mine or the driver's - i.e. should I just skb_put() to the minimum size or
>> should I report the underrun as a driver bug?
> 
> If the hardware doesn't pad frames automatically then it's the driver's
> reponsibility to do so.
> 

Nicolas, can you take a look at this? At the moment I'm using the following change
in macb.c to avoid TX underruns on short packages:

--- a/drivers/net/ethernet/cadence/macb.c	2012-05-04 19:14:41.927719667 +0200
+++ b/drivers/net/ethernet/cadence/macb.c	2012-08-21 19:22:40.063739049 +0200
@@ -618,6 +618,7 @@ static void macb_poll_controller(struct
 }
 #endif

+#define MIN_ETHFRAME_LEN	60
 static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct macb *bp = netdev_priv(dev);
@@ -635,6 +636,12 @@ static int macb_start_xmit(struct sk_buf
 	printk("\n");
 #endif

+	if (skb->len < MIN_ETHFRAME_LEN) {
+		/* Pad skb to minium Ethernet frame size */
+		if (skb_tailroom(skb) >= MIN_ETHFRAME_LEN - skb->len)
+			memset(skb_put(skb, MIN_ETHFRAME_LEN - skb->len), 0,
+						MIN_ETHFRAME_LEN - skb->len);
+	}
 	len = skb->len;
 	spin_lock_irqsave(&bp->lock, flags);


... but as you can see this is limited to linear skbs which has been allocated with
enough tailroom. Perhaps there are better ways to fix the problem? (Maybe the hardware
is actually doing the padding already and the problem has to do with the way the DMA
transfer is set up?)


-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Jan Stenbecks Torg 17 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply

* Re: IP fragmentation broken in 3.6-rc ?
From: Eric Dumazet @ 2012-08-21 17:23 UTC (permalink / raw)
  To: Julian Anastasov; +Cc: Sylvain Munaut, netdev
In-Reply-To: <alpine.LFD.2.00.1208211954380.2149@ja.ssi.bg>

On Tue, 2012-08-21 at 20:18 +0300, Julian Anastasov wrote:
> 	Hello,
> 
> On Tue, 21 Aug 2012, Eric Dumazet wrote:

> > My first patch was :
> > 
> > diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> > index e4ba974..9858714 100644
> > --- a/net/ipv4/route.c
> > +++ b/net/ipv4/route.c
> > @@ -956,6 +956,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
> >  		dst->obsolete = DST_OBSOLETE_KILL;
> >  	} else {
> >  		rt->rt_pmtu = mtu;
> > +		rt->dst.expires = 0;
> >  		dst_set_expires(&rt->dst, ip_rt_mtu_expires);
> 
> 	This is better, does not break ipv4_link_failure.
> There is a little race some ipv4_mtu() user to see
> rt_pmtu != 0 and dst.expires = 0 and to fail in time_after_eq
> test. May be that is why dst.expires is never set to 0.
> But I still don't understand what both changes fix.

In fact we re-enter ip_rt_update_pmtu() if we receive a second ICMP,
and rt->rt_pmtu is already set, but dst is expired.

Thats why Sylvain said it was not happening in the 10 minutes following
boot.

So calling again dst_set_expires(&rt->dst, ip_rt_mtu_expires) does
nothing : rt_pmtu is ignored because dst.expires is too old.

Maybe we should just do :

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e4ba974..d0181e2 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -952,7 +952,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 	ip_rt_build_flow_key(&fl4, sk, skb);
 	mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);
 
-	if (!rt->rt_pmtu) {
+	if (!rt->rt_pmtu || time_after_eq(jiffies, rt->dst.expires)) {
 		dst->obsolete = DST_OBSOLETE_KILL;
 	} else {
 		rt->rt_pmtu = mtu;

^ permalink raw reply related

* Re: [PATCH] tun: don't zeroize sock->file on detach
From: Neal Cardwell @ 2012-08-21 17:18 UTC (permalink / raw)
  To: Stanislav Kinsbursky
  Cc: David Miller, dhowells@redhat.com, netdev@vger.kernel.org,
	rick.jones2@hp.com, ycheng@google.com,
	linux-kernel@vger.kernel.org, mikulas
In-Reply-To: <5033B199.6080305@parallels.com>

On Tue, Aug 21, 2012 at 12:04 PM, Stanislav Kinsbursky
<skinsbursky@parallels.com> wrote:
> 10.08.2012 03:16, David Miller пишет:
>
>> From: Stanislav Kinsbursky <skinsbursky@parallels.com>
>> Date: Thu, 09 Aug 2012 16:50:40 +0400
>>
>>> This is a fix for bug, introduced in 3.4 kernel by commit
>>> 1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d, which, among other things,
>>> replaced
>>> simple sock_put() by sk_release_kernel(). Below is sequence, which leads
>>> to
>>> oops for non-persistent devices:
>>>
>>> tun_chr_close()
>>> tun_detach()                            <== tun->socket.file = NULL
>>> tun_free_netdev()
>>> sk_release_sock()
>>> sock_release(sock->file == NULL)
>>> iput(SOCK_INODE(sock))                  <== dereference on NULL pointer
>>>
>>> This patch just removes zeroing of socket's file from __tun_detach().
>>> sock_release() will do this.
>>>
>>> Cc: stable@vger.kernel.org
>>> Reported-by: Ruan Zhijie <ruanzhijie@hotmail.com>
>>> Tested-by: Ruan Zhijie <ruanzhijie@hotmail.com>
>>> Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
>>> Acked-by: Eric Dumazet <edumazet@google.com>
>>> Acked-by: Yuchung Cheng <ycheng@google.com>
>>> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
>>
>>
>> Applied, thanks.
>>
>
> Hi, David.
> I found out, that this commit: b09e786bd1dd66418b69348cb110f3a64764626a
> was previous attempt to fix the problem.
> I believe this commit have to be dropped.

Have you tried testing with that commit reverted? AFAICT from reading
the code, if you revert b09e786bd1dd66418b69348cb110f3a64764626a then
the sockets_in_use count becomes incorrect, because sock_release()
will be calling this_cpu_sub() for each tun socket teardown when there
was no corresponding this_cpu_add() for the tun socket (because the
tun socket is not allocated with sock_alloc()).

Can you sketch in more detail why that commit should be dropped?

neal

^ permalink raw reply

* Re: IP fragmentation broken in 3.6-rc ?
From: Julian Anastasov @ 2012-08-21 17:18 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Sylvain Munaut, netdev
In-Reply-To: <1345567633.5158.534.camel@edumazet-glaptop>


	Hello,

On Tue, 21 Aug 2012, Eric Dumazet wrote:

> On Tue, 2012-08-21 at 19:34 +0300, Julian Anastasov wrote:
> > 	Hello,
> > 
> > On Tue, 21 Aug 2012, Eric Dumazet wrote:
> > 
> > > Following patch should help :
> > > 
> > > diff --git a/include/net/dst.h b/include/net/dst.h
> > > index 621e351..a04aa37 100644
> > > --- a/include/net/dst.h
> > > +++ b/include/net/dst.h
> > > @@ -435,7 +435,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
> > >  	if (expires == 0)
> > >  		expires = 1;
> > >  
> > 
> > 	In theory, restart of PMTUD should not lead to
> > fatal problems, we will get new MTUs. But with such
> > change should be better, not much, because all MTU
> > events will come at same time, later timer will expire
> > and we will get again events from routers. The gain
> > will be an increased period (with milliseconds to seconds)
> > between PMTUD restarts. Compared to the 600-second timer,
> > this should be gain below 1% in reduced traffic for PMTUD.
> > Before now we started timer from first router, now we
> > will start/update timer period after event from last router.
> > 
> 
> Sorry I dont really understand what you mean

	This timer is used only for PMTU, right?
RFC 1191 6.3. Purging stale PMTU information.

> > 	But ipv4_link_failure and ip6_link_failure want to stop
> > this timer by setting it to NOW (0). May be we have to add
> > also a !timeout check here or to leave the code as before?
> > 
> > > -	if (dst->expires == 0 || time_before(expires, dst->expires))
> > > +	if (dst->expires == 0 || time_after(expires, dst->expires))
> > >  		dst->expires = expires;
> > >  }
> > 
> > 	The original problem should be somewhere else, I think.
> 
> This patch fixed the problem for me.

	OK, then I'll wait for the patch description
to understand what this change actually does. For me,
it just updates the timer on every MTU event, while
before the change, PMTU timer was started only once and
during the 600-second period it was not updated and also
there was the ability to invalidate the PMTU on link failure
by setting timer to jiffies, i.e. to stop this period
and to start new one with default MTU and possibly
new discovery procedure.

> My first patch was :
> 
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index e4ba974..9858714 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -956,6 +956,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
>  		dst->obsolete = DST_OBSOLETE_KILL;
>  	} else {
>  		rt->rt_pmtu = mtu;
> +		rt->dst.expires = 0;
>  		dst_set_expires(&rt->dst, ip_rt_mtu_expires);

	This is better, does not break ipv4_link_failure.
There is a little race some ipv4_mtu() user to see
rt_pmtu != 0 and dst.expires = 0 and to fail in time_after_eq
test. May be that is why dst.expires is never set to 0.
But I still don't understand what both changes fix.

Regards

--
Julian Anastasov <ja@ssi.bg>

^ permalink raw reply

* RE: [PATCH] ethtool: don't overwrite useful bits in advertising bitfield
From: Ben Hutchings @ 2012-08-21 17:03 UTC (permalink / raw)
  To: Johan Gunnarsson; +Cc: netdev@vger.kernel.org, Mikael Starvik
In-Reply-To: <A612847CFE53224C91B23E3A5B48BAC7534E8D7809@xmail3.se.axis.com>

On Tue, 2012-08-21 at 18:45 +0200, Johan Gunnarsson wrote:
[...]
> > > > > @@ -2405,19 +2421,20 @@ static int do_sset(struct cmd_context
> > *ctx)
> > > > >  			}
> > > > >  			if (autoneg_wanted == AUTONEG_ENABLE &&
> > > > >  			    advertising_wanted == 0) {
> > > > > -				ecmd.advertising = ecmd.supported &
> > > > > -					(ADVERTISED_10baseT_Half |
> > > > > -					 ADVERTISED_10baseT_Full |
> > > > > -					 ADVERTISED_100baseT_Half |
> > > > > -					 ADVERTISED_100baseT_Full |
> > > > > -					 ADVERTISED_1000baseT_Half |
> > > > > -					 ADVERTISED_1000baseT_Full |
> > > > > -					 ADVERTISED_2500baseX_Full |
> > > > > -					 ADVERTISED_10000baseT_Full |
> > > > > -					 ADVERTISED_20000baseMLD2_Full |
> > > > > -					 ADVERTISED_20000baseKR2_Full);
> > > > > +				/* Auto negotation enabled, but with
> > > > > +				 * unspecified speed and duplex: enable
> > all
> > > > > +				 * supported speeds and duplexes.
> > > > > +				 */
> > > > > +				ecmd.advertising = (ecmd.advertising &
> > > > > +					~ALL_ADVERTISED_MODES) |
> > > > > +					(ALL_ADVERTISED_MODES &
> > ecmd.supported);
> > > >
> > > > Perhaps we should also warn if there's a 'supported' flag we don't
> > > > recognise, because we don't know whether it's a link mode and we
> > might
> > > > be failing to enable/disable it as requested.
> > >
> > > You mean if ecmd.supported has bits enabled that ALL_ADVERTISED_MODES
> > > hasn't? I don't think that's a good idea, because that happens very
> > > often (for example PAUSE bits in my case.)
> > 
> > No, I mean if it has bits enabled that are not defined at all
> > (currently
> > any of bits 27-31).
> 
> Not totally sure I follow. Care to show me?
[...]

<linux/ethtool.h> or ethtool-copy.h currently defines the meanings of
bits 0-26 in the supported field.  You define ALL_ADVERTISED_MODES to
include all of those that are link modes.  But some time in the future,
the remaining bits will be assigned to new capabilities.

If today's ethtool is used with a newer driver that sets bit 27 in its
supported field, ethtool can't tell whether that represents a new link
mode that should be included in ALL_ADVERTISED_MODES, or some other kind
of capability.  So it may not be able to set the driver's advertising
mask correctly.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: IP fragmentation broken in 3.6-rc ?
From: Eric Dumazet @ 2012-08-21 16:47 UTC (permalink / raw)
  To: Julian Anastasov; +Cc: Sylvain Munaut, netdev
In-Reply-To: <alpine.LFD.2.00.1208211815550.2149@ja.ssi.bg>

On Tue, 2012-08-21 at 19:34 +0300, Julian Anastasov wrote:
> 	Hello,
> 
> On Tue, 21 Aug 2012, Eric Dumazet wrote:
> 
> > Following patch should help :
> > 
> > diff --git a/include/net/dst.h b/include/net/dst.h
> > index 621e351..a04aa37 100644
> > --- a/include/net/dst.h
> > +++ b/include/net/dst.h
> > @@ -435,7 +435,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
> >  	if (expires == 0)
> >  		expires = 1;
> >  
> 
> 	In theory, restart of PMTUD should not lead to
> fatal problems, we will get new MTUs. But with such
> change should be better, not much, because all MTU
> events will come at same time, later timer will expire
> and we will get again events from routers. The gain
> will be an increased period (with milliseconds to seconds)
> between PMTUD restarts. Compared to the 600-second timer,
> this should be gain below 1% in reduced traffic for PMTUD.
> Before now we started timer from first router, now we
> will start/update timer period after event from last router.
> 

Sorry I dont really understand what you mean


> 	But ipv4_link_failure and ip6_link_failure want to stop
> this timer by setting it to NOW (0). May be we have to add
> also a !timeout check here or to leave the code as before?
> 
> > -	if (dst->expires == 0 || time_before(expires, dst->expires))
> > +	if (dst->expires == 0 || time_after(expires, dst->expires))
> >  		dst->expires = expires;
> >  }
> 
> 	The original problem should be somewhere else, I think.

This patch fixed the problem for me.

My first patch was :

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e4ba974..9858714 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -956,6 +956,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 		dst->obsolete = DST_OBSOLETE_KILL;
 	} else {
 		rt->rt_pmtu = mtu;
+		rt->dst.expires = 0;
 		dst_set_expires(&rt->dst, ip_rt_mtu_expires);
 	}
 }

^ permalink raw reply related

* RE: [PATCH] ethtool: don't overwrite useful bits in advertising bitfield
From: Johan Gunnarsson @ 2012-08-21 16:45 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev@vger.kernel.org, Mikael Starvik
In-Reply-To: <1345561910.2659.45.camel@bwh-desktop.uk.solarflarecom.com>



> -----Original Message-----
> From: Ben Hutchings [mailto:bhutchings@solarflare.com]
> Sent: den 21 augusti 2012 17:12
> To: Johan Gunnarsson
> Cc: netdev@vger.kernel.org; Mikael Starvik
> Subject: RE: [PATCH] ethtool: don't overwrite useful bits in
> advertising bitfield
> 
> On Tue, 2012-08-21 at 10:41 +0200, Johan Gunnarsson wrote:
> >
> > > -----Original Message-----
> > > From: netdev-owner@vger.kernel.org [mailto:netdev-
> > > owner@vger.kernel.org] On Behalf Of Ben Hutchings
> > > Sent: den 20 augusti 2012 17:23
> > > To: Johan Gunnarsson
> > > Cc: netdev@vger.kernel.org; Mikael Starvik
> > > Subject: Re: [PATCH] ethtool: don't overwrite useful bits in
> > > advertising bitfield
> > >
> > > On Tue, 2012-08-14 at 16:15 +0200, Johan Gunnarsson wrote:
> > > > There are bits in this bitfield that we want to leave untouched
> > > (PAUSE
> > > > and ASYM_PAUSE bits) when changing other bits (speed and duplex
> > > bits.)
> > > > Previously, these were always overwritten to zero when running
> > > commands
> > > > like "ethtool -s eth0 speed 10 duplex full autoneg off".
> > >
> > > This is right in principle, but the implementation isn't quite
> right.
> > >
> > > > Signed-off-by: Johan Gunnarsson <johangu@axis.com>
> > > > ---
> > > >  ethtool.c |   45 +++++++++++++++++++++++++++++++--------------
> > > >  1 file changed, 31 insertions(+), 14 deletions(-)
> > > >
> > > > diff --git a/ethtool.c b/ethtool.c
> > > > index e573357..efa12c7 100644
> > > > --- a/ethtool.c
> > > > +++ b/ethtool.c
> > > > @@ -46,6 +46,18 @@
> > > >  #define MAX_ADDR_LEN	32
> > > >  #endif
> > > >
> > > > +#define ALL_ADVERTISED_MODES \
> > > > +	(ADVERTISED_10baseT_Half | \
> > > > +	 ADVERTISED_10baseT_Full | \
> > > > +	 ADVERTISED_100baseT_Half | \
> > > > +	 ADVERTISED_100baseT_Full | \
> > > > +	 ADVERTISED_1000baseT_Half | \
> > > > +	 ADVERTISED_1000baseT_Full | \
> > > > +	 ADVERTISED_2500baseX_Full | \
> > > > +	 ADVERTISED_10000baseT_Full | \
> > > > +	 ADVERTISED_20000baseMLD2_Full | \
> > > > +	 ADVERTISED_20000baseKR2_Full)
> > >
> > > This is missing the new 40G modes (not a regression, I realise).
> >
> > I'll add the 40G modes. There is also a bunch of 10G modes missing.
> Shall I add these too?
> 
> Yes please.

Alright.

> 
> > >
> > > [...]
> > > > @@ -2405,19 +2421,20 @@ static int do_sset(struct cmd_context
> *ctx)
> > > >  			}
> > > >  			if (autoneg_wanted == AUTONEG_ENABLE &&
> > > >  			    advertising_wanted == 0) {
> > > > -				ecmd.advertising = ecmd.supported &
> > > > -					(ADVERTISED_10baseT_Half |
> > > > -					 ADVERTISED_10baseT_Full |
> > > > -					 ADVERTISED_100baseT_Half |
> > > > -					 ADVERTISED_100baseT_Full |
> > > > -					 ADVERTISED_1000baseT_Half |
> > > > -					 ADVERTISED_1000baseT_Full |
> > > > -					 ADVERTISED_2500baseX_Full |
> > > > -					 ADVERTISED_10000baseT_Full |
> > > > -					 ADVERTISED_20000baseMLD2_Full |
> > > > -					 ADVERTISED_20000baseKR2_Full);
> > > > +				/* Auto negotation enabled, but with
> > > > +				 * unspecified speed and duplex: enable
> all
> > > > +				 * supported speeds and duplexes.
> > > > +				 */
> > > > +				ecmd.advertising = (ecmd.advertising &
> > > > +					~ALL_ADVERTISED_MODES) |
> > > > +					(ALL_ADVERTISED_MODES &
> ecmd.supported);
> > >
> > > Perhaps we should also warn if there's a 'supported' flag we don't
> > > recognise, because we don't know whether it's a link mode and we
> might
> > > be failing to enable/disable it as requested.
> >
> > You mean if ecmd.supported has bits enabled that ALL_ADVERTISED_MODES
> > hasn't? I don't think that's a good idea, because that happens very
> > often (for example PAUSE bits in my case.)
> 
> No, I mean if it has bits enabled that are not defined at all
> (currently
> any of bits 27-31).

Not totally sure I follow. Care to show me?

> 
> > >
> > > >  			} else if (advertising_wanted > 0) {
> > > > -				ecmd.advertising = advertising_wanted;
> > > > +				/* Enable all requested modes */
> > > > +				ecmd.advertising = (ecmd.advertising &
> > > > +					~ALL_ADVERTISED_MODES) |
> > > > +					(advertising_wanted &
> ecmd.supported);
> > >
> > > I don't think the '& ecmd.supported' here is right.  If an autoneg
> > > device supports some new link mode L that is not in
> > > ALL_ADVERTISED_MODES, but not link mode M which the user requested,
> > > then
> > > this can silently fail because the resulting advertising mask will
> > > include L but not M.
> > >
> > > We should either use advertising_wanted unmasked and let the driver
> > > validate it, or report an error if it's not present in the
> supported
> > > mask.  I think we should be consistent with the following case,
> i.e.
> > > let
> > > the driver validate it.
> >
> > How about remove "& ecmd.supported", but also warn if trying to add
> an
> > unsupported mode? Similar to the previous case.
> [...]
> 
> I don't think this is similar and I don't think we need to do both.

So let's go for the removed "& ecmd.supported" then.

> 
> Ben.
> 
> --
> Ben Hutchings, Staff Engineer, Solarflare
> Not speaking for my employer; that's the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: IP fragmentation broken in 3.6-rc ?
From: Julian Anastasov @ 2012-08-21 16:34 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Sylvain Munaut, netdev
In-Reply-To: <1345560131.5158.500.camel@edumazet-glaptop>


	Hello,

On Tue, 21 Aug 2012, Eric Dumazet wrote:

> Following patch should help :
> 
> diff --git a/include/net/dst.h b/include/net/dst.h
> index 621e351..a04aa37 100644
> --- a/include/net/dst.h
> +++ b/include/net/dst.h
> @@ -435,7 +435,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
>  	if (expires == 0)
>  		expires = 1;
>  

	In theory, restart of PMTUD should not lead to
fatal problems, we will get new MTUs. But with such
change should be better, not much, because all MTU
events will come at same time, later timer will expire
and we will get again events from routers. The gain
will be an increased period (with milliseconds to seconds)
between PMTUD restarts. Compared to the 600-second timer,
this should be gain below 1% in reduced traffic for PMTUD.
Before now we started timer from first router, now we
will start/update timer period after event from last router.

	But ipv4_link_failure and ip6_link_failure want to stop
this timer by setting it to NOW (0). May be we have to add
also a !timeout check here or to leave the code as before?

> -	if (dst->expires == 0 || time_before(expires, dst->expires))
> +	if (dst->expires == 0 || time_after(expires, dst->expires))
>  		dst->expires = expires;
>  }

	The original problem should be somewhere else, I think.

Regards

--
Julian Anastasov <ja@ssi.bg>

^ permalink raw reply

* [PATCH] af_netlink: force credentials passing [CVE-2012-3520]
From: Eric Dumazet @ 2012-08-21 16:21 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Petr Matousek, Florian Weimer, Pablo Neira Ayuso

From: Eric Dumazet <edumazet@google.com>

Pablo Neira Ayuso discovered that avahi and 
potentially NetworkManager accept spoofed Netlink messages because of a 
kernel bug.  The kernel passes all-zero SCM_CREDENTIALS ancillary data 
to the receiver if the sender did not provide such data, instead of not 
including any such data at all or including the correct data from the 
peer (as it is the case with AF_UNIX).

This bug was introduced in commit 16e572626961
(af_unix: dont send SCM_CREDENTIALS by default)

This patch forces passing credentials for netlink, as
before the regression.

Another fix would be to not add SCM_CREDENTIALS in
netlink messages if not provided by the sender, but it
might break some programs.

With help from Florian Weimer & Petr Matousek

This issue is designated as CVE-2012-3520

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Petr Matousek <pmatouse@redhat.com>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/scm.h        |    4 +++-
 net/netlink/af_netlink.c |    2 +-
 net/unix/af_unix.c       |    4 ++--
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/net/scm.h b/include/net/scm.h
index 079d788..7dc0854 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
 }
 
 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
-			       struct scm_cookie *scm)
+			       struct scm_cookie *scm, bool forcecreds)
 {
 	memset(scm, 0, sizeof(*scm));
+	if (forcecreds)
+		scm_set_cred(scm, task_tgid(current), current_cred());
 	unix_get_peersec_dgram(sock, scm);
 	if (msg->msg_controllen <= 0)
 		return 0;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5463969..1445d73 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (NULL == siocb->scm)
 		siocb->scm = &scm;
 
-	err = scm_send(sock, msg, siocb->scm);
+	err = scm_send(sock, msg, siocb->scm, true);
 	if (err < 0)
 		return err;
 
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e4768c1..c5ee4ff 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
 	wait_for_unix_gc();
-	err = scm_send(sock, msg, siocb->scm);
+	err = scm_send(sock, msg, siocb->scm, false);
 	if (err < 0)
 		return err;
 
@@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
 	wait_for_unix_gc();
-	err = scm_send(sock, msg, siocb->scm);
+	err = scm_send(sock, msg, siocb->scm, false);
 	if (err < 0)
 		return err;
 

^ permalink raw reply related

* Re: [PATCH] tun: don't zeroize sock->file on detach
From: Stanislav Kinsbursky @ 2012-08-21 16:04 UTC (permalink / raw)
  To: David Miller
  Cc: dhowells@redhat.com, netdev@vger.kernel.org, rick.jones2@hp.com,
	ycheng@google.com, linux-kernel@vger.kernel.org, mikulas
In-Reply-To: <20120809.161639.1789560369123168415.davem@davemloft.net>

10.08.2012 03:16, David Miller пишет:
> From: Stanislav Kinsbursky <skinsbursky@parallels.com>
> Date: Thu, 09 Aug 2012 16:50:40 +0400
>
>> This is a fix for bug, introduced in 3.4 kernel by commit
>> 1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d, which, among other things, replaced
>> simple sock_put() by sk_release_kernel(). Below is sequence, which leads to
>> oops for non-persistent devices:
>>
>> tun_chr_close()
>> tun_detach()				<== tun->socket.file = NULL
>> tun_free_netdev()
>> sk_release_sock()
>> sock_release(sock->file == NULL)
>> iput(SOCK_INODE(sock))			<== dereference on NULL pointer
>>
>> This patch just removes zeroing of socket's file from __tun_detach().
>> sock_release() will do this.
>>
>> Cc: stable@vger.kernel.org
>> Reported-by: Ruan Zhijie <ruanzhijie@hotmail.com>
>> Tested-by: Ruan Zhijie <ruanzhijie@hotmail.com>
>> Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
>> Acked-by: Eric Dumazet <edumazet@google.com>
>> Acked-by: Yuchung Cheng <ycheng@google.com>
>> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
>
> Applied, thanks.
>

Hi, David.
I found out, that this commit: b09e786bd1dd66418b69348cb110f3a64764626a
was previous attempt to fix the problem.
I believe this commit have to be dropped.


-- 
Best regards,
Stanislav Kinsbursky

^ permalink raw reply

* Getting VLANS to the vm ping / UDP working but TCP not
From: Andrew Holway @ 2012-08-21 14:03 UTC (permalink / raw)
  To: kvm

Hi,

I am trying out a couple of methods to get VLANs to the VM. In both cases the VM can ping google et all without problem and DNS works fine but it does not want to do any TCP. I thought this might be a frame size problem but even using telnet (which I understand sends tiny packets) fails to work.

Why would udp / ping work fine when tcp fails?

I saw some kind of weird packet on the bridge when I was trying to connect to a web server running on the VM with telnet.

15:11:47.464656 01:00:00:0e:00:24 (oui Unknown) > 00:00:01:00:00:00 (oui Unknown), ethertype Unknown (0xdcd9), length 66: 
	0x0000:  84a8 0800 4510 0030 cd23 4000 4006 527b  ....E..0.#@.@.R{
	0x0010:  257b 6811 257b 6812 f487 0050 da75 1e54  %{h.%{h....P.u.T
	0x0020:  0000 0000 7002 ffff 7b65 0000 0204 05b4  ....p...{e......
	0x0030:  0402 0000

But its hard to repeat them.

Any ideas?

Thanks,

Andrew


a) vm001 is on node002 and has the following xml:

[root@node002 ~]# virsh dumpxml vm001
...
   <interface type='bridge'>
     <mac address='00:00:00:00:00:0e'/>
     <source bridge='br0'/>
     <target dev='vnet0'/>
     <alias name='net0'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
   </interface>
   <interface type='bridge'>
     <mac address='00:00:01:00:00:0e'/>
     <source bridge='br1'/>
     <target dev='vnet1'/>
     <model type='e1000'/>
     <alias name='net1'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
   </interface>
…

[root@vm001 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
   inet6 ::1/128 scope host 
      valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
   link/ether 00:00:00:00:00:0e brd ff:ff:ff:ff:ff:ff
   inet 10.141.100.1/16 brd 10.141.255.255 scope global eth0
   inet6 fe80::200:ff:fe00:e/64 scope link 
      valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
   link/ether 00:00:01:00:00:0e brd ff:ff:ff:ff:ff:ff

###
4: eth1.4@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
   link/ether 00:00:01:00:00:0e brd ff:ff:ff:ff:ff:ff
   inet 37.123.104.18/29 brd 37.123.104.23 scope global eth1.4
   inet6 fe80::200:1ff:fe00:e/64 scope link 
      valid_lft forever preferred_lft forever
###


[root@node002 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
   inet6 ::1/128 scope host 
      valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state UNKNOWN qlen 1000
   link/ether 00:02:c9:34:67:31 brd ff:ff:ff:ff:ff:ff
   inet 192.168.0.1/24 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
   link/ether 00:9c:02:24:1a:e0 brd ff:ff:ff:ff:ff:ff
   inet6 fe80::29c:2ff:fe24:1ae0/64 scope link 
      valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1522 qdisc mq state UP qlen 1000
   link/ether 00:9c:02:24:1a:e4 brd ff:ff:ff:ff:ff:ff
   inet6 fe80::29c:2ff:fe24:1ae4/64 scope link 
      valid_lft forever preferred_lft forever
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
   link/ether 00:9c:02:24:1a:e0 brd ff:ff:ff:ff:ff:ff
   inet 10.141.0.2/16 brd 10.141.255.255 scope global br0
   inet6 fe80::29c:2ff:fe24:1ae0/64 scope link 
      valid_lft forever preferred_lft forever
7: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1522 qdisc noqueue state UNKNOWN 
   link/ether 00:9c:02:24:1a:e4 brd ff:ff:ff:ff:ff:ff
   inet6 fe80::29c:2ff:fe24:1ae4/64 scope link 
      valid_lft forever preferred_lft forever
8: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
   link/ether 52:54:00:81:84:9f brd ff:ff:ff:ff:ff:ff
   inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
9: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 500
   link/ether 52:54:00:81:84:9f brd ff:ff:ff:ff:ff:ff
33: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 500
   link/ether fe:00:00:00:00:0e brd ff:ff:ff:ff:ff:ff
   inet6 fe80::fc00:ff:fe00:e/64 scope link 
      valid_lft forever preferred_lft forever
34: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1522 qdisc pfifo_fast state UNKNOWN qlen 500
   link/ether fe:00:01:00:00:0e brd ff:ff:ff:ff:ff:ff
   inet6 fe80::fc00:1ff:fe00:e/64 scope link 
      valid_lft forever preferred_lft forever

[root@node002 ~]# sysctl -a | grep tcp
fs.nfs.nlm_tcpport = 0
fs.nfs.nfs_callback_tcpport = 0
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 432000
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_tcp_loose = 1
net.netfilter.nf_conntrack_tcp_be_liberal = 0
net.netfilter.nf_conntrack_tcp_max_retrans = 3
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_retrans_collapse = 1
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_stdurg = 0
net.ipv4.tcp_rfc1337 = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_fack = 1
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_mem = 12397248	16529664	24794496
net.ipv4.tcp_wmem = 4096	16384	4194304
net.ipv4.tcp_rmem = 4096	87380	4194304
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_frto = 2
net.ipv4.tcp_frto_response = 0
net.ipv4.tcp_low_latency = 0
net.ipv4.tcp_no_metrics_save = 0
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_tso_win_divisor = 3
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_abc = 0
net.ipv4.tcp_mtu_probing = 0
net.ipv4.tcp_base_mss = 512
net.ipv4.tcp_workaround_signed_windows = 0
net.ipv4.tcp_dma_copybreak = 262144
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_max_ssthresh = 0
net.ipv4.tcp_thin_linear_timeouts = 0
net.ipv4.tcp_thin_dupack = 0
sunrpc.transports = tcp 1048576
sunrpc.transports = tcp-bc 1048576
sunrpc.tcp_slot_table_entries = 2
sunrpc.tcp_max_slot_table_entries = 65536
sunrpc.tcp_fin_timeout = 15

^ permalink raw reply

* Re: regression with poll(2)
From: Andrew Morton @ 2012-08-21 15:58 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Mel Gorman, Sage Weil, David Miller, netdev, linux-kernel,
	ceph-devel, Neil Brown, Peter Zijlstra, michaelc, emunson,
	Eric Dumazet, Christoph Lameter
In-Reply-To: <CA+55aFw6S85jR+5zP9W6YykdsTMSVw9T5ibW93Gtx2rjw-b2EA@mail.gmail.com>

On Mon, 20 Aug 2012 10:02:05 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote:

> On Mon, Aug 20, 2012 at 2:04 AM, Mel Gorman <mgorman@suse.de> wrote:
> >
> > Can the following patch be tested please? It is reported to fix an fio
> > regression that may be similar to what you are experiencing but has not
> > been picked up yet.
> 
> Andrew, is this in your queue, or should I take this directly, or
> what? It seems to fix the problem for Eric and Sage, at least.

Yes, I have a copy queued:


From: Alex Shi <alex.shi@intel.com>
Subject: mm: correct page->pfmemalloc to fix deactivate_slab regression

cfd19c5a9ec ("mm: only set page->pfmemalloc when ALLOC_NO_WATERMARKS was
used") tried to narrow down page->pfmemalloc setting, but it missed some
places the pfmemalloc should be set.

So, in __slab_alloc, the unalignment pfmemalloc and ALLOC_NO_WATERMARKS
cause incorrect deactivate_slab() on our core2 server:

    64.73%           fio  [kernel.kallsyms]     [k] _raw_spin_lock
                     |
                     --- _raw_spin_lock
                        |
                        |---0.34%-- deactivate_slab
                        |          __slab_alloc
                        |          kmem_cache_alloc
                        |          |

That causes our fio sync write performance to have a 40% regression.

Move the checking in get_page_from_freelist() which resolves this issue.

Signed-off-by: Alex Shi <alex.shi@intel.com>
Acked-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Tested-by: Eric Dumazet <eric.dumazet@gmail.com>
Tested-by: Sage Weil <sage@inktank.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 mm/page_alloc.c |   21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff -puN mm/page_alloc.c~mm-correct-page-pfmemalloc-to-fix-deactivate_slab-regression mm/page_alloc.c
--- a/mm/page_alloc.c~mm-correct-page-pfmemalloc-to-fix-deactivate_slab-regression
+++ a/mm/page_alloc.c
@@ -1928,6 +1928,17 @@ this_zone_full:
 		zlc_active = 0;
 		goto zonelist_scan;
 	}
+
+	if (page)
+		/*
+		 * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was
+		 * necessary to allocate the page. The expectation is
+		 * that the caller is taking steps that will free more
+		 * memory. The caller should avoid the page being used
+		 * for !PFMEMALLOC purposes.
+		 */
+		page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS);
+
 	return page;
 }
 
@@ -2389,14 +2400,6 @@ rebalance:
 				zonelist, high_zoneidx, nodemask,
 				preferred_zone, migratetype);
 		if (page) {
-			/*
-			 * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was
-			 * necessary to allocate the page. The expectation is
-			 * that the caller is taking steps that will free more
-			 * memory. The caller should avoid the page being used
-			 * for !PFMEMALLOC purposes.
-			 */
-			page->pfmemalloc = true;
 			goto got_pg;
 		}
 	}
@@ -2569,8 +2572,6 @@ retry_cpuset:
 		page = __alloc_pages_slowpath(gfp_mask, order,
 				zonelist, high_zoneidx, nodemask,
 				preferred_zone, migratetype);
-	else
-		page->pfmemalloc = false;
 
 	trace_mm_page_alloc(page, order, gfp_mask, migratetype);
 
_

^ permalink raw reply

* netconsole leads to stalled CPU task
From: Sylvain Munaut @ 2012-08-21 15:13 UTC (permalink / raw)
  To: netdev

Hi,


I'm trying to use the netconsole to feed kernel message to the outside
but this lead to a stall ...

This only happens in a fairly specific configuration where you have a
bridge over vlan over bonding.
I tested with only (bridge over vlan) and (vlan over bonding) and
those work fine.


bash# modprobe netconsole
netconsole=8888@10.208.1.30/mgmt,8000@10.208.1.3/00:16:3e:1a:37:37
[... never returns ... ]

dmesg:

[  130.672942] netpoll: netconsole: local port 8888
[  130.673206] netpoll: netconsole: local IP 10.208.1.30
[  130.673460] netpoll: netconsole: interface 'mgmt'
[  130.673735] netpoll: netconsole: remote port 8000
[  130.673984] netpoll: netconsole: remote IP 10.208.1.3
[  130.674231] netpoll: netconsole: remote ethernet address 00:16:3e:1a:37:37
[  132.975290] console [netcon0] enabled
[  132.975541] netconsole: network logging started
[  190.677624] INFO: rcu_preempt detected stalls on CPUs/tasks: { 15}
(detected by 2, t=60002 jiffies)
[  190.678218] INFO: Stall ended before state dump start
[  370.682595] INFO: rcu_preempt detected stalls on CPUs/tasks: { 15}
(detected by 2, t=240007 jiffies)
[  370.683197] INFO: Stall ended before state dump start
[  451.664596] INFO: rcu_bh detected stalls on CPUs/tasks: { 15}
(detected by 16, t=60004 jiffies)
[  451.665190] INFO: Stall ended before state dump start
[  550.687619] INFO: rcu_preempt detected stalls on CPUs/tasks: { 15}
(detected by 16, t=420012 jiffies)
[  550.688211] INFO: Stall ended before state dump start
[  631.669621] INFO: rcu_bh detected stalls on CPUs/tasks: { 15}
(detected by 2, t=240009 jiffies)
[  631.670220] INFO: Stall ended before state dump start


ifconfig:

bond0     Link encap:Ethernet  HWaddr 18:03:73:ed:67:ad
          inet6 addr: fe80::1a03:73ff:feed:67ad/64 Scope:Link
          UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
          RX packets:735 errors:0 dropped:1 overruns:0 frame:0
          TX packets:127 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:99136 (96.8 KiB)  TX bytes:40635 (39.6 KiB)

bond0.1   Link encap:Ethernet  HWaddr 18:03:73:ed:67:ad
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:283 errors:0 dropped:0 overruns:0 frame:0
          TX packets:108 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:41948 (40.9 KiB)  TX bytes:37915 (37.0 KiB)

eth0      Link encap:Ethernet  HWaddr 18:03:73:ed:67:ad
          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
          RX packets:450 errors:0 dropped:0 overruns:0 frame:0
          TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:52085 (50.8 KiB)  TX bytes:1053 (1.0 KiB)

eth2      Link encap:Ethernet  HWaddr 18:03:73:ed:67:ad
          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
          RX packets:285 errors:0 dropped:1 overruns:0 frame:0
          TX packets:117 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:47051 (45.9 KiB)  TX bytes:39582 (38.6 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

mgmt      Link encap:Ethernet  HWaddr 18:03:73:ed:67:ad
          inet addr:10.208.1.30  Bcast:10.208.1.255  Mask:255.255.255.0
          inet6 addr: fe80::1a03:73ff:feed:67ad/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:280 errors:0 dropped:0 overruns:0 frame:0
          TX packets:108 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:41713 (40.7 KiB)  TX bytes:37915 (37.0 KiB)


Cheers,

    Sylvain

^ permalink raw reply

* Re: [net-next 1/6] ethtool.h: MDI setting support
From: Ben Hutchings @ 2012-08-21 15:12 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: davem, Jesse Brandeburg, netdev, gospo, sassmann
In-Reply-To: <1345538275-1690-2-git-send-email-jeffrey.t.kirsher@intel.com>

On Tue, 2012-08-21 at 01:37 -0700, Jeff Kirsher wrote:
> From: Jesse Brandeburg <jesse.brandeburg@intel.com>
> 
> This change modifies the core ethtool struct to allow a driver to
> support setting of MDI/MDI-X state for twisted pair wiring.  This
> change uses a previously reserved u8 and should not change any
> binary compatibility of ethtool.
> 
> Also as per Ben Hutchings' suggestion, the capabilities are
> stored in a separate byte so the driver can report if it supports
> changing settings.
> 
> see thread: http://kerneltrap.org/mailarchive/linux-netdev/2010/11/17/6289820/thread
> 
> see ethtool patches titled:
> ethtool: allow setting MDI-X state
> 
> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
> CC: Ben Hutchings <bhutchings@solarflare.com>
> Tested-by: Aaron Brown aaron.f.brown@intel.com
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Reviewed-by: Ben Hutchings <bhutchings@solarflare.com>

> ---
>  include/linux/ethtool.h | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index 21eff41..fcb4f8e 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -45,8 +45,10 @@ struct ethtool_cmd {
>  				 * bits) in Mbps. Please use
>  				 * ethtool_cmd_speed()/_set() to
>  				 * access it */
> -	__u8	eth_tp_mdix;
> -	__u8	reserved2;
> +	__u8	eth_tp_mdix;	/* twisted pair MDI-X status */
> +	__u8    eth_tp_mdix_ctrl; /* twisted pair MDI-X control, when set,
> +				   * link should be renegotiated if necessary
> +				   */
>  	__u32	lp_advertising;	/* Features the link partner advertises */
>  	__u32	reserved[2];
>  };
> @@ -1229,10 +1231,13 @@ struct ethtool_ops {
>  #define AUTONEG_DISABLE		0x00
>  #define AUTONEG_ENABLE		0x01
>  
> -/* Mode MDI or MDI-X */
> -#define ETH_TP_MDI_INVALID	0x00
> -#define ETH_TP_MDI		0x01
> -#define ETH_TP_MDI_X		0x02
> +/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then
> + * the driver is required to renegotiate link
> + */
> +#define ETH_TP_MDI_INVALID	0x00 /* status: unknown; control: unsupported */
> +#define ETH_TP_MDI		0x01 /* status: MDI;     control: force MDI */
> +#define ETH_TP_MDI_X		0x02 /* status: MDI-X;   control: force MDI-X */
> +#define ETH_TP_MDI_AUTO		0x03 /*                  control: auto-select */
>  
>  /* Wake-On-Lan options. */
>  #define WAKE_PHY		(1 << 0)

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* RE: [PATCH] ethtool: don't overwrite useful bits in advertising bitfield
From: Ben Hutchings @ 2012-08-21 15:11 UTC (permalink / raw)
  To: Johan Gunnarsson; +Cc: netdev@vger.kernel.org, Mikael Starvik
In-Reply-To: <A612847CFE53224C91B23E3A5B48BAC7534E8D76AD@xmail3.se.axis.com>

On Tue, 2012-08-21 at 10:41 +0200, Johan Gunnarsson wrote:
> 
> > -----Original Message-----
> > From: netdev-owner@vger.kernel.org [mailto:netdev-
> > owner@vger.kernel.org] On Behalf Of Ben Hutchings
> > Sent: den 20 augusti 2012 17:23
> > To: Johan Gunnarsson
> > Cc: netdev@vger.kernel.org; Mikael Starvik
> > Subject: Re: [PATCH] ethtool: don't overwrite useful bits in
> > advertising bitfield
> > 
> > On Tue, 2012-08-14 at 16:15 +0200, Johan Gunnarsson wrote:
> > > There are bits in this bitfield that we want to leave untouched
> > (PAUSE
> > > and ASYM_PAUSE bits) when changing other bits (speed and duplex
> > bits.)
> > > Previously, these were always overwritten to zero when running
> > commands
> > > like "ethtool -s eth0 speed 10 duplex full autoneg off".
> > 
> > This is right in principle, but the implementation isn't quite right.
> > 
> > > Signed-off-by: Johan Gunnarsson <johangu@axis.com>
> > > ---
> > >  ethtool.c |   45 +++++++++++++++++++++++++++++++--------------
> > >  1 file changed, 31 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/ethtool.c b/ethtool.c
> > > index e573357..efa12c7 100644
> > > --- a/ethtool.c
> > > +++ b/ethtool.c
> > > @@ -46,6 +46,18 @@
> > >  #define MAX_ADDR_LEN	32
> > >  #endif
> > >
> > > +#define ALL_ADVERTISED_MODES \
> > > +	(ADVERTISED_10baseT_Half | \
> > > +	 ADVERTISED_10baseT_Full | \
> > > +	 ADVERTISED_100baseT_Half | \
> > > +	 ADVERTISED_100baseT_Full | \
> > > +	 ADVERTISED_1000baseT_Half | \
> > > +	 ADVERTISED_1000baseT_Full | \
> > > +	 ADVERTISED_2500baseX_Full | \
> > > +	 ADVERTISED_10000baseT_Full | \
> > > +	 ADVERTISED_20000baseMLD2_Full | \
> > > +	 ADVERTISED_20000baseKR2_Full)
> > 
> > This is missing the new 40G modes (not a regression, I realise).
> 
> I'll add the 40G modes. There is also a bunch of 10G modes missing. Shall I add these too?

Yes please.

> > 
> > [...]
> > > @@ -2405,19 +2421,20 @@ static int do_sset(struct cmd_context *ctx)
> > >  			}
> > >  			if (autoneg_wanted == AUTONEG_ENABLE &&
> > >  			    advertising_wanted == 0) {
> > > -				ecmd.advertising = ecmd.supported &
> > > -					(ADVERTISED_10baseT_Half |
> > > -					 ADVERTISED_10baseT_Full |
> > > -					 ADVERTISED_100baseT_Half |
> > > -					 ADVERTISED_100baseT_Full |
> > > -					 ADVERTISED_1000baseT_Half |
> > > -					 ADVERTISED_1000baseT_Full |
> > > -					 ADVERTISED_2500baseX_Full |
> > > -					 ADVERTISED_10000baseT_Full |
> > > -					 ADVERTISED_20000baseMLD2_Full |
> > > -					 ADVERTISED_20000baseKR2_Full);
> > > +				/* Auto negotation enabled, but with
> > > +				 * unspecified speed and duplex: enable all
> > > +				 * supported speeds and duplexes.
> > > +				 */
> > > +				ecmd.advertising = (ecmd.advertising &
> > > +					~ALL_ADVERTISED_MODES) |
> > > +					(ALL_ADVERTISED_MODES & ecmd.supported);
> > 
> > Perhaps we should also warn if there's a 'supported' flag we don't
> > recognise, because we don't know whether it's a link mode and we might
> > be failing to enable/disable it as requested.
> 
> You mean if ecmd.supported has bits enabled that ALL_ADVERTISED_MODES
> hasn't? I don't think that's a good idea, because that happens very
> often (for example PAUSE bits in my case.)

No, I mean if it has bits enabled that are not defined at all (currently
any of bits 27-31).

> > 
> > >  			} else if (advertising_wanted > 0) {
> > > -				ecmd.advertising = advertising_wanted;
> > > +				/* Enable all requested modes */
> > > +				ecmd.advertising = (ecmd.advertising &
> > > +					~ALL_ADVERTISED_MODES) |
> > > +					(advertising_wanted & ecmd.supported);
> > 
> > I don't think the '& ecmd.supported' here is right.  If an autoneg
> > device supports some new link mode L that is not in
> > ALL_ADVERTISED_MODES, but not link mode M which the user requested,
> > then
> > this can silently fail because the resulting advertising mask will
> > include L but not M.
> > 
> > We should either use advertising_wanted unmasked and let the driver
> > validate it, or report an error if it's not present in the supported
> > mask.  I think we should be consistent with the following case, i.e.
> > let
> > the driver validate it.
> 
> How about remove "& ecmd.supported", but also warn if trying to add an
> unsupported mode? Similar to the previous case.
[...]

I don't think this is similar and I don't think we need to do both.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH] iproute2: Add missing tc-ematch.8 for man page installation
From: Stephen Hemminger @ 2012-08-21 14:49 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: Linux Netdev List
In-Reply-To: <503319AD.2090701@hartkopp.net>

On Tue, 21 Aug 2012 07:16:29 +0200
Oliver Hartkopp <socketcan@hartkopp.net> wrote:

> 
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Applied

^ permalink raw reply


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