Netdev List
 help / color / mirror / Atom feed
* [net-next.git 1/4 (v5)] phy: add the EEE support and the way to access to the MMD registers.
From: Giuseppe CAVALLARO @ 2012-06-13  7:17 UTC (permalink / raw)
  To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro
In-Reply-To: <1339571827-7162-1-git-send-email-peppe.cavallaro@st.com>

This patch adds the support for the Energy-Efficient Ethernet (EEE)
to the Physical Abstraction Layer.
To support the EEE we have to access to the MMD registers 3.20 and
7.60/61. So two new functions have been added to read/write the MMD
registers (clause 45).

An Ethernet driver (I tested the stmmac) can invoke the phy_init_eee to properly
check if the EEE is supported by the PHYs and it can also set the clock
stop enable bit in the 3.0 register.
The phy_get_eee_err can be used for reporting the number of time where
the PHY failed to complete its normal wake sequence.

In the end, this patch also adds the EEE ethtool support implementing:
 o phy_ethtool_set_eee
 o phy_ethtool_get_eee

v1: initial patch
v2: fixed some errors especially on naming convention
v3: renamed again the mmd read/write functions thank to Ben's feedback
v4: moved file to phy.c and added the ethtool support.
v5: fixed phy_adv_to_eee, phy_eee_to_supported, phy_eee_to_adv return
    values according to ethtool API (thanks to Ben's feedback).
    Renamed some macros to avoid too long names.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/phy/phy.c |  261 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mdio.h  |   21 +++-
 include/linux/mii.h   |    9 ++
 include/linux/phy.h   |    5 +
 4 files changed, 292 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2e1c237..8935295 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -35,6 +35,7 @@
 #include <linux/phy.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/mdio.h>
 
 #include <linux/atomic.h>
 #include <asm/io.h>
@@ -967,3 +968,263 @@ void phy_state_machine(struct work_struct *work)
 
 	schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
 }
+
+static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
+				    int addr)
+{
+	/* Write the desired MMD Devad */
+	bus->write(bus, addr, MII_MMD_CTRL, devad);
+
+	/* Write the desired MMD register address */
+	bus->write(bus, addr, MII_MMD_DATA, prtad);
+
+	/* Select the Function : DATA with no post increment */
+	bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
+}
+
+/**
+ * phy_read_mmd_indirect - reads data from the MMC register (clause 22 to
+ * access to clause 45)
+ * @bus: the target MII bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ *
+ * Description: Reads data from the MMD regisetrs of the
+ * phy addr. To read these register we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Read  reg 14 // Read MMD data
+ */
+static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
+				 int addr)
+{
+	u32 ret;
+
+	mmd_phy_indirect(bus, prtad, devad, addr);
+
+	/* Read the content of the MMD's selected register */
+	ret = bus->read(bus, addr, MII_MMD_DATA);
+
+	return ret;
+}
+
+/**
+ * phy_write_mmd_indirect - writes data to the MMC register (clause 22 to
+ * access to clause 45)
+ * @bus: the target MII bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ * @data: data to write in the MMD register
+ *
+ * Description: Reads data from the MMD regisetrs of the
+ * phy addr. To read these register we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Write reg 14 // Write MMD data
+ */
+static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
+				   int addr, u32 data)
+{
+	mmd_phy_indirect(bus, prtad, devad, addr);
+
+	/* Write the data into MMD's selected register */
+	bus->write(bus, addr, MII_MMD_DATA, data);
+}
+
+/* phy_init_eee
+ * @phydev: target phy_device struct
+ * @clk_stop_enable: PHY may stop the clock during LPI
+ *
+ * Description: it checks if the Energy-Efficient Ethernet (EEE)
+ * is supported by looking at the MMD registers 3.20 and 7.60/61
+ * and it programs the MMD register 3.0 setting the "Clock stop enable"
+ * bit if required.
+ * In fact, the clk_stop_enable can be passed to:
+ *  1 = The PHY may stop the clock during LPI
+ *  0 = Clock not stoppable
+ */
+int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
+{
+	int ret = -EPROTONOSUPPORT;
+
+	/* According to 802.3az,the EEE is supported only in full duplex-mode.
+	 * Also EEE feature is active when core is operating with MII, GMII
+	 * or RGMII.
+	 */
+	if ((phydev->duplex == DUPLEX_FULL) &&
+	    ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
+		int eee_cap, eee_link;
+
+		/* EEE ability must be supported in both local and remote
+		 * PHY devices.
+		 */
+		eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+						MDIO_MMD_AN, phydev->addr);
+		if (eee_cap < 0)
+			return eee_cap;
+
+		eee_link = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+						 MDIO_MMD_PCS, phydev->addr);
+		if (eee_link < 0)
+			return eee_link;
+
+		if (eee_cap && eee_link) {
+			if (clk_stop_enable) {
+				/* Configure the PHY to stop receiving xMII
+				 * clock while it is signaling LPI
+				 */
+				int ctrl;
+				ctrl = phy_read_mmd_indirect(phydev->bus,
+							     MDIO_CTRL1,
+							     MDIO_MMD_PCS,
+							     phydev->addr);
+				if (ctrl < 0)
+					return ctrl;
+
+				ctrl |= MDIO_PCS_CTRL1_CLKSTOP_EN;
+				phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
+						       MDIO_MMD_PCS,
+						       phydev->addr, ctrl);
+			}
+
+			ret = 0; /* EEE supported */
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(phy_init_eee);
+
+/* phy_get_eee_err
+ * @phydev: target phy_device struct
+ *
+ * Description: it is to report the number of time where the PHY
+ * failed to complete its normal wake sequence.
+ */
+int phy_get_eee_err(struct phy_device *phydev)
+{
+	return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
+				     MDIO_MMD_PCS, phydev->addr);
+
+}
+EXPORT_SYMBOL(phy_get_eee_err);
+
+static u32 phy_eee_to_adv(u16 eee_adv)
+{
+	u32 adv = 0;
+
+	if (eee_adv & MDIO_EEE_100TX)
+		adv |= ADVERTISED_100baseT_Full;
+	if (eee_adv & MDIO_EEE_1000T)
+		adv |= ADVERTISED_1000baseT_Full;
+	if (eee_adv & MDIO_EEE_10GT)
+		adv |= ADVERTISED_10000baseT_Full;
+	if (eee_adv & MDIO_EEE_1000KX)
+		adv |= ADVERTISED_1000baseKX_Full;
+	if (eee_adv & MDIO_EEE_10GKX4)
+		adv |= ADVERTISED_10000baseKX4_Full;
+	if (eee_adv & MDIO_EEE_10GKR)
+		adv |= ADVERTISED_10000baseKR_Full;
+
+	return adv;
+}
+
+static u32 phy_eee_to_supported(u16 eee_supported)
+{
+	u32 supported = 0;
+
+	if (eee_supported & MDIO_EEE_100TX)
+		supported |= SUPPORTED_100baseT_Full;
+	if (eee_supported & MDIO_EEE_1000T)
+		supported |= SUPPORTED_1000baseT_Full;
+	if (eee_supported & MDIO_EEE_10GT)
+		supported |= SUPPORTED_10000baseT_Full;
+	if (eee_supported & MDIO_EEE_1000KX)
+		supported |= SUPPORTED_1000baseKX_Full;
+	if (eee_supported & MDIO_EEE_10GKX4)
+		supported |= SUPPORTED_10000baseKX4_Full;
+	if (eee_supported & MDIO_EEE_10GKR)
+		supported |= SUPPORTED_10000baseKR_Full;
+
+	return supported;
+}
+
+/* phy_ethtool_get_eee
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it reportes the Supported/Advertisement/LP Advertisement
+ * capabilities.
+ */
+int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+	int val;
+
+	/* Get Supported EEE */
+	val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+				    MDIO_MMD_PCS, phydev->addr);
+	if (val < 0)
+		return val;
+	data->supported = phy_eee_to_supported(val);
+
+	/* Get advertisement EEE */
+	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+				    MDIO_MMD_AN, phydev->addr);
+	if (val < 0)
+		return val;
+	data->advertised = phy_eee_to_adv(val);
+
+	/* Get LP advertisement EEE */
+	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+				    MDIO_MMD_AN, phydev->addr);
+	if (val < 0)
+		return val;
+	data->lp_advertised = phy_eee_to_adv(val);
+
+	return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_get_eee);
+
+static u16 phy_adv_to_eee(u32 adv)
+{
+	u16 reg = 0;
+
+	if (adv & ADVERTISED_100baseT_Full)
+		reg |= MDIO_EEE_100TX;
+	if (adv & ADVERTISED_1000baseT_Full)
+		reg |= MDIO_EEE_1000T;
+	if (adv & ADVERTISED_10000baseT_Full)
+		reg |= MDIO_EEE_10GT;
+	if (adv & ADVERTISED_1000baseKX_Full)
+		reg |= MDIO_EEE_1000KX;
+	if (adv & ADVERTISED_10000baseKX4_Full)
+		reg |= MDIO_EEE_10GKX4;
+	if (adv & ADVERTISED_10000baseKR_Full)
+		reg |= MDIO_EEE_10GKR;
+
+	return reg;
+}
+
+/* phy_ethtool_set_eee
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it is to program the Advertisement EEE register.
+ */
+int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+	int val;
+
+	val = phy_adv_to_eee(data->advertised);
+	phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
+			       phydev->addr, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_set_eee);
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index dfb9479..4ad8f0e 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -43,7 +43,11 @@
 #define MDIO_PKGID2		15
 #define MDIO_AN_ADVERTISE	16	/* AN advertising (base page) */
 #define MDIO_AN_LPA		19	/* AN LP abilities (base page) */
+#define MDIO_PCS_EEE_ABLE	20	/* EEE Capability register */
+#define MDIO_PCS_EEE_WK_ERR	22	/* EEE wake error counter */
 #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
+#define MDIO_AN_EEE_ADV		60	/* EEE advertisement */
+#define MDIO_AN_EEE_LPABLE	61	/* EEE link partner ability */
 
 /* Media-dependent registers. */
 #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
@@ -56,7 +60,6 @@
 #define MDIO_PCS_10GBRT_STAT2	33	/* 10GBASE-R/-T PCS status 2 */
 #define MDIO_AN_10GBT_CTRL	32	/* 10GBASE-T auto-negotiation control */
 #define MDIO_AN_10GBT_STAT	33	/* 10GBASE-T auto-negotiation status */
-#define MDIO_AN_EEE_ADV		60	/* EEE advertisement */
 
 /* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */
 #define MDIO_PMA_LASI_RXCTRL	0x9000	/* RX_ALARM control */
@@ -82,6 +85,7 @@
 #define MDIO_AN_CTRL1_RESTART		BMCR_ANRESTART
 #define MDIO_AN_CTRL1_ENABLE		BMCR_ANENABLE
 #define MDIO_AN_CTRL1_XNP		0x2000	/* Enable extended next page */
+#define MDIO_PCS_CTRL1_CLKSTOP_EN	0x400	/* Stop the clock during LPI */
 
 /* 10 Gb/s */
 #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
@@ -237,9 +241,18 @@
 #define MDIO_AN_10GBT_STAT_MS		0x4000	/* Master/slave config */
 #define MDIO_AN_10GBT_STAT_MSFLT	0x8000	/* Master/slave config fault */
 
-/* AN EEE Advertisement register. */
-#define MDIO_AN_EEE_ADV_100TX		0x0002	/* Advertise 100TX EEE cap */
-#define MDIO_AN_EEE_ADV_1000T		0x0004	/* Advertise 1000T EEE cap */
+/* EEE Supported/Advertisement/LP Advertisement registers.
+ *
+ * EEE capability Register (3.20), Advertisement (7.60) and
+ * Link partner ability (7.61) registers have and can use the same identical
+ * bit masks.
+ */
+#define MDIO_EEE_100TX			0x0002	/* 100TX EEE cap */
+#define MDIO_EEE_1000T			0x0004	/* 1000T EEE cap */
+#define MDIO_EEE_10GT			0x0008	/* 10GT EEE cap */
+#define MDIO_EEE_1000KX			0x0010	/* 1000KX EEE cap */
+#define MDIO_EEE_10GKX4			0x0020	/* 10G KX4 EEE cap */
+#define MDIO_EEE_10GKR			0x0040	/* 10G KR EEE cap */
 
 /* LASI RX_ALARM control/status registers. */
 #define MDIO_PMA_LASI_RX_PHYXSLFLT	0x0001	/* PHY XS RX local fault */
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 2783eca..8ef3a7a 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -21,6 +21,8 @@
 #define MII_EXPANSION		0x06	/* Expansion register          */
 #define MII_CTRL1000		0x09	/* 1000BASE-T control          */
 #define MII_STAT1000		0x0a	/* 1000BASE-T status           */
+#define	MII_MMD_CTRL		0x0d	/* MMD Access Control Register */
+#define	MII_MMD_DATA		0x0e	/* MMD Access Data Register */
 #define MII_ESTATUS		0x0f	/* Extended Status             */
 #define MII_DCOUNTER		0x12	/* Disconnect counter          */
 #define MII_FCSCOUNTER		0x13	/* False carrier counter       */
@@ -141,6 +143,13 @@
 #define FLOW_CTRL_TX		0x01
 #define FLOW_CTRL_RX		0x02
 
+/* MMD Access Control register fields */
+#define MII_MMD_CTRL_DEVAD_MASK	0x1f	/* Mask MMD DEVAD*/
+#define MII_MMD_CTRL_ADDR	0x0000	/* Address */
+#define MII_MMD_CTRL_NOINCR	0x4000	/* no post increment */
+#define MII_MMD_CTRL_INCR_RDWT	0x8000	/* post increment on reads & writes */
+#define MII_MMD_CTRL_INCR_ON_WT	0xC000	/* post increment on writes only */
+
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
 struct mii_ioctl_data {
 	__u16		phy_id;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c291cae..97fc4cf 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -532,6 +532,11 @@ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
 		int (*run)(struct phy_device *));
 int phy_scan_fixups(struct phy_device *phydev);
 
+int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
+int phy_get_eee_err(struct phy_device *phydev);
+int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
+int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
+
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
 
-- 
1.7.4.4

^ permalink raw reply related

* [net-next.git 0/4] EEE for PAL and stmmac (v2)
From: Giuseppe CAVALLARO @ 2012-06-13  7:17 UTC (permalink / raw)
  To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro

These patches add the EEE support in the stmmac device driver
restoring an old work I had done some months ago and not
completed in time.

I've tested all on ST STB with the IC+ 101G PHY device that has
this feature.

The initial EEE support for the stmmac has been written by Rayagond
but I have reworked all his code adding new parts and especially
performing tests on a real hardware. Thx Rayagond!

In these patches, we can see that the stmmac supports the EEE
only if the DMA HW capability register says that this
feature is actually available. In that case, the driver can enter
in the Tx LPI mode by using a timer as recommended by Synopsys.
Note that EEE is supported in new chip generations; in particular
I used the 3.61a.

At any rate, further information about how the driver treats the EEE
can be found in the stmmac.txt file (there is a patch for that).

Another patch is for Physical Abstraction Layer now able to
manage the MMD registers (clause 45); it also provides the ethtool
support to manage supported/advertisement/lp adv features.

Giuseppe Cavallaro (4):
  phy: add the EEE support and the way to access to the MMD registers.
  stmmac: do not use strict_strtoul but kstrtoul
  stmmac: update the driver Documentation and add EEE
  stmmac: add the Energy Efficient Ethernet support

 Documentation/networking/stmmac.txt                |   36 +++-
 drivers/net/ethernet/stmicro/stmmac/common.h       |   31 +++-
 drivers/net/ethernet/stmicro/stmmac/dwmac1000.h    |   20 ++
 .../net/ethernet/stmicro/stmmac/dwmac1000_core.c   |  101 +++++++-
 .../net/ethernet/stmicro/stmmac/dwmac100_core.c    |    4 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h    |    1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h       |   10 +-
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   57 +++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  233 ++++++++++++++----
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 drivers/net/phy/phy.c                              |  261 ++++++++++++++++++++
 include/linux/mdio.h                               |   21 ++-
 include/linux/mii.h                                |    9 +
 include/linux/phy.h                                |    5 +
 14 files changed, 725 insertions(+), 66 deletions(-)

-- 
1.7.4.4

^ permalink raw reply

* Re: [PATCH 1/3] net: lpc_eth: Replace WARN() trace with simple pr_warn()
From: Eric Dumazet @ 2012-06-13  6:16 UTC (permalink / raw)
  To: Roland Stigge
  Cc: David Miller, netdev, linux-kernel, kevin.wells, srinivas.bakki,
	aletes.xgr, linux-arm-kernel
In-Reply-To: <1339442328.6001.2602.camel@edumazet-glaptop>

On Mon, 2012-06-11 at 21:18 +0200, Eric Dumazet wrote:
> On Mon, 2012-06-11 at 11:26 +0200, Roland Stigge wrote:
> 
> > Is it sensible at this point to increase the TX buffers anyway? For
> > different reasons of course: We have enough SRAM available and TX
> > buffers (16->32) are still more than RX buffers (48).
> 
> I doubt it has any impact on performance for a 100Mbit link ?
> 
> One thing that could be done would be to free skbs in
> lpc_eth_hard_start_xmit() instead of __lpc_handle_xmit()
> 

Here is the patch I was thinking about

(on top of latest net-next)

Could you please test it ?

 drivers/net/ethernet/nxp/lpc_eth.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 083d671..426f14c 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -440,7 +440,7 @@ struct netdata_local {
 	spinlock_t		lock;
 	void __iomem		*net_base;
 	u32			msg_enable;
-	struct sk_buff		*skb[ENET_TX_DESC];
+	unsigned int		skblen[ENET_TX_DESC];
 	unsigned int		last_tx_idx;
 	unsigned int		num_used_tx_buffs;
 	struct mii_bus		*mii_bus;
@@ -908,7 +908,7 @@ static void __lpc_handle_xmit(struct net_device *ndev)
 
 	txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base));
 	while (pldat->last_tx_idx != txcidx) {
-		skb = pldat->skb[pldat->last_tx_idx];
+		unsigned int skblen = pldat->skblen[pldat->last_tx_idx];
 
 		/* A buffer is available, get buffer status */
 		ptxstat = &pldat->tx_stat_v[pldat->last_tx_idx];
@@ -945,9 +945,8 @@ static void __lpc_handle_xmit(struct net_device *ndev)
 		} else {
 			/* Update stats */
 			ndev->stats.tx_packets++;
-			ndev->stats.tx_bytes += skb->len;
+			ndev->stats.tx_bytes += skblen;
 		}
-		dev_kfree_skb_irq(skb);
 
 		txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base));
 	}
@@ -1132,7 +1131,7 @@ static int lpc_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	memcpy(pldat->tx_buff_v + txidx * ENET_MAXF_SIZE, skb->data, len);
 
 	/* Save the buffer and increment the buffer counter */
-	pldat->skb[txidx] = skb;
+	pldat->skblen[txidx] = len;
 	pldat->num_used_tx_buffs++;
 
 	/* Start transmit */
@@ -1147,6 +1146,7 @@ static int lpc_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	spin_unlock_irq(&pldat->lock);
 
+	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
 

^ permalink raw reply related

* [PATCH] netpoll: fix netpoll_send_udp() bugs
From: Eric Dumazet @ 2012-06-13  5:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Bogdan Hamciuc, Herbert Xu, Neil Horman

From: Eric Dumazet <edumazet@google.com>

Bogdan Hamciuc diagnosed and fixed following bug in netpoll_send_udp() :

"skb->len += len;" instead of "skb_put(skb, len);"

Meaning that _if_ a network driver needs to call skb_realloc_headroom(),
only packet headers would be copied, leaving garbage in the payload.

However the skb_realloc_headroom() must be avoided as much as possible
since it requires memory and netpoll tries hard to work even if memory
is exhausted (using a pool of preallocated skbs)

It appears netpoll_send_udp() reserved 16 bytes for the ethernet header,
which happens to work for typicall drivers but not all.

Right thing is to use LL_RESERVED_SPACE(dev)
(And also add dev->needed_tailroom of tailroom)

This patch combines both fixes.

Many thanks to Bogdan for raising this issue.

Reported-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Neil Horman <nhorman@tuxdriver.com>
---
 net/core/netpoll.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3d84fb9..f9f40b9 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -362,22 +362,23 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
 
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 {
-	int total_len, eth_len, ip_len, udp_len;
+	int total_len, ip_len, udp_len;
 	struct sk_buff *skb;
 	struct udphdr *udph;
 	struct iphdr *iph;
 	struct ethhdr *eth;
 
 	udp_len = len + sizeof(*udph);
-	ip_len = eth_len = udp_len + sizeof(*iph);
-	total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
+	ip_len = udp_len + sizeof(*iph);
+	total_len = ip_len + LL_RESERVED_SPACE(np->dev);
 
-	skb = find_skb(np, total_len, total_len - len);
+	skb = find_skb(np, total_len + np->dev->needed_tailroom,
+		       total_len - len);
 	if (!skb)
 		return;
 
 	skb_copy_to_linear_data(skb, msg, len);
-	skb->len += len;
+	skb_put(skb, len);
 
 	skb_push(skb, sizeof(*udph));
 	skb_reset_transport_header(skb);

^ permalink raw reply related

* linux-next: manual merge of the akpm tree with the net tree
From: Stephen Rothwell @ 2012-06-13  5:27 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-next, linux-kernel, Stefan Roese, David Miller, netdev,
	Viresh Kumar

[-- Attachment #1: Type: text/plain, Size: 5541 bytes --]

Hi Andrew,

Today's linux-next merge of the akpm tree got a conflict in
drivers/net/ethernet/stmicro/stmmac/stmmac.h between commit 883ffd6e6411
("net: stmmac: Fix clock en-/disable calls") from the net tree and commit
"net/stmmac: remove conditional compilation of clk code" from the akpm
tree.

I fixed it up (I think - see below) and can carry the fix as necessary.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index dc20c56..900c5e6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -82,9 +82,7 @@ struct stmmac_priv {
 	struct stmmac_counters mmc;
 	struct dma_features dma_cap;
 	int hw_cap_support;
-#ifdef CONFIG_HAVE_CLK
 	struct clk *stmmac_clk;
-#endif
 	int clk_csr;
 	int synopsys_id;
 };
@@ -105,46 +103,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 				     struct plat_stmmacenet_data *plat_dat,
 				     void __iomem *addr);
 
-#ifdef CONFIG_HAVE_CLK
-static inline int stmmac_clk_enable(struct stmmac_priv *priv)
-{
-	if (!IS_ERR(priv->stmmac_clk))
-		return clk_prepare_enable(priv->stmmac_clk);
-
-	return 0;
-}
-
-static inline void stmmac_clk_disable(struct stmmac_priv *priv)
-{
-	if (IS_ERR(priv->stmmac_clk))
-		return;
-
-	clk_disable_unprepare(priv->stmmac_clk);
-}
-static inline int stmmac_clk_get(struct stmmac_priv *priv)
-{
-	priv->stmmac_clk = clk_get(priv->device, NULL);
-
-	if (IS_ERR(priv->stmmac_clk))
-		return PTR_ERR(priv->stmmac_clk);
-
-	return 0;
-}
-#else
-static inline int stmmac_clk_enable(struct stmmac_priv *priv)
-{
-	return 0;
-}
-static inline void stmmac_clk_disable(struct stmmac_priv *priv)
-{
-}
-static inline int stmmac_clk_get(struct stmmac_priv *priv)
-{
-	return 0;
-}
-#endif /* CONFIG_HAVE_CLK */
-
-
 #ifdef CONFIG_STMMAC_PLATFORM
 extern struct platform_driver stmmac_pltfr_driver;
 static inline int stmmac_register_platform(void)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 590e95b..bb63678 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -28,6 +28,7 @@
 	https://bugzilla.stlinux.com/
 *******************************************************************************/
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/ip.h>
@@ -165,12 +166,8 @@ static void stmmac_verify_args(void)
 
 static void stmmac_clk_csr_set(struct stmmac_priv *priv)
 {
-#ifdef CONFIG_HAVE_CLK
 	u32 clk_rate;
 
-	if (IS_ERR(priv->stmmac_clk))
-		return;
-
 	clk_rate = clk_get_rate(priv->stmmac_clk);
 
 	/* Platform provided default clk_csr would be assumed valid
@@ -192,7 +189,6 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
 	   * we can not estimate the proper divider as it is not known
 	   * the frequency of clk_csr_i. So we do not change the default
 	   * divider. */
-#endif
 }
 
 #if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG)
@@ -974,7 +970,7 @@ static int stmmac_open(struct net_device *dev)
 	} else
 		priv->tm->enable = 1;
 #endif
-	stmmac_clk_enable(priv);
+	clk_prepare_enable(priv->stmmac_clk);
 
 	stmmac_check_ether_addr(priv);
 
@@ -1078,7 +1074,7 @@ open_error:
 	if (priv->phydev)
 		phy_disconnect(priv->phydev);
 
-	stmmac_clk_disable(priv);
+	clk_disable_unprepare(priv->stmmac_clk);
 
 	return ret;
 }
@@ -1131,7 +1127,7 @@ static int stmmac_release(struct net_device *dev)
 #ifdef CONFIG_STMMAC_DEBUG_FS
 	stmmac_exit_fs();
 #endif
-	stmmac_clk_disable(priv);
+	clk_disable_unprepare(priv->stmmac_clk);
 
 	return 0;
 }
@@ -1926,11 +1922,14 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 	ret = register_netdev(ndev);
 	if (ret) {
 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
-		goto error;
+		goto error_netdev_register;
 	}
 
-	if (stmmac_clk_get(priv))
+	priv->stmmac_clk = clk_get(priv->device, NULL);
+	if (IS_ERR(priv->stmmac_clk)) {
 		pr_warning("%s: warning: cannot get CSR clock\n", __func__);
+		goto error_clk_get;
+	}
 
 	/* If a specific clk_csr value is passed from the platform
 	 * this means that the CSR Clock Range selection cannot be
@@ -1948,15 +1947,17 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 	if (ret < 0) {
 		pr_debug("%s: MDIO bus (id: %d) registration failed",
 			 __func__, priv->plat->bus_id);
-		goto error;
+		goto error_mdio_register;
 	}
 
 	return priv;
 
-error:
-	netif_napi_del(&priv->napi);
-
+error_mdio_register:
+	clk_put(priv->stmmac_clk);
+error_clk_get:
 	unregister_netdev(ndev);
+error_netdev_register:
+	netif_napi_del(&priv->napi);
 	free_netdev(ndev);
 
 	return NULL;
@@ -2025,7 +2026,7 @@ int stmmac_suspend(struct net_device *ndev)
 	else {
 		stmmac_set_mac(priv->ioaddr, false);
 		/* Disable clock in case of PWM is off */
-		stmmac_clk_disable(priv);
+		clk_disable_unprepare(priv->stmmac_clk);
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
@@ -2050,7 +2051,7 @@ int stmmac_resume(struct net_device *ndev)
 		priv->hw->mac->pmt(priv->ioaddr, 0);
 	else
 		/* enable the clk prevously disabled */
-		stmmac_clk_enable(priv);
+		clk_prepare_enable(priv->stmmac_clk);
 
 	netif_device_attach(ndev);
 

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply related

* [GIT] net merged into net-next
From: David Miller @ 2012-06-13  5:18 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linville-2XuSBdqkA4R54TAoqtyWWQ,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA


John please double check my work as the only merge hassles
were wireless bits.  I'm pretty sure I resolved things in
a reasonable way.

Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net-next 4/4] 6lowpan: len field is not stored and accessed properly
From: Tony Cheneau @ 2012-06-13  4:54 UTC (permalink / raw)
  To: Alexander Smirnov
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <CAJmB2rAYZe9FEfUcxd_g6kX247MExv89h=Cjfxmvfb+=6qGSgQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi again,

Thank you for your comment. See my answer inline.

Le Tue, 12 Jun 2012 22:20:13 +0400,
Alexander Smirnov <alex.bluesman.smirnov@gmail.com> a écrit :

> 2012/6/11 Tony Cheneau <tony.cheneauh@amnesiak.org>:
> > Lenght field should be encoded (and accessed) the other way around.
> > As it is currently written, it could lead to interroperability
> > issues.
> 
> What kind of "interroperability issues" can occur? Please describe it
> in details, I can't read your mind. And again, can these problems be
> caused by the byte-order mismatch?
Sorry if I wasn't clear. Yes, I believe it is a byte-order mismatch.
I wasn't able to verify interoperability with other implementations
myself, but I compared with some packet capture I obtained from some
other implementations, where the byte-order was different. I'll double
check that when I'll have access to my lab again.
The reason I choose the term "interoperability issues" is that this
patch focuses on the length field where patch 3 focused on the tag
field. If you encode the tag field incorrectly, it is not a big deal,
because the recipient will decode wrongly, but all fragment of a same
packet will share a same tag (regardless of you decode it properly or
not). However, when the same thing happen with the length field, if you
endianness is wrong, the recipient will interpret a totally different
length and will reserve a wrong amount of memory in order to store the
packet (this is mainly a matter of concern if you are performing
fragment reassembly and do not allocate enough memory for the complete
frame). Do that make sense?

Just like the previous patch, I'll rework it as well.

As a side note, do you have any opinions on the first two patches 

Regards,
	Tony



> >
> > Also, I rewrote the code so that iphc0 argument of
> > lowpan_alloc_new_frame could be removed.
> > ---
> >  net/ieee802154/6lowpan.c |   20 ++++++++++++--------
> >  1 files changed, 12 insertions(+), 8 deletions(-)
> >
> > diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
> > index af2f12e..b400156 100644
> > --- a/net/ieee802154/6lowpan.c
> > +++ b/net/ieee802154/6lowpan.c
> > @@ -654,7 +654,7 @@ static void
> > lowpan_fragment_timer_expired(unsigned long entry_addr) }
> >
> >  static struct lowpan_fragment *
> > -lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 len, u16
> > tag) +lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
> >  {
> >        struct lowpan_fragment *frame;
> >
> > @@ -665,7 +665,7 @@ lowpan_alloc_new_frame(struct sk_buff *skb, u8
> > iphc0, u8 len, u16 tag)
> >        INIT_LIST_HEAD(&frame->list);
> >
> > -       frame->length = (iphc0 & 7) | (len << 3);
> > +       frame->length = len;
> >        frame->tag = tag;
> >
> >        /* allocate buffer for frame assembling */
> > @@ -721,13 +721,17 @@ lowpan_process_data(struct sk_buff *skb)
> >        case LOWPAN_DISPATCH_FRAGN:
> >        {
> >                struct lowpan_fragment *frame;
> > -               u8 len, offset;
> > -               u16 tag;
> > +               /* slen stores the rightmost 8 bits of the 11 bits
> > length */
> > +               u8 slen, offset;
> > +               u16 len, tag;
> >                bool found = false;
> >
> > -               len = lowpan_fetch_skb_u8(skb); /* frame length */
> > +               slen = lowpan_fetch_skb_u8(skb); /* frame length */
> >                tag = lowpan_fetch_skb_u16(skb);
> >
> > +               /* adds the 3 MSB to the 8 LSB to retrieve the 11
> > bits length */
> > +               len = ((iphc0 & 7) << 8) | slen;
> > +
> >                /*
> >                 * check if frame assembling with the same tag is
> >                 * already in progress
> > @@ -742,7 +746,7 @@ lowpan_process_data(struct sk_buff *skb)
> >
> >                /* alloc new frame structure */
> >                if (!found) {
> > -                       frame = lowpan_alloc_new_frame(skb, iphc0,
> > len, tag);
> > +                       frame = lowpan_alloc_new_frame(skb, len,
> > tag); if (!frame)
> >                                goto unlock_and_drop;
> >                }
> > @@ -1000,8 +1004,8 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
> >        tag = fragment_tag++;
> >
> >        /* first fragment header */
> > -       head[0] = LOWPAN_DISPATCH_FRAG1 | (payload_length & 0x7);
> > -       head[1] = (payload_length >> 3) & 0xff;
> > +       head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) &
> > 0x7);
> > +       head[1] = payload_length & 0xff;
> >        head[2] = tag >> 8;
> >        head[3] = tag & 0xff;
> >
> > --
> > 1.7.3.4
> >
> 
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and 
> threat landscape has changed and how IT managers can respond.
> Discussions will include endpoint security, mobile security and the
> latest in malware threats.
> http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
> _______________________________________________ Linux-zigbee-devel
> mailing list Linux-zigbee-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

^ permalink raw reply

* Re: [PATCH 4/7] usbnet: remove EVENT_DEV_OPEN flag
From: Ming Lei @ 2012-06-13  4:47 UTC (permalink / raw)
  To: Oliver Neukum; +Cc: David S. Miller, Greg Kroah-Hartman, netdev, linux-usb
In-Reply-To: <CACVXFVPf+Q9i-Ju3GFapiTB2wEWZSBrZ2Gf=WHsLWfWfTnWGpA@mail.gmail.com>

On Wed, Jun 13, 2012 at 10:12 AM, Ming Lei <tom.leiming@gmail.com> wrote:
> On Wed, Jun 13, 2012 at 2:14 AM, Oliver Neukum <oliver@neukum.org> wrote:
>> Am Dienstag, 12. Juni 2012, 03:19:42 schrieb Ming Lei:
>>> EVENT_DEV_OPEN is introduced to mark if the interface is opened or
>>> not, but we already have IFF_UP to handle it, so just
>>> remove the flag and use IFF_UP.
>>
>> When is IFF_UP cleared? The flag is tested in usbnet_resume(),
>
> The flag is cleared just after usbnet_stop completes.

Looks we can use the below to replace EVENT_DEV_OPEN:

     (netif_running((dev)->net) && ((dev)->net->flags & IFF_UP))


Thanks,
-- 
Ming Lei

^ permalink raw reply

* Re: [PATCH net-next 3/4] 6lowpan: the two bytes of u16 tag needs to be stored/accessed the other way around
From: Tony Cheneau @ 2012-06-13  4:42 UTC (permalink / raw)
  To: Alexander Smirnov; +Cc: netdev, linux-zigbee-devel
In-Reply-To: <CAJmB2rB20UL_8u1PmJM67dQJ1FaW09irJhz6-OusZwWkgs0kLQ@mail.gmail.com>

Hello Alexander,

Please see my response inline.

Le Tue, 12 Jun 2012 22:07:12 +0400,
Alexander Smirnov <alex.bluesman.smirnov@gmail.com> a écrit :

> 2012/6/11 Tony Cheneau <tony.cheneauh@amnesiak.org>:
> > Or else, tag values, as displayed with a trafic analyser, such a
> > Wireshark, are not properly displayed (e.g. 0x01 00 insted of 0x00
> > 01, and so on). ---
> >  net/ieee802154/6lowpan.c |    6 +++---
> >  1 files changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
> > index af4f29b..af2f12e 100644
> > --- a/net/ieee802154/6lowpan.c
> > +++ b/net/ieee802154/6lowpan.c
> > @@ -307,7 +307,7 @@ static u16 lowpan_fetch_skb_u16(struct sk_buff
> > *skb)
> >
> >        BUG_ON(!pskb_may_pull(skb, 2));
> >
> > -       ret = skb->data[0] | (skb->data[1] << 8);
> > +       ret = (skb->data[0] << 8) | skb->data[1];
> 
> This function aimed to obtain u16 from skb, why did you change the
> byte-order here instead of 'tag' variable byte-shifting? 
This probably reflects my lack of practice in writing/reading network
code. I witnessed in my network that the byte order was wrong when
sending/receiving packet (using Wireshark) and though it would be a
quick fix. Also, I assumed skb->data would store data using network
ordering, so that skb->data[0] would have been the MSB and
skb->data[1] would have been the LSB. I'll look more into that.

> Will this
> code work properly on the both little and big-endian machines?
I haven't checked that. But, just for clarification, if my changes are
not working properly on both architectures, it means that the original
code doesn't either, right?

> Please
> rework this to keep order properly for all the architectures.
I will read some more network code to see how it is handled in other
part of the kernel and rewrite the patch accordingly (if at all
needed). 

Thank you for your advises.

> >        skb_pull(skb, 2);
> >        return ret;
> >  }
> > @@ -1002,8 +1002,8 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
> >        /* first fragment header */
> >        head[0] = LOWPAN_DISPATCH_FRAG1 | (payload_length & 0x7);
> >        head[1] = (payload_length >> 3) & 0xff;
> > -       head[2] = tag & 0xff;
> > -       head[3] = tag >> 8;
> > +       head[2] = tag >> 8;
> > +       head[3] = tag & 0xff;
> >
> >        err = lowpan_fragment_xmit(skb, head, header_length, 0, 0);
> >
> > --
> > 1.7.3.4
> >
> >
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Regards,
	Tony

^ permalink raw reply

* Re: ethtool: allow ETHTOOL_GSSET_INFO for users
From: David Miller @ 2012-06-13  4:33 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, mirq-linux
In-Reply-To: <1339543678.15266.7.camel@bwh-desktop.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Wed, 13 Jun 2012 00:27:58 +0100

> Please consider this for stable 3.0.y and 3.2.y:
> 
> commit f80400a26a2e8bff541de12834a1134358bb6642
> Author: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> Date:   Sun Jan 22 00:20:40 2012 +0000
> 
>     ethtool: allow ETHTOOL_GSSET_INFO for users

Queued up, thanks.

^ permalink raw reply

* Re: [PATCH 2/5] ipv4: Kill ip_rt_frag_needed().
From: David Miller @ 2012-06-13  4:22 UTC (permalink / raw)
  To: steffen.klassert; +Cc: netdev
In-Reply-To: <20120612.133333.527780673034196147.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Tue, 12 Jun 2012 13:33:33 -0700 (PDT)

> What we possibly could do is adjust the socket's IP_PMTUDISC_* setting
> from IP_PMTUDISC_WANT to IP_PMTUDISC_DONT in response to PMTU
> messages.
> 
> This seems to solve all the problems.  Individual RAW and UDP sockets
> get the behavior they did before, and route cache PMTU poisoning is
> less of an issue.

Here is an implementation of that idea:

diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 8260ef7..61cb532 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -416,6 +416,16 @@ static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk)
 	return inet_sk(__sk)->pinet6;
 }
 
+/* We don't want to update the routing tables because there is no way
+ * to validate the legitimacy of this PMTU event.  Instead, downgrade
+ * the PMTU setting of the socket.
+ */
+static inline void inet6_datagram_pmtu_event(struct ipv6_pinfo *np)
+{
+	if (np->pmtudisc == IP_PMTUDISC_WANT)
+		np->pmtudisc = IP_PMTUDISC_DONT;
+}
+
 static inline struct inet6_request_sock *
 			inet6_rsk(const struct request_sock *rsk)
 {
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index ae17e13..2199afb 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -199,6 +199,16 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
 }
 #endif
 
+/* We don't want to update the routing cache because there is no way
+ * to validate the legitimacy of this PMTU event.  Instead, downgrade
+ * the PMTU setting of the socket.
+ */
+static inline void inet_datagram_pmtu_event(struct inet_sock *inet)
+{
+	if (inet->pmtudisc == IP_PMTUDISC_WANT)
+		inet->pmtudisc = IP_PMTUDISC_DONT;
+}
+
 extern int inet_sk_rebuild_header(struct sock *sk);
 
 extern u32 inet_ehash_secret;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 2c00e8b..c6becc1 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -374,6 +374,7 @@ void ping_err(struct sk_buff *skb, u32 info)
 			if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) {
 				err = EMSGSIZE;
 				harderr = 1;
+				inet_datagram_pmtu_event(inet_sock);
 				break;
 			}
 			goto out;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 4032b81..ed24b05 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -244,6 +244,7 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
 		if (code == ICMP_FRAG_NEEDED) {
 			harderr = inet->pmtudisc != IP_PMTUDISC_DONT;
 			err = EMSGSIZE;
+			inet_datagram_pmtu_event(inet);
 		}
 	}
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index eaca736..40cf013 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -618,6 +618,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
 			if (inet->pmtudisc != IP_PMTUDISC_DONT) {
 				err = EMSGSIZE;
 				harderr = 1;
+				inet_datagram_pmtu_event(inet);
 				break;
 			}
 			goto out;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 93d6983..79e2f7a 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -328,9 +328,10 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
 		return;
 
 	harderr = icmpv6_err_convert(type, code, &err);
-	if (type == ICMPV6_PKT_TOOBIG)
+	if (type == ICMPV6_PKT_TOOBIG) {
 		harderr = (np->pmtudisc == IPV6_PMTUDISC_DO);
-
+		inet6_datagram_pmtu_event(np);
+	}
 	if (np->recverr) {
 		u8 *payload = skb->data;
 		if (!inet->hdrincl)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index f05099f..fb57815 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -481,6 +481,9 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
 	np = inet6_sk(sk);
 
+	if (type == ICMPV6_PKT_TOOBIG)
+		inet6_datagram_pmtu_event(np);
+
 	if (!icmpv6_err_convert(type, code, &err) && !np->recverr)
 		goto out;
 

^ permalink raw reply related

* [PATCH 3/3] usbnet: handle remote wakeup asap
From: Ming Lei @ 2012-06-13  4:20 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, netdev, linux-usb, Ming Lei, stable
In-Reply-To: <1339561217-18151-1-git-send-email-ming.lei@canonical.com>

If usbnet is resumed by remote wakeup, generally there are
some packets comming to be handled, so allocate and submit
rx URBs in usbnet_resume to avoid delays introduced by tasklet.
Otherwise, usbnet may have been runtime suspended before the
usbnet_bh is executed to schedule Rx URBs.

Without the patch, usbnet can't recieve any packets from peer
in runtime suspend state if runtime PM is enabled and
autosuspend_delay is set as zero.

Cc: stable@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/usb/usbnet.c |   42 ++++++++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 16 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 9bfa775..4911efa 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1201,6 +1201,21 @@ deferred:
 }
 EXPORT_SYMBOL_GPL(usbnet_start_xmit);
 
+static void rx_alloc_submit(struct usbnet *dev, gfp_t flags)
+{
+	struct urb	*urb;
+	int		i;
+
+	/* don't refill the queue all at once */
+	for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {
+		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (urb != NULL) {
+			if (rx_submit(dev, urb, flags) == -ENOLINK)
+				return;
+		}
+	}
+}
+
 /*-------------------------------------------------------------------------*/
 
 // tasklet (work deferred from completions, in_irq) or timer
@@ -1240,26 +1255,14 @@ static void usbnet_bh (unsigned long param)
 		   !timer_pending (&dev->delay) &&
 		   !test_bit (EVENT_RX_HALT, &dev->flags)) {
 		int	temp = dev->rxq.qlen;
-		int	qlen = RX_QLEN (dev);
-
-		if (temp < qlen) {
-			struct urb	*urb;
-			int		i;
-
-			// don't refill the queue all at once
-			for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
-				urb = usb_alloc_urb (0, GFP_ATOMIC);
-				if (urb != NULL) {
-					if (rx_submit (dev, urb, GFP_ATOMIC) ==
-					    -ENOLINK)
-						return;
-				}
-			}
+
+		if (temp < RX_QLEN(dev)) {
+			rx_alloc_submit(dev, GFP_ATOMIC);
 			if (temp != dev->rxq.qlen)
 				netif_dbg(dev, link, dev->net,
 					  "rxqlen %d --> %d\n",
 					  temp, dev->rxq.qlen);
-			if (dev->rxq.qlen < qlen)
+			if (dev->rxq.qlen < RX_QLEN(dev))
 				tasklet_schedule (&dev->bh);
 		}
 		if (dev->txq.qlen < TX_QLEN (dev))
@@ -1565,6 +1568,13 @@ int usbnet_resume (struct usb_interface *intf)
 		spin_unlock_irq(&dev->txq.lock);
 
 		if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+			/* handle remote wakeup ASAP */
+			if (!dev->wait &&
+				netif_device_present(dev->net) &&
+				!timer_pending(&dev->delay) &&
+				!test_bit(EVENT_RX_HALT, &dev->flags))
+					rx_alloc_submit(dev, GFP_KERNEL);
+
 			if (!(dev->txq.qlen >= TX_QLEN(dev)))
 				netif_tx_wake_all_queues(dev->net);
 			tasklet_schedule (&dev->bh);
-- 
1.7.9.5

^ permalink raw reply related

* usbnet: PM related fixes
From: Ming Lei @ 2012-06-13  4:20 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman; +Cc: Oliver Neukum, netdev, linux-usb

Hi David,

The 3 patches fix some PM related problems.

Sorry for sending them after the cleanup patches since I found them just
after sending out the cleanup patches. 

 drivers/net/usb/usbnet.c |   47 +++++++++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 17 deletions(-)

^ permalink raw reply

* [PATCH 2/3] usbnet: decrease suspend count if returning -EBUSY for runtime suspend
From: Ming Lei @ 2012-06-13  4:20 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Ming Lei,
	stable-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1339561217-18151-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>

This patch decreases dev->suspend_count in the -EBUSY failure path
of usbnet_suspend. Without the change, the later runtime suspend
will do nothing except for increasing dev->suspend_count.

Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 drivers/net/usb/usbnet.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index f06cf9b..9bfa775 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1508,6 +1508,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 		spin_lock_irq(&dev->txq.lock);
 		/* don't autosuspend while transmitting */
 		if (dev->txq.qlen && PMSG_IS_AUTO(message)) {
+			dev->suspend_count--;
 			spin_unlock_irq(&dev->txq.lock);
 			return -EBUSY;
 		} else {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 1/3] usbnet: clear OPEN flag in failure path
From: Ming Lei @ 2012-06-13  4:20 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Ming Lei,
	stable-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1339561217-18151-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>

Without clearing OPEN flag in failure path, runtime or system resume
may submit interrupt/rx URB and start tx queue mistakenly on a
interface in DOWN state.

Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 drivers/net/usb/usbnet.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ac2e493..f06cf9b 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -793,11 +793,13 @@ int usbnet_open (struct net_device *net)
 	if (info->manage_power) {
 		retval = info->manage_power(dev, 1);
 		if (retval < 0)
-			goto done;
+			goto done_manage_power_error;
 		usb_autopm_put_interface(dev->intf);
 	}
 	return retval;
 
+done_manage_power_error:
+	clear_bit(EVENT_DEV_OPEN, &dev->flags);
 done:
 	usb_autopm_put_interface(dev->intf);
 done_nopm:
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 5/5] KVM: Replace test_and_set_bit_le() in mark_page_dirty_in_slot() with set_bit_le()
From: Takuya Yoshikawa @ 2012-06-13  4:05 UTC (permalink / raw)
  To: akpm
  Cc: bhutchings, grundler, arnd, benh, avi, mtosatti,
	linux-net-drivers, netdev, linux-kernel, linux-arch, kvm,
	takuya.yoshikawa
In-Reply-To: <20120613130054.b5695621.yoshikawa.takuya@oss.ntt.co.jp>

From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>

Now that we have defined generic set_bit_le() we do not need to use
test_and_set_bit_le() for atomically setting a bit.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Avi Kivity <avi@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
---
 virt/kvm/kvm_main.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 02cb440..560c502 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1485,8 +1485,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,
 	if (memslot && memslot->dirty_bitmap) {
 		unsigned long rel_gfn = gfn - memslot->base_gfn;
 
-		/* TODO: introduce set_bit_le() and use it */
-		test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap);
+		set_bit_le(rel_gfn, memslot->dirty_bitmap);
 	}
 }
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 4/5] powerpc: bitops: Introduce {clear,set}_bit_le()
From: Takuya Yoshikawa @ 2012-06-13  4:04 UTC (permalink / raw)
  To: akpm
  Cc: bhutchings, grundler, arnd, benh, avi, mtosatti,
	linux-net-drivers, netdev, linux-kernel, linux-arch, kvm,
	takuya.yoshikawa
In-Reply-To: <20120613130054.b5695621.yoshikawa.takuya@oss.ntt.co.jp>

From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>

Needed to replace test_and_set_bit_le() in virt/kvm/kvm_main.c which is
being used for this missing function.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/bitops.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index efdc926..dc2cf9c 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -288,6 +288,16 @@ static __inline__ int test_bit_le(unsigned long nr,
 	return (tmp[nr >> 3] >> (nr & 7)) & 1;
 }
 
+static inline void set_bit_le(int nr, void *addr)
+{
+	set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+	clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
 static inline void __set_bit_le(int nr, void *addr)
 {
 	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 3/5] bitops: Introduce generic {clear,set}_bit_le()
From: Takuya Yoshikawa @ 2012-06-13  4:03 UTC (permalink / raw)
  To: akpm
  Cc: bhutchings, grundler, arnd, benh, avi, mtosatti,
	linux-net-drivers, netdev, linux-kernel, linux-arch, kvm,
	takuya.yoshikawa
In-Reply-To: <20120613130054.b5695621.yoshikawa.takuya@oss.ntt.co.jp>

From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>

Needed to replace test_and_set_bit_le() in virt/kvm/kvm_main.c which is
being used for this missing function.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 include/asm-generic/bitops/le.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h
index f95c663..6173154 100644
--- a/include/asm-generic/bitops/le.h
+++ b/include/asm-generic/bitops/le.h
@@ -54,6 +54,16 @@ static inline int test_bit_le(int nr, const void *addr)
 	return test_bit(nr ^ BITOP_LE_SWIZZLE, addr);
 }
 
+static inline void set_bit_le(int nr, void *addr)
+{
+	set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+	clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
 static inline void __set_bit_le(int nr, void *addr)
 {
 	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 2/5] drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
From: Takuya Yoshikawa @ 2012-06-13  4:03 UTC (permalink / raw)
  To: akpm
  Cc: bhutchings, grundler, arnd, benh, avi, mtosatti,
	linux-net-drivers, netdev, linux-kernel, linux-arch, kvm,
	takuya.yoshikawa
In-Reply-To: <20120613130054.b5695621.yoshikawa.takuya@oss.ntt.co.jp>

From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>

To introduce generic set_bit_le() later, we remove our own definition
and use a proper non-atomic bitops function: __set_bit_le().

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Acked-by: Grant Grundler <grundler@parisc-linux.org>
---
 drivers/net/ethernet/dec/tulip/de2104x.c    |    7 ++-----
 drivers/net/ethernet/dec/tulip/tulip_core.c |    7 ++-----
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 61cc093..77335853 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -661,9 +661,6 @@ static netdev_tx_t de_start_xmit (struct sk_buff *skb,
    new frame, not around filling de->setup_frame.  This is non-deterministic
    when re-entered but still correct. */
 
-#undef set_bit_le
-#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
-
 static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
 {
 	struct de_private *de = netdev_priv(dev);
@@ -673,12 +670,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
 	u16 *eaddrs;
 
 	memset(hash_table, 0, sizeof(hash_table));
-	set_bit_le(255, hash_table); 			/* Broadcast entry */
+	__set_bit_le(255, hash_table);			/* Broadcast entry */
 	/* This should work on big-endian machines as well. */
 	netdev_for_each_mc_addr(ha, dev) {
 		int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;
 
-		set_bit_le(index, hash_table);
+		__set_bit_le(index, hash_table);
 	}
 
 	for (i = 0; i < 32; i++) {
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index c4f37ac..885700a 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1010,9 +1010,6 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
    new frame, not around filling tp->setup_frame.  This is non-deterministic
    when re-entered but still correct. */
 
-#undef set_bit_le
-#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
-
 static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
 {
 	struct tulip_private *tp = netdev_priv(dev);
@@ -1022,12 +1019,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
 	u16 *eaddrs;
 
 	memset(hash_table, 0, sizeof(hash_table));
-	set_bit_le(255, hash_table); 			/* Broadcast entry */
+	__set_bit_le(255, hash_table);			/* Broadcast entry */
 	/* This should work on big-endian machines as well. */
 	netdev_for_each_mc_addr(ha, dev) {
 		int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;
 
-		set_bit_le(index, hash_table);
+		__set_bit_le(index, hash_table);
 	}
 	for (i = 0; i < 32; i++) {
 		*setup_frm++ = hash_table[i];
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 1/5] sfc: Use standard __{clear,set}_bit_le() functions
From: Takuya Yoshikawa @ 2012-06-13  4:02 UTC (permalink / raw)
  To: akpm
  Cc: bhutchings, grundler, arnd, benh, avi, mtosatti,
	linux-net-drivers, netdev, linux-kernel, linux-arch, kvm,
	takuya.yoshikawa
In-Reply-To: <20120613130054.b5695621.yoshikawa.takuya@oss.ntt.co.jp>

From: Ben Hutchings <bhutchings@solarflare.com>

There are now standard functions for dealing with little-endian bit
arrays, so use them instead of our own implementations.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
---
 drivers/net/ethernet/sfc/efx.c        |    4 ++--
 drivers/net/ethernet/sfc/net_driver.h |   12 ------------
 drivers/net/ethernet/sfc/nic.c        |    4 ++--
 3 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index b95f2e1..ca2a348 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1976,14 +1976,14 @@ static void efx_set_rx_mode(struct net_device *net_dev)
 		netdev_for_each_mc_addr(ha, net_dev) {
 			crc = ether_crc_le(ETH_ALEN, ha->addr);
 			bit = crc & (EFX_MCAST_HASH_ENTRIES - 1);
-			set_bit_le(bit, mc_hash->byte);
+			__set_bit_le(bit, mc_hash);
 		}
 
 		/* Broadcast packets go through the multicast hash filter.
 		 * ether_crc_le() of the broadcast address is 0xbe2612ff
 		 * so we always add bit 0xff to the mask.
 		 */
-		set_bit_le(0xff, mc_hash->byte);
+		__set_bit_le(0xff, mc_hash);
 	}
 
 	if (efx->port_enabled)
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 0e57535..6f1a7f7 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1080,18 +1080,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
 	return &rx_queue->buffer[index];
 }
 
-/* Set bit in a little-endian bitfield */
-static inline void set_bit_le(unsigned nr, unsigned char *addr)
-{
-	addr[nr / 8] |= (1 << (nr % 8));
-}
-
-/* Clear bit in a little-endian bitfield */
-static inline void clear_bit_le(unsigned nr, unsigned char *addr)
-{
-	addr[nr / 8] &= ~(1 << (nr % 8));
-}
-
 
 /**
  * EFX_MAX_FRAME_LEN - calculate maximum frame length
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 4a9a5be..bb0172d 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -473,9 +473,9 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 
 		efx_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
 		if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
-			clear_bit_le(tx_queue->queue, (void *)&reg);
+			__clear_bit_le(tx_queue->queue, &reg);
 		else
-			set_bit_le(tx_queue->queue, (void *)&reg);
+			__set_bit_le(tx_queue->queue, &reg);
 		efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
 	}
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 0/5] Introduce generic set_bit_le() -v2
From: Takuya Yoshikawa @ 2012-06-13  4:00 UTC (permalink / raw)
  To: akpm
  Cc: bhutchings, grundler, arnd, benh, avi, mtosatti,
	linux-net-drivers, netdev, linux-kernel, linux-arch, kvm,
	takuya.yoshikawa

  [ Andrew, can you take this or should I send to other person?
    Note: the whole series is against linux-next. ]

KVM is using test_and_set_bit_le() for this missing function; this patch
series corrects this usage.

As some drivers have their own definitions of set_bit_le(), a bit of
preparation is also needed.

  Although these are differently implemented, especially for big-endian
  case, than the generic __set_bit_le(), it should not be a problem to
  use the latter since both maintainers prefer it.

Changes from v1:
  - sfc:     Ben made a patch
  - tulip:   followed suggestion by Grant
  - bitops:  added clear_bit_le -- suggested by Arnd
  - powerpc: added the same code


Ben Hutchings (1):
  sfc: Use standard __{clear,set}_bit_le() functions

Takuya Yoshikawa (4):
  drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
  bitops: Introduce generic {clear,set}_bit_le()
  powerpc: bitops: Introduce {clear,set}_bit_le()
  KVM: Replace test_and_set_bit_le() in mark_page_dirty_in_slot() with set_bit_le()

 arch/powerpc/include/asm/bitops.h           |   10 ++++++++++
 drivers/net/ethernet/dec/tulip/de2104x.c    |    7 ++-----
 drivers/net/ethernet/dec/tulip/tulip_core.c |    7 ++-----
 drivers/net/ethernet/sfc/efx.c              |    4 ++--
 drivers/net/ethernet/sfc/net_driver.h       |   12 ------------
 drivers/net/ethernet/sfc/nic.c              |    4 ++--
 include/asm-generic/bitops/le.h             |   10 ++++++++++
 virt/kvm/kvm_main.c                         |    3 +--
 8 files changed, 29 insertions(+), 28 deletions(-)

-- 
1.7.5.4


^ permalink raw reply

* Re: [PATCH 4/7] usbnet: remove EVENT_DEV_OPEN flag
From: Ming Lei @ 2012-06-13  2:12 UTC (permalink / raw)
  To: Oliver Neukum; +Cc: David S. Miller, Greg Kroah-Hartman, netdev, linux-usb
In-Reply-To: <201206122014.28408.oliver@neukum.org>

On Wed, Jun 13, 2012 at 2:14 AM, Oliver Neukum <oliver@neukum.org> wrote:
> Am Dienstag, 12. Juni 2012, 03:19:42 schrieb Ming Lei:
>> EVENT_DEV_OPEN is introduced to mark if the interface is opened or
>> not, but we already have IFF_UP to handle it, so just
>> remove the flag and use IFF_UP.
>
> When is IFF_UP cleared? The flag is tested in usbnet_resume(),

The flag is cleared just after usbnet_stop completes.

> so it must be cleared before usbnet_stop() is called.

Yes, I see, otherwise system or runtime resume may happen
at the same time with usbnet_stop.

Thanking you for point it out.

Thanks,
-- 
Ming Lei

^ permalink raw reply

* Re: net/netfilter/nf_conntrack_proto_tcp.c:1606:9: error: ‘struct nf_proto_net’ has no member named ‘user’
From: Gao feng @ 2012-06-13  2:06 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: David Miller, wfg, netdev
In-Reply-To: <20120612160304.GA31427@1984>

于 2012年06月13日 00:03, Pablo Neira Ayuso 写道:
> On Tue, Jun 12, 2012 at 07:03:31PM +0800, Gao feng wrote:
>> 于 2012年06月12日 17:29, Pablo Neira Ayuso 写道:
>>
>>>> nf_proto_net.users has different meaning when SYSCTL enabled or disabled.
>>>>
>>>> when SYSCTL enabled,it means if both tcpv4 and tcpv6 register the sysctl,
>>>> it is increased when register sysctl success and decreased when unregister sysctl.
>>>> we can regard it as the refcnt of ctl_table.
>>>>
>>>> when SYSCTL disabled,it just used to identify if the proto's pernet data
>>>> has been initialized.
>>>
>>> We have to use two different counters for this. The conditional
>>> meaning of that variable is really confusing.
>>>
>> Hi David & Pablo
>>
>> Please have a look at this patch and tell me if it's OK.
>> it base on Pable's patch.
> 
> I think we have to merge those tcpv4_init_net and tcpv6_init_net
> functions into one single function tcp_init_net. Then, we can pass
> l4proto->l3proto to init_net:
> 
>         if (proto->init_net) {
>                 ret = proto->init_net(net, l4proto->l3proto);
>                 if (ret < 0)
>                         return ret;
>         }
> 
> Thus, we can check if this is IPv4 or IPv6 and initialize the compat
> part accordingly.

Agree, it will be more clearer and will decrease the redundancy codes.

> 
> Still, we have that pn->users thing:
> 
>         if (!pn->users++) {
>                 for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++)
>                         tn->timeouts[i] = tcp_timeouts[i];
> 
>                 tn->tcp_loose = nf_ct_tcp_loose;
>                 tn->tcp_be_liberal = nf_ct_tcp_be_liberal;
>                 tn->tcp_max_retrans = nf_ct_tcp_max_retrans;
>         }
> 
> Define some pn->initialized boolean. Set it to true at the end of
> the new tcp_init_net.
> 
> Similar thing for other protocol trackers.
> 
> Let me know if you are going to send me patches. In that case, please
> do it on top of the current tree.

Ok,I will clean up it as you said.

> 
> Once that has been cleaned up, we can prepare follow-up patches to
> move the sysctl code to nf_conntrack_proto_*_sysctl.c to reduce the
> ifdef pollution.
> 

^ permalink raw reply

* Re: [PATCH net-next] ethtool: Make more commands available to unprivileged processes
From: David Miller @ 2012-06-13  1:52 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers
In-Reply-To: <1339542341.15266.3.camel@bwh-desktop.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Wed, 13 Jun 2012 00:05:41 +0100

> 'Get' commands should generally not require CAP_NET_ADMIN, with
> the exception of those that expose internal state.
> 
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
> ---
> The one command I'm not sure about is ETHTOOL_STATS.  It might reveal
> too much detail about network traffic.  That said, /proc/net/dev and
> /sys/class/net/*/statistics are already world-readable.

Applied, it just means we need to scrutinize what people put into the
stats a little bit more.

^ permalink raw reply

* Re: [PATCH 1/1] net-next: add dev_loopback_xmit() to avoid duplicate code
From: David Miller @ 2012-06-13  1:52 UTC (permalink / raw)
  To: michel
  Cc: netdev, linux-kernel, kuznet, jmorris, yoshfuji, kaber, edumazet,
	jpirko, mirq-linux, bhutchings
In-Reply-To: <1339532195.2701.8.camel@Thor>

From: Michel Machado <michel@digirati.com.br>
Date: Tue, 12 Jun 2012 16:16:35 -0400

> Add dev_loopback_xmit() in order to deduplicate functions
> ip_dev_loopback_xmit() (in net/ipv4/ip_output.c) and
> ip6_dev_loopback_xmit() (in net/ipv6/ip6_output.c).
> 
> I was about to reinvent the wheel when I noticed that
> ip_dev_loopback_xmit() and ip6_dev_loopback_xmit() do exactly what I
> need and are not IP-only functions, but they were not available to reuse
> elsewhere.
> 
> ip6_dev_loopback_xmit() does not have line "skb_dst_force(skb);", but I
> understand that this is harmless, and should be in dev_loopback_xmit().
> 
> Signed-off-by: Michel Machado <michel@digirati.com.br>

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