netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4 (net.git)] stmmac EEE support
@ 2012-02-28 12:44 Giuseppe CAVALLARO
  2012-02-28 12:44 ` [PATCH 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
                   ` (5 more replies)
  0 siblings, 6 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-28 12:44 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

These patches add the EEE support in the stmmac device driver.
I've tested it on ST STB with the IC+ 101G PHY device that has
this feature.
Initially the EEE for the stmmac has been written by Rayagond
but I 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).

These patches also add a new option for ethtool to enable/disable
the EEE. There is a patch for the ethtool user space application;
I'm sending it too.

Another patch is for Physical Abstraction Layer now able to
manage the MMD registers (clause 45).
Maybe, I could directly add the EEE in the mdio driver.
I didn't that because I wanted to keep the stmmac able to access
to the phy registers through the Physical Abstraction Layer and
w/ having any links to the mdio.o.

Welcome review and advice.
Regards
Peppe

Giuseppe Cavallaro (4):
  phy: add the EEE support and the way to access to the MMD regs
  net: ethtool: add the EEE support
  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       |   27 ++++-
 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       |    7 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   46 ++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  157 +++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 drivers/net/phy/phy_device.c                       |  136 +++++++++++++++++
 include/linux/ethtool.h                            |    7 +
 include/linux/mdio.h                               |    5 +
 include/linux/mii.h                                |   11 ++
 include/linux/phy.h                                |    3 +
 net/core/ethtool.c                                 |   32 ++++
 16 files changed, 571 insertions(+), 24 deletions(-)

-- 
1.7.4.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
@ 2012-02-28 12:44 ` Giuseppe CAVALLARO
  2012-02-28 12:44 ` [PATCH 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-28 12:44 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

This patch adds the initial support for the Energy-Efficient
Ethernet (EEE). It has been tested on IC+101G device on ST STB.

To support the EEE we have to access to the MMD registers 3.20 and
3.60/61. So I added two new functions to read/write the MMD
registers (clause 45)

The upper-layer will invoke the phy_check_eee to properly check
if the EEE is supported by the PHYs.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/phy/phy_device.c |  136 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mdio.h         |    5 ++
 include/linux/mii.h          |   11 ++++
 include/linux/phy.h          |    3 +
 4 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f320f46..c269492e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -30,6 +30,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/mdio.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -898,6 +899,141 @@ int genphy_resume(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_resume);
 
+static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
+				int addr)
+{
+
+	/* Write the desired MMD Devad */
+	bus->write(bus, addr, MII_MMD_CRTL, 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_CRTL,
+		   (devad | MII_MMD_CTRL_FUNC_DATA_NOINCR));
+}
+
+/**
+ * read_phy_mmd - 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 read_phy_mmd(struct mii_bus *bus, int prtad, int devad, int addr)
+{
+	u32 ret;
+
+	mmd_phy_cl45(bus, prtad, devad, addr);
+
+	/* Read the content of the MMD's selected register */
+	ret = bus->read(bus, addr, MII_MMD_DATA);
+	if (ret < 0)
+		return -EIO;
+
+	return ret;
+}
+
+/**
+ * write_phy_mmd - 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 write_phy_mmd(struct mii_bus *bus, int prtad, int devad, int addr,
+			  u32 data)
+{
+	mmd_phy_cl45(bus, prtad, devad, addr);
+
+	/* Write the data into MMD's selected register */
+	bus->write(bus, addr, MII_MMD_DATA, data);
+}
+
+/* phy_check_eee
+ * @dev: device to probe and init
+ *
+ * Description: check if the Energy-Efficient Ethernet (EEE)
+ * is supported by looking at the MMD registers 3.20 and 3.60/61
+ */
+int phy_check_eee(struct phy_device *phydev)
+{
+	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 = read_phy_mmd(phydev->bus, MDIO_EEE_PART_LINK,
+					MDIO_MMD_AN, phydev->addr);
+		if (eee_cap < 0)
+			return eee_cap;
+
+		eee_link = read_phy_mmd(phydev->bus, MDIO_EEE_CAP,
+					MDIO_MMD_PCS, phydev->addr);
+		if (eee_link < 0)
+			return eee_link;
+
+		if (eee_cap && eee_link) {
+			/* Configure the PHY to stop receiving xMII clock
+			 * while it is signaling LPI */
+			int pcs_ctrl = read_phy_mmd(phydev->bus, MDIO_CTRL1,
+						    MDIO_MMD_PCS,
+						    phydev->addr);
+			if (pcs_ctrl < 0)
+				return pcs_ctrl;
+
+			pcs_ctrl |= MDIO_PCS_CLK_STOP_ENABLE;
+			write_phy_mmd(phydev->bus, MDIO_CTRL1, MDIO_MMD_PCS,
+				      phydev->addr, pcs_ctrl);
+
+			ret = 0; /* EEE supported */
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(phy_get_eee_err);
+
+/* phy_get_eee_err
+ * @dev: device to probe and init
+ *
+ * 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 read_phy_mmd(phydev->bus, MDIO_EEE_WK_ERR, MDIO_MMD_PCS,
+			    phydev->addr);
+
+}
+EXPORT_SYMBOL(phy_check_eee);
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index b1494ac..07ee422 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -42,7 +42,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_EEE_CAP		20	/* EEE Capability register */
+#define MDIO_EEE_WK_ERR		22	/* EEE wake error counter */
 #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
+#define MDIO_EEE_ADV		60	/* EEE advertisement */
+#define MDIO_EEE_PART_LINK	61	/* EEE link partner ability */
 
 /* Media-dependent registers. */
 #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
@@ -81,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_CLK_STOP_ENABLE	0x400	/* Stop the clock during LPI */
 
 /* 10 Gb/s */
 #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 2783eca..18457add 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_CRTL		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,15 @@
 #define FLOW_CTRL_TX		0x01
 #define FLOW_CTRL_RX		0x02
 
+/* MMD Access Control register fields */
+#define MII_MMD_CRTL_DEVAD_MASK			0x1f	/* Mask MMD DEVAD*/
+#define MII_MMD_CRTL_FUNC_ADDR			0x0000	/* Address */
+#define MII_MMD_CTRL_FUNC_DATA_NOINCR		0x4000	/* no post increment */
+#define MII_MMD_CTRL_FUNC_DATA_INCR_ON_RDWT	0x8000	/* post increment on
+							 * reads & writes */
+#define MII_MMD_CTRL_FUNC_DATA_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 c599f7ec..2d1b0d5 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -529,6 +529,9 @@ 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_check_eee(struct phy_device *phydev);
+int phy_get_eee_err(struct phy_device *phydev);
+
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
 
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/4] net: ethtool: add the EEE support
  2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
  2012-02-28 12:44 ` [PATCH 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
@ 2012-02-28 12:44 ` Giuseppe CAVALLARO
  2012-02-28 15:45   ` Ben Hutchings
  2012-02-28 12:44 ` [PATCH 3/4] stmmac: update the driver Documentation and add EEE Giuseppe CAVALLARO
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-28 12:44 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

This patch adds two new functions to detect if Energy-Efficient
Ethernet (EEE) is supported and the way to enable/disable it.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 include/linux/ethtool.h |    7 +++++++
 net/core/ethtool.c      |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index da5b2de..fdea3c7 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -43,6 +43,7 @@ struct ethtool_cmd {
 	__u8	eth_tp_mdix;
 	__u8	reserved2;
 	__u32	lp_advertising;	/* Features the link partner advertises */
+	__u32	eee;		/* Energy-Efficient Etehrnet */
 	__u32	reserved[2];
 };
 
@@ -874,6 +875,8 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
  * 		   and flag of the device.
  * @get_dump_data: Get dump data.
  * @set_dump: Set dump specific flags to the device.
+ * @get_eee: Get Energy-Efficient Ethernet (EEE) supported and status.
+ * @set_eee: Set EEE status (enable/disable).
  *
  * All operations are optional (i.e. the function pointer may be set
  * to %NULL) and callers must take this into account.  Callers must
@@ -937,6 +940,8 @@ struct ethtool_ops {
 				 struct ethtool_dump *, void *);
 	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
 
+	int	(*get_eee) (struct net_device *, struct ethtool_value *);
+	int	(*set_eee) (struct net_device *, struct ethtool_value *);
 };
 #endif /* __KERNEL__ */
 
@@ -1010,6 +1015,8 @@ struct ethtool_ops {
 #define ETHTOOL_SET_DUMP	0x0000003e /* Set dump settings */
 #define ETHTOOL_GET_DUMP_FLAG	0x0000003f /* Get dump settings */
 #define ETHTOOL_GET_DUMP_DATA	0x00000040 /* Get dump data */
+#define ETHTOOL_GEEE		0x00000041 /* Get EEE */
+#define ETHTOOL_SEEE		0x00000042 /* Set EEE */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 3f79db1..088b621 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -714,6 +714,32 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
 	return dev->ethtool_ops->set_wol(dev, &wol);
 }
 
+static int ethtool_get_eee(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (!dev->ethtool_ops->get_eee)
+		return -EOPNOTSUPP;
+
+	dev->ethtool_ops->get_eee(dev, &edata);
+
+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
+		return -EFAULT;
+	return 0;
+}
+
+static int ethtool_set_eee(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (!dev->ethtool_ops->set_eee)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
+		return -EFAULT;
+
+	return dev->ethtool_ops->set_eee(dev, &edata);
+}
 static int ethtool_nway_reset(struct net_device *dev)
 {
 	if (!dev->ethtool_ops->nway_reset)
@@ -1368,6 +1394,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 		rc = ethtool_set_value_void(dev, useraddr,
 				       dev->ethtool_ops->set_msglevel);
 		break;
+	case ETHTOOL_GEEE:
+		rc = ethtool_get_eee(dev, useraddr);
+		break;
+	case ETHTOOL_SEEE:
+		rc = ethtool_set_eee(dev, useraddr);
+		break;
 	case ETHTOOL_NWAY_RST:
 		rc = ethtool_nway_reset(dev);
 		break;
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/4] stmmac: update the driver Documentation and add EEE
  2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
  2012-02-28 12:44 ` [PATCH 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
  2012-02-28 12:44 ` [PATCH 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
@ 2012-02-28 12:44 ` Giuseppe CAVALLARO
  2012-02-28 12:44 ` [PATCH 4/4] stmmac: add the Energy Efficient Ethernet support Giuseppe CAVALLARO
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-28 12:44 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

This patch updates the stmmac's documentation adding
some missing files in the secstion to describe the
driver's structure. Also the patch adds a new section
for the EEE support.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 Documentation/networking/stmmac.txt |   36 +++++++++++++++++++++++++++++-----
 1 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index d0aeead..cd38f6e 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -230,9 +230,11 @@ reset procedure etc).
  o Makefile
  o stmmac_main.c: main network device driver;
  o stmmac_mdio.c: mdio functions;
+ o stmmac_pci: PCI driver;
+ o stmmac_platform.c: platform driver
  o stmmac_ethtool.c: ethtool support;
  o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
-		      Only tested on ST40 platforms based.
+		      (only tested on ST40 platforms based);
  o stmmac.h: private driver structure;
  o common.h: common definitions and VFTs;
  o descs.h: descriptor structure definitions;
@@ -242,9 +244,11 @@ reset procedure etc).
  o dwmac100_core: MAC 100 core and dma code;
  o dwmac100_dma.c: dma funtions for the MAC chip;
  o dwmac1000.h: specific header file for the MAC;
- o dwmac_lib.c: generic DMA functions shared among chips
- o enh_desc.c: functions for handling enhanced descriptors
- o norm_desc.c: functions for handling normal descriptors
+ o dwmac_lib.c: generic DMA functions shared among chips;
+ o enh_desc.c: functions for handling enhanced descriptors;
+ o norm_desc.c: functions for handling normal descriptors;
+ o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes;
+ o mmc_core.c/mmc.h: Management MAC Counters;
 
 5) Debug Information
 
@@ -277,7 +281,27 @@ All these are only useful during the developing stage
 and should never enabled inside the code for general usage.
 In fact, these can generate an huge amount of debug messages.
 
-6) TODO:
+6) Energy Efficient Ethernet
+
+Energy Efficient Ethernet(EEE) enables IEEE 802.3 MAC sublayer along
+with a family of Physical layer to operate in the Low power Idle(LPI)
+mode. The EEE mode supports the IEEE 802.3 MAC operation at 100Mbps,
+1000Mbps & 10Gbps.
+
+The LPI mode allows power saving by switching off parts of the
+communication device functionality when there is no data to be
+transmitted & received. The system on both the side of the link can
+disable some functionalities & save power during the period of low-link
+utilization. The MAC controls whether the system should enter or exit
+the LPI mode & communicate this to PHY.
+
+As soon as the interface is opened, the driver verifies if the EEE can
+be supported. This is done by looking at both the DMA HW capability
+register and the PHY devices MCD registers.
+To enter in Tx LPI mode the driver needs to have a software timer
+that enable and disable the LPI mode when there is nothing to be
+transmitted.
+
+7) TODO:
  o XGMAC is not supported.
- o Add the EEE - Energy Efficient Ethernet
  o Add the PTP - precision time protocol
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/4] stmmac: add the Energy Efficient Ethernet support.
  2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
                   ` (2 preceding siblings ...)
  2012-02-28 12:44 ` [PATCH 3/4] stmmac: update the driver Documentation and add EEE Giuseppe CAVALLARO
@ 2012-02-28 12:44 ` Giuseppe CAVALLARO
  2012-02-28 12:46 ` [PATCH] ethtool: add the EEE option Giuseppe CAVALLARO
  2012-02-28 20:18 ` [PATCH 0/4 (net.git)] stmmac EEE support David Miller
  5 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-28 12:44 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro, Rayagond Kokatanur

This patch adds the Energy Efficient Ethernet support.
Please see the driver's documentation for further
information about this support in the driver.

Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/common.h       |   27 ++++-
 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       |    7 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   46 ++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  157 +++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 9 files changed, 347 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 0319d64..4e07692 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -95,6 +95,16 @@ struct stmmac_extra_stats {
 	unsigned long poll_n;
 	unsigned long sched_timer_n;
 	unsigned long normal_irq_n;
+	unsigned long mmc_tx_irq_n;
+	unsigned long mmc_rx_irq_n;
+	unsigned long mmc_rx_csum_offload_irq_n;
+	/* EEE */
+	unsigned long irq_receive_pmt_irq_n;
+	unsigned long irq_tx_path_in_lpi_mode_n;
+	unsigned long irq_tx_path_exit_lpi_mode_n;
+	unsigned long irq_rx_path_in_lpi_mode_n;
+	unsigned long irq_rx_path_exit_lpi_mode_n;
+	unsigned long phy_eee_wakeup_error_n;
 };
 
 #define HASH_TABLE_SIZE 64
@@ -151,6 +161,17 @@ enum tx_dma_irq_status {
 	handle_tx_rx = 3,
 };
 
+enum core_specific_irq_mask {
+	core_mmc_tx_irq = 1,
+	core_mmc_rx_irq = 2,
+	core_mmc_rx_csum_offload_irq = 4,
+	core_irq_receive_pmt_irq = 8,
+	core_irq_tx_path_in_lpi_mode = 16,
+	core_irq_tx_path_exit_lpi_mode = 32,
+	core_irq_rx_path_in_lpi_mode = 64,
+	core_irq_rx_path_exit_lpi_mode = 128,
+};
+
 /* DMA HW capabilities */
 struct dma_features {
 	unsigned int mbps_10_100;
@@ -266,7 +287,7 @@ struct stmmac_ops {
 	/* Dump MAC registers */
 	void (*dump_regs) (void __iomem *ioaddr);
 	/* Handle extra events on specific interrupts hw dependent */
-	void (*host_irq_status) (void __iomem *ioaddr);
+	int (*host_irq_status) (void __iomem *ioaddr);
 	/* Multicast filter setting */
 	void (*set_filter) (struct net_device *dev);
 	/* Flow control setting */
@@ -279,6 +300,10 @@ struct stmmac_ops {
 			       unsigned int reg_n);
 	void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
 			       unsigned int reg_n);
+	void (*set_eee_mode) (void __iomem *ioaddr);
+	void (*reset_eee_mode) (void __iomem *ioaddr);
+	void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
+	void (*set_eee_pls) (void __iomem *ioaddr, int link);
 };
 
 struct mac_link {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index cfcef0e..1764f85 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -36,6 +36,7 @@
 
 #define GMAC_INT_STATUS		0x00000038	/* interrupt status register */
 enum dwmac1000_irq_status {
+	lpiis_irq = 0x400,
 	time_stamp_irq = 0x0200,
 	mmc_rx_csum_offload_irq = 0x0080,
 	mmc_tx_irq = 0x0040,
@@ -60,6 +61,25 @@ enum power_event {
 	power_down = 0x00000001,
 };
 
+/* Energy Efficient Ethernet (EEE)
+ *
+ * LPI status, timer and control register offset
+ */
+#define LPI_CTRL_STATUS	0x0030
+#define LPI_TIMER_CTRL	0x0034
+
+/* LPI control and status defines */
+#define LPI_CTRL_STATUS_LPITXA	0x00080000	/* Enable LPI TX Automate */
+#define LPI_CTRL_STATUS_PLSEN	0x00040000	/* Enable PHY Link Status */
+#define LPI_CTRL_STATUS_PLS	0x00020000	/* PHY Link Status */
+#define LPI_CTRL_STATUS_LPIEN	0x00010000	/* LPI Enable */
+#define LPI_CTRL_STATUS_RLPIST	0x00000200	/* Receive LPI state */
+#define LPI_CTRL_STATUS_TLPIST	0x00000100	/* Transmit LPI state */
+#define LPI_CTRL_STATUS_RLPIEX	0x00000008	/* Receive LPI Exit */
+#define LPI_CTRL_STATUS_RLPIEN	0x00000004	/* Receive LPI Entry */
+#define LPI_CTRL_STATUS_TLPIEX	0x00000002	/* Transmit LPI Exit */
+#define LPI_CTRL_STATUS_TLPIEN	0x00000001	/* Transmit LPI Entry */
+
 /* GMAC HW ADDR regs */
 #define GMAC_ADDR_HIGH(reg)		(0x00000040+(reg * 8))
 #define GMAC_ADDR_LOW(reg)		(0x00000044+(reg * 8))
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b1c48b9..a4fab30 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -187,26 +187,107 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
 }
 
 
-static void dwmac1000_irq_status(void __iomem *ioaddr)
+static int dwmac1000_irq_status(void __iomem *ioaddr)
 {
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+	int status = 0;
 
 	/* Not used events (e.g. MMC interrupts) are not handled. */
-	if ((intr_status & mmc_tx_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
+	if ((intr_status & mmc_tx_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_TX_INTR));
-	if (unlikely(intr_status & mmc_rx_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
+		status |= core_mmc_tx_irq;
+	}
+	if (unlikely(intr_status & mmc_rx_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_INTR));
-	if (unlikely(intr_status & mmc_rx_csum_offload_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
+		status |= core_mmc_rx_irq;
+	}
+	if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
+		status |= core_mmc_rx_csum_offload_irq;
+	}
 	if (unlikely(intr_status & pmt_irq)) {
-		CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
+		CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
 		/* clear the PMT bits 5 and 6 by reading the PMT
 		 * status register. */
 		readl(ioaddr + GMAC_PMT);
+		status |= core_irq_receive_pmt_irq;
 	}
+	/* MAC trx/rx EEE LPI entry/exit interrupts */
+	if (intr_status & lpiis_irq) {
+		/* Clean LPI interrupt by reading the Reg 12 */
+		u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);
+
+		if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
+			CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
+			status |= core_irq_tx_path_in_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
+			CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
+			status |= core_irq_tx_path_exit_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
+			CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
+			status |= core_irq_rx_path_in_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
+			CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
+			status |= core_irq_rx_path_exit_lpi_mode;
+		}
+	}
+
+	return status;
+}
+
+static void  dwmac1000_set_eee_mode(void __iomem *ioaddr)
+{
+	u32 value;
+
+	/* Enable the link status receive on RGMII, SGMII ore SMII
+	 * receive path and instruct the transmit to enter in LPI
+	 * state. */
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+	value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+{
+	u32 value;
+
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+	value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+{
+	u32 value;
+
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+
+	if (link)
+		value |= LPI_CTRL_STATUS_PLS;
+	else
+		value &= ~LPI_CTRL_STATUS_PLS;
+
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+{
+	int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
+
+	/* Program the timers in the LPI timer control register:
+	 * LS: minimum time (ms) for which the link
+	 *  status from PHY should be ok before transmitting
+	 *  the LPI pattern.
+	 * TW: minimum time (us) for which the core waits
+	 *  after it has stopped transmitting the LPI pattern.
+	 */
+	writel(value, ioaddr + LPI_TIMER_CTRL);
 }
 
 static const struct stmmac_ops dwmac1000_ops = {
@@ -219,6 +300,10 @@ static const struct stmmac_ops dwmac1000_ops = {
 	.pmt = dwmac1000_pmt,
 	.set_umac_addr = dwmac1000_set_umac_addr,
 	.get_umac_addr = dwmac1000_get_umac_addr,
+	.set_eee_mode =  dwmac1000_set_eee_mode,
+	.reset_eee_mode =  dwmac1000_reset_eee_mode,
+	.set_eee_timer =  dwmac1000_set_eee_timer,
+	.set_eee_pls =  dwmac1000_set_eee_pls,
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 138fb8d..a11370b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,9 +72,9 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
 		readl(ioaddr + MAC_VLAN2));
 }
 
-static void dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(void __iomem *ioaddr)
 {
-	return;
+	return 0;
 }
 
 static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 437edac..27cbcd7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -69,6 +69,7 @@
 #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
 
 /* DMA Status register defines */
+#define DMA_STATUS_GLPII	0x40000000	/* GMAC LPI interrupt */
 #define DMA_STATUS_GPI		0x10000000	/* PMT interrupt */
 #define DMA_STATUS_GMI		0x08000000	/* MMC interrupt */
 #define DMA_STATUS_GLI		0x04000000	/* GMAC Line interface int */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b4b095f..266fcac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -81,6 +81,10 @@ struct stmmac_priv {
 	struct stmmac_counters mmc;
 	struct dma_features dma_cap;
 	int hw_cap_support;
+	struct timer_list eee_ctrl_timer;
+	bool tx_path_in_lpi_mode;
+	bool eee_enabled;
+	int lpi_irq;
 };
 
 extern int phyaddr;
@@ -99,3 +103,6 @@ int stmmac_dvr_remove(struct net_device *ndev);
 struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 				     struct plat_stmmacenet_data *plat_dat,
 				     void __iomem *addr);
+void stmmac_disable_eee_mode(struct stmmac_priv *priv);
+bool stmmac_eee_init(struct stmmac_priv *priv);
+
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index f98e151..90cce62 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -93,6 +93,16 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(poll_n),
 	STMMAC_STAT(sched_timer_n),
 	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(mmc_tx_irq_n),
+	STMMAC_STAT(mmc_rx_irq_n),
+	STMMAC_STAT(mmc_rx_csum_offload_irq_n),
+	STMMAC_STAT(irq_receive_pmt_irq_n),
+	STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
+	STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
+	STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
+	STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
+	STMMAC_STAT(phy_eee_wakeup_error_n),
 };
 #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
 
@@ -366,6 +376,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
 					     (*(u32 *)p);
 			}
 		}
+		if (priv->eee_enabled) {
+			int val = phy_get_eee_err(priv->phydev);
+			if (val)
+				priv->xstats.phy_eee_wakeup_error_n = val;
+		}
 	}
 	for (i = 0; i < STMMAC_STATS_LEN; i++) {
 		char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
@@ -464,6 +479,35 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	return 0;
 }
 
+static int ethtool_op_get_eee(struct net_device *dev, struct ethtool_value *eee)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if (!priv->dma_cap.eee)
+		return -EOPNOTSUPP;
+
+	eee->data = priv->eee_enabled;
+
+	return 0;
+}
+
+static int ethtool_op_set_eee(struct net_device *dev, struct ethtool_value *eee)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if ((!eee->data) && (priv->eee_enabled)) {
+		stmmac_disable_eee_mode(priv);
+		priv->eee_enabled = eee->data;
+	} else if ((eee->data) && (!priv->eee_enabled))
+		/* We are asking for enabling the EEE but this
+		 * has to be verified by invoking the eee_init function.
+		 * For this reason we cannot set eee_enabled to
+		 * eee->data, directly. */
+		priv->eee_enabled = stmmac_eee_init(priv);
+
+	return 0;
+}
+
 static const struct ethtool_ops stmmac_ethtool_ops = {
 	.begin = stmmac_check_if_running,
 	.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -481,6 +525,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
 	.get_wol = stmmac_get_wol,
 	.set_wol = stmmac_set_wol,
 	.get_sset_count	= stmmac_get_sset_count,
+	.get_eee = ethtool_op_get_eee,
+	.set_eee = ethtool_op_set_eee,
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6ee593a..349423e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -133,6 +133,11 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
 
+static int eee_timer = 1000;
+module_param(eee_timer, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
+#define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
+
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_STMMAC_DEBUG_FS
@@ -197,6 +202,82 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
 					  phydev->speed);
 }
 
+static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
+{
+	/* Check and enter in LPI mode */
+	if ((priv->dirty_tx == priv->cur_tx) &&
+	    (priv->tx_path_in_lpi_mode == false))
+		priv->hw->mac->set_eee_mode(priv->ioaddr);
+}
+
+void stmmac_disable_eee_mode(struct stmmac_priv *priv)
+{
+	/* Exit and disable EEE in case of we are are in LPI state. */
+	priv->hw->mac->reset_eee_mode(priv->ioaddr);
+	del_timer_sync(&priv->eee_ctrl_timer);
+	priv->tx_path_in_lpi_mode = false;
+}
+
+/**
+ * stmmac_eee_ctrl_timer
+ * @arg : data hook
+ * Description:
+ *  If there is no data transfer and if we are not in LPI state,
+ *  then MAC Transmitter can be moved to LPI state.
+ */
+static void stmmac_eee_ctrl_timer(unsigned long arg)
+{
+	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
+
+	stmmac_enable_eee_mode(priv);
+	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+}
+
+/**
+ * stmmac_eee_init
+ * @priv: private device pointer
+ * Description:
+ *  If the EEE support has been enabled while configuring the driver,
+ *  if the GMAC actually supports the EEE (from the HW cap reg) and the
+ *  phy can also manage EEE, so enable the LPI state and start the timer
+ *  to verify if the tx path can enter in LPI state.
+ */
+bool stmmac_eee_init(struct stmmac_priv *priv)
+{
+	bool ret = false;
+
+	/* MAC core supports the EEE feature. */
+	if (priv->dma_cap.eee) {
+
+		/* Check if the PHY supports EEE*/
+		if (phy_check_eee(priv->phydev))
+			goto out;
+
+		init_timer(&priv->eee_ctrl_timer);
+		priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
+		priv->eee_ctrl_timer.data = (unsigned long)priv;
+		priv->eee_ctrl_timer.expires = STMMAC_LPI_TIMER(eee_timer);
+		add_timer(&priv->eee_ctrl_timer);
+
+		priv->hw->mac->set_eee_timer(priv->ioaddr, 0x3e8, 0);
+
+		pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
+
+		ret = true;
+	}
+out:
+	return ret;
+}
+
+static void stmmac_eee_adjust(struct stmmac_priv *priv)
+{
+	/* When the EEE has been already initialised we have to
+	 * modify the PLS bit in the LPI ctrl & status reg according
+	 * to the PHY link status. For this reason. */
+	if (priv->eee_enabled)
+		priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
+}
+
 /**
  * stmmac_adjust_link
  * @dev: net device structure
@@ -217,6 +298,7 @@ static void stmmac_adjust_link(struct net_device *dev)
 	    phydev->addr, phydev->link);
 
 	spin_lock_irqsave(&priv->lock, flags);
+
 	if (phydev->link) {
 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
 
@@ -283,6 +365,8 @@ static void stmmac_adjust_link(struct net_device *dev)
 	if (new_state && netif_msg_link(priv))
 		phy_print_status(phydev);
 
+	stmmac_eee_adjust(priv);
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
@@ -300,7 +384,7 @@ static int stmmac_init_phy(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev;
-	char phy_id[MII_BUS_ID_SIZE + 3];
+	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
 	char bus_id[MII_BUS_ID_SIZE];
 	int interface = priv->plat->interface;
 	priv->oldlink = 0;
@@ -308,11 +392,13 @@ static int stmmac_init_phy(struct net_device *dev)
 	priv->oldduplex = -1;
 
 	snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", priv->plat->bus_id);
-	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
 		 priv->plat->phy_addr);
-	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
+	/* (mii bus id:phy device id)  */
+	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
 
-	phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface);
+	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 0,
+			     interface);
 
 	if (IS_ERR(phydev)) {
 		pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -651,6 +737,11 @@ static void stmmac_tx(struct stmmac_priv *priv)
 		}
 		netif_tx_unlock(priv->dev);
 	}
+
+	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
+		stmmac_enable_eee_mode(priv);
+		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+	}
 	spin_unlock(&priv->tx_lock);
 }
 
@@ -976,6 +1067,17 @@ static int stmmac_open(struct net_device *dev)
 		}
 	}
 
+	/* Request the IRQ lines */
+	if (priv->lpi_irq != -ENXIO) {
+		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
+				  dev->name, dev);
+		if (unlikely(ret < 0)) {
+			pr_err("%s: ERROR: allocating the LPI IRQ %d"
+			       " (error: %d)\n", __func__, priv->lpi_irq, ret);
+			goto open_error_lpiirq;
+		}
+	}
+
 	/* Enable the MAC Rx/Tx */
 	stmmac_set_mac(priv->ioaddr, true);
 
@@ -1011,12 +1113,18 @@ static int stmmac_open(struct net_device *dev)
 	if (priv->phydev)
 		phy_start(priv->phydev);
 
+	priv->eee_enabled = stmmac_eee_init(priv);
+
 	napi_enable(&priv->napi);
 	skb_queue_head_init(&priv->rx_recycle);
 	netif_start_queue(dev);
 
 	return 0;
 
+open_error_lpiirq:
+	if (priv->wol_irq != dev->irq)
+		free_irq(priv->wol_irq, dev);
+
 open_error_wolirq:
 	free_irq(dev->irq, dev);
 
@@ -1040,6 +1148,9 @@ static int stmmac_release(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
+	if (priv->eee_enabled)
+		del_timer_sync(&priv->eee_ctrl_timer);
+
 	/* Stop and disconnect the PHY */
 	if (priv->phydev) {
 		phy_stop(priv->phydev);
@@ -1062,6 +1173,8 @@ static int stmmac_release(struct net_device *dev)
 	free_irq(dev->irq, dev);
 	if (priv->wol_irq != dev->irq)
 		free_irq(priv->wol_irq, dev);
+	if (priv->lpi_irq != -ENXIO)
+		free_irq(priv->lpi_irq, dev);
 
 	/* Stop TX/RX DMA and clear the descriptors */
 	priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1111,6 +1224,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	spin_lock(&priv->tx_lock);
 
+	if (priv->tx_path_in_lpi_mode)
+		stmmac_disable_eee_mode(priv);
+
 	entry = priv->cur_tx % txsize;
 
 #ifdef STMMAC_XMIT_DEBUG
@@ -1485,10 +1601,37 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
 		return IRQ_NONE;
 	}
 
-	if (priv->plat->has_gmac)
-		/* To handle GMAC own interrupts */
-		priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
+	/* To handle GMAC own interrupts */
+	if (priv->plat->has_gmac) {
+		int status = priv->hw->mac->host_irq_status((void __iomem *)
+							    dev->base_addr);
+		if (unlikely(status)) {
+			if (status & core_mmc_tx_irq)
+				priv->xstats.mmc_tx_irq_n++;
+			if (status & core_mmc_rx_irq)
+				priv->xstats.mmc_rx_irq_n++;
+			if (status & core_mmc_rx_csum_offload_irq)
+				priv->xstats.mmc_rx_csum_offload_irq_n++;
+			if (status & core_irq_receive_pmt_irq)
+				priv->xstats.irq_receive_pmt_irq_n++;
+
+			/* For LPI we need to save the tx status */
+			if (status & core_irq_tx_path_in_lpi_mode) {
+				priv->xstats.irq_tx_path_in_lpi_mode_n++;
+				priv->tx_path_in_lpi_mode = true;
+			}
+			if (status & core_irq_tx_path_exit_lpi_mode) {
+				priv->xstats.irq_tx_path_exit_lpi_mode_n++;
+				priv->tx_path_in_lpi_mode = false;
+			}
+			if (status & core_irq_rx_path_in_lpi_mode)
+				priv->xstats.irq_rx_path_in_lpi_mode_n++;
+			if (status & core_irq_rx_path_exit_lpi_mode)
+				priv->xstats.irq_rx_path_exit_lpi_mode_n++;
+		}
+	}
 
+	/* To handle DMA interrupts */
 	stmmac_dma_interrupt(priv);
 
 	return IRQ_HANDLED;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 3aad981..bc0e83f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -94,6 +94,8 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
 	if (priv->wol_irq == -ENXIO)
 		priv->wol_irq = priv->dev->irq;
 
+	priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
+
 	platform_set_drvdata(pdev, priv->dev);
 
 	pr_debug("STMMAC platform driver registration completed");
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH] ethtool: add the EEE option
  2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
                   ` (3 preceding siblings ...)
  2012-02-28 12:44 ` [PATCH 4/4] stmmac: add the Energy Efficient Ethernet support Giuseppe CAVALLARO
@ 2012-02-28 12:46 ` Giuseppe CAVALLARO
  2012-02-28 20:18 ` [PATCH 0/4 (net.git)] stmmac EEE support David Miller
  5 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-28 12:46 UTC (permalink / raw)
  To: netdev; +Cc: bhutchings, Giuseppe Cavallaro

This patch adds a new option to enable/disable the
Energy Efficient Ethernet support: below some example:

bash-3.00# ethtool -s eth0 eee on
stmmac: Energy-Efficient Ethernet initialized

bash-3.00# ./ethtool eth0
Settings for eth0:
	Supported ports: [ TP MII ]
	Supported link modes:   10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
[snip]
	Wake-on: d
	Current message level: 0x0000003f (63)
			       drv probe link timer ifdown ifup
	Link detected: yes
	Energy-Efficient Ethernet: Enabled

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 ethtool-copy.h |    3 +++
 ethtool.c      |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index d904c1a..e17ae37 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -40,6 +40,7 @@ struct ethtool_cmd {
 	__u8	eth_tp_mdix;
 	__u8	reserved2;
 	__u32	lp_advertising;	/* Features the link partner advertises */
+	__u32	eee;		/* Energy-Efficient Etehrnet */
 	__u32	reserved[2];
 };
 
@@ -786,6 +787,8 @@ enum ethtool_sfeatures_retval_bits {
 #define ETHTOOL_SET_DUMP	0x0000003e /* Set dump settings */
 #define ETHTOOL_GET_DUMP_FLAG	0x0000003f /* Get dump settings */
 #define ETHTOOL_GET_DUMP_DATA	0x00000040 /* Get dump data */
+#define ETHTOOL_GEEE		0x00000041 /* Get EEE */
+#define ETHTOOL_SEEE		0x00000042 /* Set EEE */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/ethtool.c b/ethtool.c
index d0cc7d4..9e63973 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1840,6 +1840,18 @@ static int do_gset(struct cmd_context *ctx)
 	} else if (errno != EOPNOTSUPP) {
 		perror("Cannot get link status");
 	}
+	edata.cmd = ETHTOOL_GEEE;
+	err = send_ioctl(ctx, &edata);
+	if (err == 0) {
+		fprintf(stdout, "	Energy-Efficient Ethernet: %s\n",
+			edata.data ? "enabled" : "disabled");
+		allfail = 0;
+	} else if (errno != EOPNOTSUPP) {
+		perror("Cannot get EEE feature");
+	} else if (errno == EOPNOTSUPP) {
+		fprintf(stdout, "	Energy-Efficient Ethernet:"
+				" not supported\n");
+	}
 
 	if (allfail) {
 		fprintf(stdout, "No data available\n");
@@ -1857,6 +1869,8 @@ static int do_sset(struct cmd_context *ctx)
 	int phyad_wanted = -1;
 	int xcvr_wanted = -1;
 	int advertising_wanted = -1;
+	int eee_wanted = -1;
+	int eee_changed = 0;
 	int gset_changed = 0; /* did anything in GSET change? */
 	u32 wol_wanted = 0;
 	int wol_change = 0;
@@ -1983,6 +1997,17 @@ static int do_sset(struct cmd_context *ctx)
 					ARRAY_SIZE(cmdline_msglvl));
 				break;
 			}
+		} else if (!strcmp(argp[i], "eee")) {
+			eee_changed = 1;
+			i++;
+			if (i >= argc)
+				exit_bad_args();
+			if (!strcmp(argp[i], "on"))
+				eee_wanted = 1;
+			else if (!strcmp(argp[i], "off"))
+				eee_wanted = 0;
+			else
+				exit_bad_args();
 		} else {
 			exit_bad_args();
 		}
@@ -2129,6 +2154,23 @@ static int do_sset(struct cmd_context *ctx)
 		}
 	}
 
+	if (eee_changed) {
+		struct ethtool_value edata;
+
+		edata.cmd = ETHTOOL_GEEE;
+		err = send_ioctl(ctx, &edata);
+		if (err < 0)
+			perror("Cannot get current EEE settings");
+		else {
+			edata.cmd = ETHTOOL_SEEE;
+			edata.data = eee_wanted;
+			err = send_ioctl(ctx, &edata);
+			if (err < 0)
+				fprintf(stderr, "Cannot turn %s the EEE",
+					(eee_wanted ? "on" : "off"));
+		}
+	}
+
 	if (msglvl_changed) {
 		struct ethtool_value edata;
 
@@ -3129,7 +3171,8 @@ static const struct option {
 	  "		[ xcvr internal|external ]\n"
 	  "		[ wol p|u|m|b|a|g|s|d... ]\n"
 	  "		[ sopass %x:%x:%x:%x:%x:%x ]\n"
-	  "		[ msglvl %d | msglvl type on|off ... ]\n" },
+	  "		[ msglvl %d | msglvl type on|off ]\n"
+	  "		[ eee on|off ... ]\n" },
 	{ "-a|--show-pause", 1, do_gpause, "Show pause options" },
 	{ "-A|--pause", 1, do_spause, "Set pause options",
 	  "		[ autoneg on|off ]\n"
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/4] net: ethtool: add the EEE support
  2012-02-28 12:44 ` [PATCH 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
@ 2012-02-28 15:45   ` Ben Hutchings
  2012-02-29 16:12     ` Giuseppe CAVALLARO
  0 siblings, 1 reply; 23+ messages in thread
From: Ben Hutchings @ 2012-02-28 15:45 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev

On Tue, 2012-02-28 at 13:44 +0100, Giuseppe CAVALLARO wrote:
> This patch adds two new functions to detect if Energy-Efficient
> Ethernet (EEE) is supported and the way to enable/disable it.
> 
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> ---
>  include/linux/ethtool.h |    7 +++++++
>  net/core/ethtool.c      |   32 ++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index da5b2de..fdea3c7 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -43,6 +43,7 @@ struct ethtool_cmd {
>  	__u8	eth_tp_mdix;
>  	__u8	reserved2;
>  	__u32	lp_advertising;	/* Features the link partner advertises */
> +	__u32	eee;		/* Energy-Efficient Etehrnet */
>  	__u32	reserved[2];
>  };

You can't change the size of this structure.

> @@ -874,6 +875,8 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
>   * 		   and flag of the device.
>   * @get_dump_data: Get dump data.
>   * @set_dump: Set dump specific flags to the device.
> + * @get_eee: Get Energy-Efficient Ethernet (EEE) supported and status.
> + * @set_eee: Set EEE status (enable/disable).
>   *
>   * All operations are optional (i.e. the function pointer may be set
>   * to %NULL) and callers must take this into account.  Callers must
> @@ -937,6 +940,8 @@ struct ethtool_ops {
>  				 struct ethtool_dump *, void *);
>  	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
>  
> +	int	(*get_eee) (struct net_device *, struct ethtool_value *);
> +	int	(*set_eee) (struct net_device *, struct ethtool_value *);
[...]

Why are there new operations as well as a new field to ethtool_cmd?

Is the value a boolean or a bitmask?

Since EEE is an auto-negotiated feature, why aren't you defining flags
for the supported/advertising/lp_advertising fields?

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	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/4 (net.git)] stmmac EEE support
  2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
                   ` (4 preceding siblings ...)
  2012-02-28 12:46 ` [PATCH] ethtool: add the EEE option Giuseppe CAVALLARO
@ 2012-02-28 20:18 ` David Miller
  2012-02-29 16:07   ` Giuseppe CAVALLARO
  5 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2012-02-28 20:18 UTC (permalink / raw)
  To: peppe.cavallaro; +Cc: netdev


Patches adding new features should target net-next.git not net.git

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/4 (net.git)] stmmac EEE support
  2012-02-28 20:18 ` [PATCH 0/4 (net.git)] stmmac EEE support David Miller
@ 2012-02-29 16:07   ` Giuseppe CAVALLARO
  2012-03-06  8:28     ` [net-next 0/4] stmmac: add the " Giuseppe CAVALLARO
  0 siblings, 1 reply; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-29 16:07 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On 2/28/2012 9:18 PM, David Miller wrote:
> 
> Patches adding new features should target net-next.git not net.git
> 

Sorry David, I'll resend all patches against net-next.

Peppe

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/4] net: ethtool: add the EEE support
  2012-02-28 15:45   ` Ben Hutchings
@ 2012-02-29 16:12     ` Giuseppe CAVALLARO
  2012-02-29 17:00       ` Ben Hutchings
  0 siblings, 1 reply; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-02-29 16:12 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev

Hello Ben,

On 2/28/2012 4:45 PM, Ben Hutchings wrote:
> On Tue, 2012-02-28 at 13:44 +0100, Giuseppe CAVALLARO wrote:
>> This patch adds two new functions to detect if Energy-Efficient
>> Ethernet (EEE) is supported and the way to enable/disable it.
>>
>> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>> ---
>>  include/linux/ethtool.h |    7 +++++++
>>  net/core/ethtool.c      |   32 ++++++++++++++++++++++++++++++++
>>  2 files changed, 39 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index da5b2de..fdea3c7 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -43,6 +43,7 @@ struct ethtool_cmd {
>>  	__u8	eth_tp_mdix;
>>  	__u8	reserved2;
>>  	__u32	lp_advertising;	/* Features the link partner advertises */
>> +	__u32	eee;		/* Energy-Efficient Etehrnet */
>>  	__u32	reserved[2];
>>  };
> 
> You can't change the size of this structure.

hmm, sorry but it's likely I missed something. Let me review the code
and so I come back on this.
> 
>> @@ -874,6 +875,8 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
>>   * 		   and flag of the device.
>>   * @get_dump_data: Get dump data.
>>   * @set_dump: Set dump specific flags to the device.
>> + * @get_eee: Get Energy-Efficient Ethernet (EEE) supported and status.
>> + * @set_eee: Set EEE status (enable/disable).
>>   *
>>   * All operations are optional (i.e. the function pointer may be set
>>   * to %NULL) and callers must take this into account.  Callers must
>> @@ -937,6 +940,8 @@ struct ethtool_ops {
>>  				 struct ethtool_dump *, void *);
>>  	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
>>  
>> +	int	(*get_eee) (struct net_device *, struct ethtool_value *);
>> +	int	(*set_eee) (struct net_device *, struct ethtool_value *);
> [...]
> 
> Why are there new operations as well as a new field to ethtool_cmd?
> 
> Is the value a boolean or a bitmask?

the former.
These are for enabling/disabling the EEE and also to get the status.

> Since EEE is an auto-negotiated feature, why aren't you defining flags
> for the supported/advertising/lp_advertising fields?

I added these because the stmmac needs to have a timer to enter in LPI
tx mode. So this can be stopped by using ethtool.
I didn't define flags for supported/advertising/lp_advertising because
these are fixed in the RO MMD register and it makes no sense to modify
them (hmm, I think :-)).

Regards
Peppe

> 
> Ben.
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/4] net: ethtool: add the EEE support
  2012-02-29 16:12     ` Giuseppe CAVALLARO
@ 2012-02-29 17:00       ` Ben Hutchings
  0 siblings, 0 replies; 23+ messages in thread
From: Ben Hutchings @ 2012-02-29 17:00 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev

On Wed, 2012-02-29 at 17:12 +0100, Giuseppe CAVALLARO wrote:
> Hello Ben,
> 
> On 2/28/2012 4:45 PM, Ben Hutchings wrote:
> > On Tue, 2012-02-28 at 13:44 +0100, Giuseppe CAVALLARO wrote:
[...]
> >> @@ -937,6 +940,8 @@ struct ethtool_ops {
> >>  				 struct ethtool_dump *, void *);
> >>  	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
> >>  
> >> +	int	(*get_eee) (struct net_device *, struct ethtool_value *);
> >> +	int	(*set_eee) (struct net_device *, struct ethtool_value *);
> > [...]
> > 
> > Why are there new operations as well as a new field to ethtool_cmd?
> > 
> > Is the value a boolean or a bitmask?
> 
> the former.
> These are for enabling/disabling the EEE and also to get the status.
> 
> > Since EEE is an auto-negotiated feature, why aren't you defining flags
> > for the supported/advertising/lp_advertising fields?
> 
> I added these because the stmmac needs to have a timer to enter in LPI
> tx mode. So this can be stopped by using ethtool.
> I didn't define flags for supported/advertising/lp_advertising because
> these are fixed in the RO MMD register and it makes no sense to modify
> them (hmm, I think :-)).

It is certainly necessary to distinguish:
a. PHY is advertising EEE
from
b. Link partner is advertising EEE
or
c. EEE will be used (= a && b)

I haven't had anything to do with PHY drivers for a while but it looks
like you should be able to map MDIO register 3.20 to supported flags,
7.60 to advertising and 7.61 to lp_advertising.

Even if your particular device doesn't support these MDIO registers,
other devices will.  So I think you should define the flags and then if
you don't have that fine control you should check in your set_settings
implementation that the advertising value either has all the EEE mode
flags clear or has all the modes the hardware supports set.

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	[flat|nested] 23+ messages in thread

* [net-next 0/4] stmmac: add the EEE support
  2012-02-29 16:07   ` Giuseppe CAVALLARO
@ 2012-03-06  8:28     ` Giuseppe CAVALLARO
  2012-03-06  8:28       ` [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
                         ` (3 more replies)
  0 siblings, 4 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-06  8:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, bhutchings, rayagond, Giuseppe Cavallaro

These patches add the EEE support in the stmmac device driver;
Patches have been built against net-next.git repository.

Please discard the previous ones sent for net.git.

I've tested it on ST STB with the IC+ 101G PHY device that has
this feature.
Initially the EEE for the stmmac has been written by Rayagond
but I 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).

These patches also add a new option for ethtool to enable/disable
the EEE.
I've already sent the patch for the ethtool user space application.

Another patch is for Physical Abstraction Layer now able to
manage the MMD registers (clause 45).
Maybe, I could directly add the EEE in the mdio driver.
I didn't that because I wanted to keep the stmmac able to access
to the phy registers through the Physical Abstraction Layer and
w/ having any links to the mdio.o.

Welcome review and advice.
Regards
Peppe

Giuseppe Cavallaro (4):
  phy: add the EEE support and the way to access to the MMD regs
  net: ethtool: add the EEE support
  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       |   27 ++++-
 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       |    7 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   46 ++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  157 +++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 drivers/net/phy/phy_device.c                       |  136 +++++++++++++++++
 include/linux/ethtool.h                            |    7 +
 include/linux/mdio.h                               |    5 +
 include/linux/mii.h                                |   11 ++
 include/linux/phy.h                                |    3 +
 net/core/ethtool.c                                 |   32 ++++
 16 files changed, 571 insertions(+), 24 deletions(-)

-- 
1.7.4.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-03-06  8:28     ` [net-next 0/4] stmmac: add the " Giuseppe CAVALLARO
@ 2012-03-06  8:28       ` Giuseppe CAVALLARO
  2012-03-06 16:55         ` Ben Hutchings
  2012-03-06  8:28       ` [net-next 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-06  8:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, bhutchings, rayagond, Giuseppe Cavallaro

This patch adds the initial support for the Energy-Efficient
Ethernet (EEE). It has been tested on IC+101G device on ST STB.

To support the EEE we have to access to the MMD registers 3.20 and
3.60/61. So I added two new functions to read/write the MMD
registers (clause 45)

The upper-layer will invoke the phy_check_eee to properly check
if the EEE is supported by the PHYs.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/phy/phy_device.c |  136 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mdio.h         |    5 ++
 include/linux/mii.h          |   11 ++++
 include/linux/phy.h          |    3 +
 4 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f320f46..c269492e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -30,6 +30,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/mdio.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -898,6 +899,141 @@ int genphy_resume(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_resume);
 
+static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
+				int addr)
+{
+
+	/* Write the desired MMD Devad */
+	bus->write(bus, addr, MII_MMD_CRTL, 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_CRTL,
+		   (devad | MII_MMD_CTRL_FUNC_DATA_NOINCR));
+}
+
+/**
+ * read_phy_mmd - 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 read_phy_mmd(struct mii_bus *bus, int prtad, int devad, int addr)
+{
+	u32 ret;
+
+	mmd_phy_cl45(bus, prtad, devad, addr);
+
+	/* Read the content of the MMD's selected register */
+	ret = bus->read(bus, addr, MII_MMD_DATA);
+	if (ret < 0)
+		return -EIO;
+
+	return ret;
+}
+
+/**
+ * write_phy_mmd - 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 write_phy_mmd(struct mii_bus *bus, int prtad, int devad, int addr,
+			  u32 data)
+{
+	mmd_phy_cl45(bus, prtad, devad, addr);
+
+	/* Write the data into MMD's selected register */
+	bus->write(bus, addr, MII_MMD_DATA, data);
+}
+
+/* phy_check_eee
+ * @dev: device to probe and init
+ *
+ * Description: check if the Energy-Efficient Ethernet (EEE)
+ * is supported by looking at the MMD registers 3.20 and 3.60/61
+ */
+int phy_check_eee(struct phy_device *phydev)
+{
+	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 = read_phy_mmd(phydev->bus, MDIO_EEE_PART_LINK,
+					MDIO_MMD_AN, phydev->addr);
+		if (eee_cap < 0)
+			return eee_cap;
+
+		eee_link = read_phy_mmd(phydev->bus, MDIO_EEE_CAP,
+					MDIO_MMD_PCS, phydev->addr);
+		if (eee_link < 0)
+			return eee_link;
+
+		if (eee_cap && eee_link) {
+			/* Configure the PHY to stop receiving xMII clock
+			 * while it is signaling LPI */
+			int pcs_ctrl = read_phy_mmd(phydev->bus, MDIO_CTRL1,
+						    MDIO_MMD_PCS,
+						    phydev->addr);
+			if (pcs_ctrl < 0)
+				return pcs_ctrl;
+
+			pcs_ctrl |= MDIO_PCS_CLK_STOP_ENABLE;
+			write_phy_mmd(phydev->bus, MDIO_CTRL1, MDIO_MMD_PCS,
+				      phydev->addr, pcs_ctrl);
+
+			ret = 0; /* EEE supported */
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(phy_get_eee_err);
+
+/* phy_get_eee_err
+ * @dev: device to probe and init
+ *
+ * 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 read_phy_mmd(phydev->bus, MDIO_EEE_WK_ERR, MDIO_MMD_PCS,
+			    phydev->addr);
+
+}
+EXPORT_SYMBOL(phy_check_eee);
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index dfb9479..a2dfe86 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_EEE_CAP		20	/* EEE Capability register */
+#define MDIO_EEE_WK_ERR		22	/* EEE wake error counter */
 #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
+#define MDIO_EEE_ADV		60	/* EEE advertisement */
+#define MDIO_EEE_PART_LINK	61	/* EEE link partner ability */
 
 /* Media-dependent registers. */
 #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
@@ -82,6 +86,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_CLK_STOP_ENABLE	0x400	/* Stop the clock during LPI */
 
 /* 10 Gb/s */
 #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 2783eca..18457add 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_CRTL		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,15 @@
 #define FLOW_CTRL_TX		0x01
 #define FLOW_CTRL_RX		0x02
 
+/* MMD Access Control register fields */
+#define MII_MMD_CRTL_DEVAD_MASK			0x1f	/* Mask MMD DEVAD*/
+#define MII_MMD_CRTL_FUNC_ADDR			0x0000	/* Address */
+#define MII_MMD_CTRL_FUNC_DATA_NOINCR		0x4000	/* no post increment */
+#define MII_MMD_CTRL_FUNC_DATA_INCR_ON_RDWT	0x8000	/* post increment on
+							 * reads & writes */
+#define MII_MMD_CTRL_FUNC_DATA_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 c599f7ec..2d1b0d5 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -529,6 +529,9 @@ 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_check_eee(struct phy_device *phydev);
+int phy_get_eee_err(struct phy_device *phydev);
+
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
 
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next 2/4] net: ethtool: add the EEE support
  2012-03-06  8:28     ` [net-next 0/4] stmmac: add the " Giuseppe CAVALLARO
  2012-03-06  8:28       ` [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
@ 2012-03-06  8:28       ` Giuseppe CAVALLARO
  2012-03-06 16:56         ` Ben Hutchings
  2012-03-06  8:28       ` [net-next 3/4] stmmac: update the driver Documentation and add EEE Giuseppe CAVALLARO
  2012-03-06  8:28       ` [net-next 4/4] stmmac: add the Energy Efficient Ethernet support Giuseppe CAVALLARO
  3 siblings, 1 reply; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-06  8:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, bhutchings, rayagond, Giuseppe Cavallaro

This patch adds two new functions to detect if Energy-Efficient
Ethernet (EEE) is supported and the way to enable/disable it.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 include/linux/ethtool.h |    7 +++++++
 net/core/ethtool.c      |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index e1d9e0e..8aed0dd 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -48,6 +48,7 @@ struct ethtool_cmd {
 	__u8	eth_tp_mdix;
 	__u8	reserved2;
 	__u32	lp_advertising;	/* Features the link partner advertises */
+	__u32	eee;		/* Energy-Efficient Etehrnet */
 	__u32	reserved[2];
 };
 
@@ -893,6 +894,8 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
  * 		   and flag of the device.
  * @get_dump_data: Get dump data.
  * @set_dump: Set dump specific flags to the device.
+ * @get_eee: Get Energy-Efficient Ethernet (EEE) supported and status.
+ * @set_eee: Set EEE status (enable/disable).
  *
  * All operations are optional (i.e. the function pointer may be set
  * to %NULL) and callers must take this into account.  Callers must
@@ -956,6 +959,8 @@ struct ethtool_ops {
 				 struct ethtool_dump *, void *);
 	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
 
+	int	(*get_eee) (struct net_device *, struct ethtool_value *);
+	int	(*set_eee) (struct net_device *, struct ethtool_value *);
 };
 #endif /* __KERNEL__ */
 
@@ -1029,6 +1034,8 @@ struct ethtool_ops {
 #define ETHTOOL_SET_DUMP	0x0000003e /* Set dump settings */
 #define ETHTOOL_GET_DUMP_FLAG	0x0000003f /* Get dump settings */
 #define ETHTOOL_GET_DUMP_DATA	0x00000040 /* Get dump data */
+#define ETHTOOL_GEEE		0x00000041 /* Get EEE */
+#define ETHTOOL_SEEE		0x00000042 /* Set EEE */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 6d6d7d2..f47075e 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -716,6 +716,32 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
 	return dev->ethtool_ops->set_wol(dev, &wol);
 }
 
+static int ethtool_get_eee(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (!dev->ethtool_ops->get_eee)
+		return -EOPNOTSUPP;
+
+	dev->ethtool_ops->get_eee(dev, &edata);
+
+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
+		return -EFAULT;
+	return 0;
+}
+
+static int ethtool_set_eee(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (!dev->ethtool_ops->set_eee)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
+		return -EFAULT;
+
+	return dev->ethtool_ops->set_eee(dev, &edata);
+}
 static int ethtool_nway_reset(struct net_device *dev)
 {
 	if (!dev->ethtool_ops->nway_reset)
@@ -1370,6 +1396,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 		rc = ethtool_set_value_void(dev, useraddr,
 				       dev->ethtool_ops->set_msglevel);
 		break;
+	case ETHTOOL_GEEE:
+		rc = ethtool_get_eee(dev, useraddr);
+		break;
+	case ETHTOOL_SEEE:
+		rc = ethtool_set_eee(dev, useraddr);
+		break;
 	case ETHTOOL_NWAY_RST:
 		rc = ethtool_nway_reset(dev);
 		break;
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next 3/4] stmmac: update the driver Documentation and add EEE
  2012-03-06  8:28     ` [net-next 0/4] stmmac: add the " Giuseppe CAVALLARO
  2012-03-06  8:28       ` [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
  2012-03-06  8:28       ` [net-next 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
@ 2012-03-06  8:28       ` Giuseppe CAVALLARO
  2012-03-06  8:28       ` [net-next 4/4] stmmac: add the Energy Efficient Ethernet support Giuseppe CAVALLARO
  3 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-06  8:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, bhutchings, rayagond, Giuseppe Cavallaro

This patch updates the stmmac's documentation adding
some missing files in the secstion to describe the
driver's structure. Also the patch adds a new section
for the EEE support.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 Documentation/networking/stmmac.txt |   36 +++++++++++++++++++++++++++++-----
 1 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index d0aeead..cd38f6e 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -230,9 +230,11 @@ reset procedure etc).
  o Makefile
  o stmmac_main.c: main network device driver;
  o stmmac_mdio.c: mdio functions;
+ o stmmac_pci: PCI driver;
+ o stmmac_platform.c: platform driver
  o stmmac_ethtool.c: ethtool support;
  o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
-		      Only tested on ST40 platforms based.
+		      (only tested on ST40 platforms based);
  o stmmac.h: private driver structure;
  o common.h: common definitions and VFTs;
  o descs.h: descriptor structure definitions;
@@ -242,9 +244,11 @@ reset procedure etc).
  o dwmac100_core: MAC 100 core and dma code;
  o dwmac100_dma.c: dma funtions for the MAC chip;
  o dwmac1000.h: specific header file for the MAC;
- o dwmac_lib.c: generic DMA functions shared among chips
- o enh_desc.c: functions for handling enhanced descriptors
- o norm_desc.c: functions for handling normal descriptors
+ o dwmac_lib.c: generic DMA functions shared among chips;
+ o enh_desc.c: functions for handling enhanced descriptors;
+ o norm_desc.c: functions for handling normal descriptors;
+ o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes;
+ o mmc_core.c/mmc.h: Management MAC Counters;
 
 5) Debug Information
 
@@ -277,7 +281,27 @@ All these are only useful during the developing stage
 and should never enabled inside the code for general usage.
 In fact, these can generate an huge amount of debug messages.
 
-6) TODO:
+6) Energy Efficient Ethernet
+
+Energy Efficient Ethernet(EEE) enables IEEE 802.3 MAC sublayer along
+with a family of Physical layer to operate in the Low power Idle(LPI)
+mode. The EEE mode supports the IEEE 802.3 MAC operation at 100Mbps,
+1000Mbps & 10Gbps.
+
+The LPI mode allows power saving by switching off parts of the
+communication device functionality when there is no data to be
+transmitted & received. The system on both the side of the link can
+disable some functionalities & save power during the period of low-link
+utilization. The MAC controls whether the system should enter or exit
+the LPI mode & communicate this to PHY.
+
+As soon as the interface is opened, the driver verifies if the EEE can
+be supported. This is done by looking at both the DMA HW capability
+register and the PHY devices MCD registers.
+To enter in Tx LPI mode the driver needs to have a software timer
+that enable and disable the LPI mode when there is nothing to be
+transmitted.
+
+7) TODO:
  o XGMAC is not supported.
- o Add the EEE - Energy Efficient Ethernet
  o Add the PTP - precision time protocol
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next 4/4] stmmac: add the Energy Efficient Ethernet support.
  2012-03-06  8:28     ` [net-next 0/4] stmmac: add the " Giuseppe CAVALLARO
                         ` (2 preceding siblings ...)
  2012-03-06  8:28       ` [net-next 3/4] stmmac: update the driver Documentation and add EEE Giuseppe CAVALLARO
@ 2012-03-06  8:28       ` Giuseppe CAVALLARO
  3 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-06  8:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, bhutchings, rayagond, Giuseppe Cavallaro

This patch adds the Energy Efficient Ethernet support.
Please see the driver's documentation for further
information about this support in the driver.

Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/common.h       |   27 ++++-
 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       |    7 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   46 ++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  157 +++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 9 files changed, 347 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 0319d64..4e07692 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -95,6 +95,16 @@ struct stmmac_extra_stats {
 	unsigned long poll_n;
 	unsigned long sched_timer_n;
 	unsigned long normal_irq_n;
+	unsigned long mmc_tx_irq_n;
+	unsigned long mmc_rx_irq_n;
+	unsigned long mmc_rx_csum_offload_irq_n;
+	/* EEE */
+	unsigned long irq_receive_pmt_irq_n;
+	unsigned long irq_tx_path_in_lpi_mode_n;
+	unsigned long irq_tx_path_exit_lpi_mode_n;
+	unsigned long irq_rx_path_in_lpi_mode_n;
+	unsigned long irq_rx_path_exit_lpi_mode_n;
+	unsigned long phy_eee_wakeup_error_n;
 };
 
 #define HASH_TABLE_SIZE 64
@@ -151,6 +161,17 @@ enum tx_dma_irq_status {
 	handle_tx_rx = 3,
 };
 
+enum core_specific_irq_mask {
+	core_mmc_tx_irq = 1,
+	core_mmc_rx_irq = 2,
+	core_mmc_rx_csum_offload_irq = 4,
+	core_irq_receive_pmt_irq = 8,
+	core_irq_tx_path_in_lpi_mode = 16,
+	core_irq_tx_path_exit_lpi_mode = 32,
+	core_irq_rx_path_in_lpi_mode = 64,
+	core_irq_rx_path_exit_lpi_mode = 128,
+};
+
 /* DMA HW capabilities */
 struct dma_features {
 	unsigned int mbps_10_100;
@@ -266,7 +287,7 @@ struct stmmac_ops {
 	/* Dump MAC registers */
 	void (*dump_regs) (void __iomem *ioaddr);
 	/* Handle extra events on specific interrupts hw dependent */
-	void (*host_irq_status) (void __iomem *ioaddr);
+	int (*host_irq_status) (void __iomem *ioaddr);
 	/* Multicast filter setting */
 	void (*set_filter) (struct net_device *dev);
 	/* Flow control setting */
@@ -279,6 +300,10 @@ struct stmmac_ops {
 			       unsigned int reg_n);
 	void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
 			       unsigned int reg_n);
+	void (*set_eee_mode) (void __iomem *ioaddr);
+	void (*reset_eee_mode) (void __iomem *ioaddr);
+	void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
+	void (*set_eee_pls) (void __iomem *ioaddr, int link);
 };
 
 struct mac_link {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index cfcef0e..1764f85 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -36,6 +36,7 @@
 
 #define GMAC_INT_STATUS		0x00000038	/* interrupt status register */
 enum dwmac1000_irq_status {
+	lpiis_irq = 0x400,
 	time_stamp_irq = 0x0200,
 	mmc_rx_csum_offload_irq = 0x0080,
 	mmc_tx_irq = 0x0040,
@@ -60,6 +61,25 @@ enum power_event {
 	power_down = 0x00000001,
 };
 
+/* Energy Efficient Ethernet (EEE)
+ *
+ * LPI status, timer and control register offset
+ */
+#define LPI_CTRL_STATUS	0x0030
+#define LPI_TIMER_CTRL	0x0034
+
+/* LPI control and status defines */
+#define LPI_CTRL_STATUS_LPITXA	0x00080000	/* Enable LPI TX Automate */
+#define LPI_CTRL_STATUS_PLSEN	0x00040000	/* Enable PHY Link Status */
+#define LPI_CTRL_STATUS_PLS	0x00020000	/* PHY Link Status */
+#define LPI_CTRL_STATUS_LPIEN	0x00010000	/* LPI Enable */
+#define LPI_CTRL_STATUS_RLPIST	0x00000200	/* Receive LPI state */
+#define LPI_CTRL_STATUS_TLPIST	0x00000100	/* Transmit LPI state */
+#define LPI_CTRL_STATUS_RLPIEX	0x00000008	/* Receive LPI Exit */
+#define LPI_CTRL_STATUS_RLPIEN	0x00000004	/* Receive LPI Entry */
+#define LPI_CTRL_STATUS_TLPIEX	0x00000002	/* Transmit LPI Exit */
+#define LPI_CTRL_STATUS_TLPIEN	0x00000001	/* Transmit LPI Entry */
+
 /* GMAC HW ADDR regs */
 #define GMAC_ADDR_HIGH(reg)		(0x00000040+(reg * 8))
 #define GMAC_ADDR_LOW(reg)		(0x00000044+(reg * 8))
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b1c48b9..a4fab30 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -187,26 +187,107 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
 }
 
 
-static void dwmac1000_irq_status(void __iomem *ioaddr)
+static int dwmac1000_irq_status(void __iomem *ioaddr)
 {
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+	int status = 0;
 
 	/* Not used events (e.g. MMC interrupts) are not handled. */
-	if ((intr_status & mmc_tx_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
+	if ((intr_status & mmc_tx_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_TX_INTR));
-	if (unlikely(intr_status & mmc_rx_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
+		status |= core_mmc_tx_irq;
+	}
+	if (unlikely(intr_status & mmc_rx_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_INTR));
-	if (unlikely(intr_status & mmc_rx_csum_offload_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
+		status |= core_mmc_rx_irq;
+	}
+	if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
+		status |= core_mmc_rx_csum_offload_irq;
+	}
 	if (unlikely(intr_status & pmt_irq)) {
-		CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
+		CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
 		/* clear the PMT bits 5 and 6 by reading the PMT
 		 * status register. */
 		readl(ioaddr + GMAC_PMT);
+		status |= core_irq_receive_pmt_irq;
 	}
+	/* MAC trx/rx EEE LPI entry/exit interrupts */
+	if (intr_status & lpiis_irq) {
+		/* Clean LPI interrupt by reading the Reg 12 */
+		u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);
+
+		if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
+			CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
+			status |= core_irq_tx_path_in_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
+			CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
+			status |= core_irq_tx_path_exit_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
+			CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
+			status |= core_irq_rx_path_in_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
+			CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
+			status |= core_irq_rx_path_exit_lpi_mode;
+		}
+	}
+
+	return status;
+}
+
+static void  dwmac1000_set_eee_mode(void __iomem *ioaddr)
+{
+	u32 value;
+
+	/* Enable the link status receive on RGMII, SGMII ore SMII
+	 * receive path and instruct the transmit to enter in LPI
+	 * state. */
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+	value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+{
+	u32 value;
+
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+	value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+{
+	u32 value;
+
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+
+	if (link)
+		value |= LPI_CTRL_STATUS_PLS;
+	else
+		value &= ~LPI_CTRL_STATUS_PLS;
+
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+{
+	int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
+
+	/* Program the timers in the LPI timer control register:
+	 * LS: minimum time (ms) for which the link
+	 *  status from PHY should be ok before transmitting
+	 *  the LPI pattern.
+	 * TW: minimum time (us) for which the core waits
+	 *  after it has stopped transmitting the LPI pattern.
+	 */
+	writel(value, ioaddr + LPI_TIMER_CTRL);
 }
 
 static const struct stmmac_ops dwmac1000_ops = {
@@ -219,6 +300,10 @@ static const struct stmmac_ops dwmac1000_ops = {
 	.pmt = dwmac1000_pmt,
 	.set_umac_addr = dwmac1000_set_umac_addr,
 	.get_umac_addr = dwmac1000_get_umac_addr,
+	.set_eee_mode =  dwmac1000_set_eee_mode,
+	.reset_eee_mode =  dwmac1000_reset_eee_mode,
+	.set_eee_timer =  dwmac1000_set_eee_timer,
+	.set_eee_pls =  dwmac1000_set_eee_pls,
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 138fb8d..a11370b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,9 +72,9 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
 		readl(ioaddr + MAC_VLAN2));
 }
 
-static void dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(void __iomem *ioaddr)
 {
-	return;
+	return 0;
 }
 
 static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 437edac..27cbcd7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -69,6 +69,7 @@
 #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
 
 /* DMA Status register defines */
+#define DMA_STATUS_GLPII	0x40000000	/* GMAC LPI interrupt */
 #define DMA_STATUS_GPI		0x10000000	/* PMT interrupt */
 #define DMA_STATUS_GMI		0x08000000	/* MMC interrupt */
 #define DMA_STATUS_GLI		0x04000000	/* GMAC Line interface int */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b4b095f..266fcac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -81,6 +81,10 @@ struct stmmac_priv {
 	struct stmmac_counters mmc;
 	struct dma_features dma_cap;
 	int hw_cap_support;
+	struct timer_list eee_ctrl_timer;
+	bool tx_path_in_lpi_mode;
+	bool eee_enabled;
+	int lpi_irq;
 };
 
 extern int phyaddr;
@@ -99,3 +103,6 @@ int stmmac_dvr_remove(struct net_device *ndev);
 struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 				     struct plat_stmmacenet_data *plat_dat,
 				     void __iomem *addr);
+void stmmac_disable_eee_mode(struct stmmac_priv *priv);
+bool stmmac_eee_init(struct stmmac_priv *priv);
+
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index f98e151..90cce62 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -93,6 +93,16 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(poll_n),
 	STMMAC_STAT(sched_timer_n),
 	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(mmc_tx_irq_n),
+	STMMAC_STAT(mmc_rx_irq_n),
+	STMMAC_STAT(mmc_rx_csum_offload_irq_n),
+	STMMAC_STAT(irq_receive_pmt_irq_n),
+	STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
+	STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
+	STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
+	STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
+	STMMAC_STAT(phy_eee_wakeup_error_n),
 };
 #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
 
@@ -366,6 +376,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
 					     (*(u32 *)p);
 			}
 		}
+		if (priv->eee_enabled) {
+			int val = phy_get_eee_err(priv->phydev);
+			if (val)
+				priv->xstats.phy_eee_wakeup_error_n = val;
+		}
 	}
 	for (i = 0; i < STMMAC_STATS_LEN; i++) {
 		char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
@@ -464,6 +479,35 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	return 0;
 }
 
+static int ethtool_op_get_eee(struct net_device *dev, struct ethtool_value *eee)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if (!priv->dma_cap.eee)
+		return -EOPNOTSUPP;
+
+	eee->data = priv->eee_enabled;
+
+	return 0;
+}
+
+static int ethtool_op_set_eee(struct net_device *dev, struct ethtool_value *eee)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if ((!eee->data) && (priv->eee_enabled)) {
+		stmmac_disable_eee_mode(priv);
+		priv->eee_enabled = eee->data;
+	} else if ((eee->data) && (!priv->eee_enabled))
+		/* We are asking for enabling the EEE but this
+		 * has to be verified by invoking the eee_init function.
+		 * For this reason we cannot set eee_enabled to
+		 * eee->data, directly. */
+		priv->eee_enabled = stmmac_eee_init(priv);
+
+	return 0;
+}
+
 static const struct ethtool_ops stmmac_ethtool_ops = {
 	.begin = stmmac_check_if_running,
 	.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -481,6 +525,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
 	.get_wol = stmmac_get_wol,
 	.set_wol = stmmac_set_wol,
 	.get_sset_count	= stmmac_get_sset_count,
+	.get_eee = ethtool_op_get_eee,
+	.set_eee = ethtool_op_set_eee,
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e85ffbd..2f69c55 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -133,6 +133,11 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
 
+static int eee_timer = 1000;
+module_param(eee_timer, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
+#define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
+
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_STMMAC_DEBUG_FS
@@ -197,6 +202,82 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
 					  phydev->speed);
 }
 
+static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
+{
+	/* Check and enter in LPI mode */
+	if ((priv->dirty_tx == priv->cur_tx) &&
+	    (priv->tx_path_in_lpi_mode == false))
+		priv->hw->mac->set_eee_mode(priv->ioaddr);
+}
+
+void stmmac_disable_eee_mode(struct stmmac_priv *priv)
+{
+	/* Exit and disable EEE in case of we are are in LPI state. */
+	priv->hw->mac->reset_eee_mode(priv->ioaddr);
+	del_timer_sync(&priv->eee_ctrl_timer);
+	priv->tx_path_in_lpi_mode = false;
+}
+
+/**
+ * stmmac_eee_ctrl_timer
+ * @arg : data hook
+ * Description:
+ *  If there is no data transfer and if we are not in LPI state,
+ *  then MAC Transmitter can be moved to LPI state.
+ */
+static void stmmac_eee_ctrl_timer(unsigned long arg)
+{
+	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
+
+	stmmac_enable_eee_mode(priv);
+	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+}
+
+/**
+ * stmmac_eee_init
+ * @priv: private device pointer
+ * Description:
+ *  If the EEE support has been enabled while configuring the driver,
+ *  if the GMAC actually supports the EEE (from the HW cap reg) and the
+ *  phy can also manage EEE, so enable the LPI state and start the timer
+ *  to verify if the tx path can enter in LPI state.
+ */
+bool stmmac_eee_init(struct stmmac_priv *priv)
+{
+	bool ret = false;
+
+	/* MAC core supports the EEE feature. */
+	if (priv->dma_cap.eee) {
+
+		/* Check if the PHY supports EEE*/
+		if (phy_check_eee(priv->phydev))
+			goto out;
+
+		init_timer(&priv->eee_ctrl_timer);
+		priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
+		priv->eee_ctrl_timer.data = (unsigned long)priv;
+		priv->eee_ctrl_timer.expires = STMMAC_LPI_TIMER(eee_timer);
+		add_timer(&priv->eee_ctrl_timer);
+
+		priv->hw->mac->set_eee_timer(priv->ioaddr, 0x3e8, 0);
+
+		pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
+
+		ret = true;
+	}
+out:
+	return ret;
+}
+
+static void stmmac_eee_adjust(struct stmmac_priv *priv)
+{
+	/* When the EEE has been already initialised we have to
+	 * modify the PLS bit in the LPI ctrl & status reg according
+	 * to the PHY link status. For this reason. */
+	if (priv->eee_enabled)
+		priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
+}
+
 /**
  * stmmac_adjust_link
  * @dev: net device structure
@@ -217,6 +298,7 @@ static void stmmac_adjust_link(struct net_device *dev)
 	    phydev->addr, phydev->link);
 
 	spin_lock_irqsave(&priv->lock, flags);
+
 	if (phydev->link) {
 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
 
@@ -283,6 +365,8 @@ static void stmmac_adjust_link(struct net_device *dev)
 	if (new_state && netif_msg_link(priv))
 		phy_print_status(phydev);
 
+	stmmac_eee_adjust(priv);
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
@@ -300,7 +384,7 @@ static int stmmac_init_phy(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev;
-	char phy_id[MII_BUS_ID_SIZE + 3];
+	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
 	char bus_id[MII_BUS_ID_SIZE];
 	int interface = priv->plat->interface;
 	priv->oldlink = 0;
@@ -308,11 +392,13 @@ static int stmmac_init_phy(struct net_device *dev)
 	priv->oldduplex = -1;
 
 	snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", priv->plat->bus_id);
-	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
 		 priv->plat->phy_addr);
-	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
+	/* (mii bus id:phy device id)  */
+	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
 
-	phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface);
+	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 0,
+			     interface);
 
 	if (IS_ERR(phydev)) {
 		pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -651,6 +737,11 @@ static void stmmac_tx(struct stmmac_priv *priv)
 		}
 		netif_tx_unlock(priv->dev);
 	}
+
+	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
+		stmmac_enable_eee_mode(priv);
+		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+	}
 	spin_unlock(&priv->tx_lock);
 }
 
@@ -975,6 +1066,17 @@ static int stmmac_open(struct net_device *dev)
 		}
 	}
 
+	/* Request the IRQ lines */
+	if (priv->lpi_irq != -ENXIO) {
+		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
+				  dev->name, dev);
+		if (unlikely(ret < 0)) {
+			pr_err("%s: ERROR: allocating the LPI IRQ %d"
+			       " (error: %d)\n", __func__, priv->lpi_irq, ret);
+			goto open_error_lpiirq;
+		}
+	}
+
 	/* Enable the MAC Rx/Tx */
 	stmmac_set_mac(priv->ioaddr, true);
 
@@ -1010,12 +1112,18 @@ static int stmmac_open(struct net_device *dev)
 	if (priv->phydev)
 		phy_start(priv->phydev);
 
+	priv->eee_enabled = stmmac_eee_init(priv);
+
 	napi_enable(&priv->napi);
 	skb_queue_head_init(&priv->rx_recycle);
 	netif_start_queue(dev);
 
 	return 0;
 
+open_error_lpiirq:
+	if (priv->wol_irq != dev->irq)
+		free_irq(priv->wol_irq, dev);
+
 open_error_wolirq:
 	free_irq(dev->irq, dev);
 
@@ -1039,6 +1147,9 @@ static int stmmac_release(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
+	if (priv->eee_enabled)
+		del_timer_sync(&priv->eee_ctrl_timer);
+
 	/* Stop and disconnect the PHY */
 	if (priv->phydev) {
 		phy_stop(priv->phydev);
@@ -1061,6 +1172,8 @@ static int stmmac_release(struct net_device *dev)
 	free_irq(dev->irq, dev);
 	if (priv->wol_irq != dev->irq)
 		free_irq(priv->wol_irq, dev);
+	if (priv->lpi_irq != -ENXIO)
+		free_irq(priv->lpi_irq, dev);
 
 	/* Stop TX/RX DMA and clear the descriptors */
 	priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1110,6 +1223,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	spin_lock(&priv->tx_lock);
 
+	if (priv->tx_path_in_lpi_mode)
+		stmmac_disable_eee_mode(priv);
+
 	entry = priv->cur_tx % txsize;
 
 #ifdef STMMAC_XMIT_DEBUG
@@ -1484,10 +1600,37 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
 		return IRQ_NONE;
 	}
 
-	if (priv->plat->has_gmac)
-		/* To handle GMAC own interrupts */
-		priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
+	/* To handle GMAC own interrupts */
+	if (priv->plat->has_gmac) {
+		int status = priv->hw->mac->host_irq_status((void __iomem *)
+							    dev->base_addr);
+		if (unlikely(status)) {
+			if (status & core_mmc_tx_irq)
+				priv->xstats.mmc_tx_irq_n++;
+			if (status & core_mmc_rx_irq)
+				priv->xstats.mmc_rx_irq_n++;
+			if (status & core_mmc_rx_csum_offload_irq)
+				priv->xstats.mmc_rx_csum_offload_irq_n++;
+			if (status & core_irq_receive_pmt_irq)
+				priv->xstats.irq_receive_pmt_irq_n++;
+
+			/* For LPI we need to save the tx status */
+			if (status & core_irq_tx_path_in_lpi_mode) {
+				priv->xstats.irq_tx_path_in_lpi_mode_n++;
+				priv->tx_path_in_lpi_mode = true;
+			}
+			if (status & core_irq_tx_path_exit_lpi_mode) {
+				priv->xstats.irq_tx_path_exit_lpi_mode_n++;
+				priv->tx_path_in_lpi_mode = false;
+			}
+			if (status & core_irq_rx_path_in_lpi_mode)
+				priv->xstats.irq_rx_path_in_lpi_mode_n++;
+			if (status & core_irq_rx_path_exit_lpi_mode)
+				priv->xstats.irq_rx_path_exit_lpi_mode_n++;
+		}
+	}
 
+	/* To handle DMA interrupts */
 	stmmac_dma_interrupt(priv);
 
 	return IRQ_HANDLED;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 3aad981..bc0e83f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -94,6 +94,8 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
 	if (priv->wol_irq == -ENXIO)
 		priv->wol_irq = priv->dev->irq;
 
+	priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
+
 	platform_set_drvdata(pdev, priv->dev);
 
 	pr_debug("STMMAC platform driver registration completed");
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-03-06  8:28       ` [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
@ 2012-03-06 16:55         ` Ben Hutchings
  2012-03-06 17:05           ` Ben Hutchings
  0 siblings, 1 reply; 23+ messages in thread
From: Ben Hutchings @ 2012-03-06 16:55 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev, davem, rayagond

On Tue, 2012-03-06 at 09:28 +0100, Giuseppe CAVALLARO wrote:
> This patch adds the initial support for the Energy-Efficient
> Ethernet (EEE). It has been tested on IC+101G device on ST STB.
> 
> To support the EEE we have to access to the MMD registers 3.20 and
> 3.60/61. So I added two new functions to read/write the MMD
> registers (clause 45)
> 
> The upper-layer will invoke the phy_check_eee to properly check
> if the EEE is supported by the PHYs.
> 
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> ---
>  drivers/net/phy/phy_device.c |  136 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mdio.h         |    5 ++
>  include/linux/mii.h          |   11 ++++
>  include/linux/phy.h          |    3 +
>  4 files changed, 155 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index f320f46..c269492e 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
[...]
> @@ -898,6 +899,141 @@ int genphy_resume(struct phy_device *phydev)
>  }
>  EXPORT_SYMBOL(genphy_resume);
>  
> +static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
> +				int addr)
[...]
> +/**
> + * read_phy_mmd - reads data from the MMC register (clause 22 to access to
> + * clause 45)
[...]
> +/**
> + * write_phy_mmd - writes data to the MMC register (clause 22 to access to
> + * clause 45)

These names need to be changed as phylib also supports (or is intended
to support) real clause 45 PHYs.

[...]
> diff --git a/include/linux/mdio.h b/include/linux/mdio.h
> index dfb9479..a2dfe86 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_EEE_CAP		20	/* EEE Capability register */
> +#define MDIO_EEE_WK_ERR		22	/* EEE wake error counter */
>  #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
> +#define MDIO_EEE_ADV		60	/* EEE advertisement */
> +#define MDIO_EEE_PART_LINK	61	/* EEE link partner ability */
>  
>  /* Media-dependent registers. */
>  #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */

The convention I tried to set here was that register numbers defined for
only one MMD are named beginning with MDIO_<mmd>_.  I also used 'LP' for
link partner and 'ABLE' for capability/ability.

So for consistency I think those should be named MDIO_PCS_EEE_ABLE,
MDIO_PCS_EEE_WK_ERR, MDIO_AN_EEE_ADV, MDIO_AN_EEE_LPABLE.

> @@ -82,6 +86,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_CLK_STOP_ENABLE	0x400	/* Stop the clock during LPI */

Register field mask names should begin with the register number name, so
that it's easier to see whether you're using them correctly.  So this
should be something like MDIO_PCS_CTRL1_CLK_STOP_ENABLE or (slightly
shorter) MDIO_PCS_CTRL1_CLKSTOP_EN.
 
>  /* 10 Gb/s */
>  #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
> diff --git a/include/linux/mii.h b/include/linux/mii.h
> index 2783eca..18457add 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_CRTL		0x0d	/* MMD Access Control Register */

Typo: CRTL should be CTRL.

> +#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,15 @@
>  #define FLOW_CTRL_TX		0x01
>  #define FLOW_CTRL_RX		0x02
>  
> +/* MMD Access Control register fields */
> +#define MII_MMD_CRTL_DEVAD_MASK			0x1f	/* Mask MMD DEVAD*/
> +#define MII_MMD_CRTL_FUNC_ADDR			0x0000	/* Address */
[...]

Again here.

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	[flat|nested] 23+ messages in thread

* Re: [net-next 2/4] net: ethtool: add the EEE support
  2012-03-06  8:28       ` [net-next 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
@ 2012-03-06 16:56         ` Ben Hutchings
  2012-03-08 15:14           ` Giuseppe CAVALLARO
  0 siblings, 1 reply; 23+ messages in thread
From: Ben Hutchings @ 2012-03-06 16:56 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev, davem, rayagond

On Tue, 2012-03-06 at 09:28 +0100, Giuseppe CAVALLARO wrote:
> This patch adds two new functions to detect if Energy-Efficient
> Ethernet (EEE) is supported and the way to enable/disable it.
[...]

You haven't fixed any of the problems in the previous version of this
patch.

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	[flat|nested] 23+ messages in thread

* Re: [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-03-06 16:55         ` Ben Hutchings
@ 2012-03-06 17:05           ` Ben Hutchings
  2012-03-08 14:54             ` Giuseppe CAVALLARO
  0 siblings, 1 reply; 23+ messages in thread
From: Ben Hutchings @ 2012-03-06 17:05 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev, davem, rayagond

On Tue, 2012-03-06 at 16:55 +0000, Ben Hutchings wrote:
> On Tue, 2012-03-06 at 09:28 +0100, Giuseppe CAVALLARO wrote:
> > This patch adds the initial support for the Energy-Efficient
> > Ethernet (EEE). It has been tested on IC+101G device on ST STB.
> > 
> > To support the EEE we have to access to the MMD registers 3.20 and
> > 3.60/61. So I added two new functions to read/write the MMD
> > registers (clause 45)
> > 
> > The upper-layer will invoke the phy_check_eee to properly check
> > if the EEE is supported by the PHYs.
> > 
> > Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> > ---
> >  drivers/net/phy/phy_device.c |  136 ++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/mdio.h         |    5 ++
> >  include/linux/mii.h          |   11 ++++
> >  include/linux/phy.h          |    3 +
> >  4 files changed, 155 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> > index f320f46..c269492e 100644
> > --- a/drivers/net/phy/phy_device.c
> > +++ b/drivers/net/phy/phy_device.c
> [...]
> > @@ -898,6 +899,141 @@ int genphy_resume(struct phy_device *phydev)
> >  }
> >  EXPORT_SYMBOL(genphy_resume);
> >  
> > +static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
> > +				int addr)
> [...]
> > +/**
> > + * read_phy_mmd - reads data from the MMC register (clause 22 to access to
> > + * clause 45)
> [...]
> > +/**
> > + * write_phy_mmd - writes data to the MMC register (clause 22 to access to
> > + * clause 45)
> 
> These names need to be changed as phylib also supports (or is intended
> to support) real clause 45 PHYs.
> 
> [...]
> > diff --git a/include/linux/mdio.h b/include/linux/mdio.h
> > index dfb9479..a2dfe86 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_EEE_CAP		20	/* EEE Capability register */
> > +#define MDIO_EEE_WK_ERR		22	/* EEE wake error counter */
> >  #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
> > +#define MDIO_EEE_ADV		60	/* EEE advertisement */
> > +#define MDIO_EEE_PART_LINK	61	/* EEE link partner ability */
> >  
> >  /* Media-dependent registers. */
> >  #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
> 
> The convention I tried to set here was that register numbers defined for
> only one MMD are named beginning with MDIO_<mmd>_.  I also used 'LP' for
> link partner and 'ABLE' for capability/ability.
> 
> So for consistency I think those should be named MDIO_PCS_EEE_ABLE,
> MDIO_PCS_EEE_WK_ERR, MDIO_AN_EEE_ADV, MDIO_AN_EEE_LPABLE.
[...]

And note we already have MDIO_AN_EEE_ADV under 'Media-dependent
registers'.  I think that may be the wrong section so feel free to move
it up to 'Generic MDIO registers', but don't make two definitions.

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	[flat|nested] 23+ messages in thread

* Re: [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-03-06 17:05           ` Ben Hutchings
@ 2012-03-08 14:54             ` Giuseppe CAVALLARO
  2012-03-08 18:29               ` Ben Hutchings
  0 siblings, 1 reply; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-08 14:54 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, davem, rayagond

Hello Ben

thanks for your review and sorry for my delay.

On 3/6/2012 6:05 PM, Ben Hutchings wrote:
> On Tue, 2012-03-06 at 16:55 +0000, Ben Hutchings wrote:
>> On Tue, 2012-03-06 at 09:28 +0100, Giuseppe CAVALLARO wrote:
>>> This patch adds the initial support for the Energy-Efficient
>>> Ethernet (EEE). It has been tested on IC+101G device on ST STB.
>>>
>>> To support the EEE we have to access to the MMD registers 3.20 and
>>> 3.60/61. So I added two new functions to read/write the MMD
>>> registers (clause 45)
>>>
>>> The upper-layer will invoke the phy_check_eee to properly check
>>> if the EEE is supported by the PHYs.
>>>
>>> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>>> ---
>>>  drivers/net/phy/phy_device.c |  136 ++++++++++++++++++++++++++++++++++++++++++
>>>  include/linux/mdio.h         |    5 ++
>>>  include/linux/mii.h          |   11 ++++
>>>  include/linux/phy.h          |    3 +
>>>  4 files changed, 155 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
>>> index f320f46..c269492e 100644
>>> --- a/drivers/net/phy/phy_device.c
>>> +++ b/drivers/net/phy/phy_device.c
>> [...]
>>> @@ -898,6 +899,141 @@ int genphy_resume(struct phy_device *phydev)
>>>  }
>>>  EXPORT_SYMBOL(genphy_resume);
>>>  
>>> +static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
>>> +				int addr)
>> [...]
>>> +/**
>>> + * read_phy_mmd - reads data from the MMC register (clause 22 to access to
>>> + * clause 45)
>> [...]
>>> +/**
>>> + * write_phy_mmd - writes data to the MMC register (clause 22 to access to
>>> + * clause 45)
>>
>> These names need to be changed as phylib also supports (or is intended
>> to support) real clause 45 PHYs.


What do you suggest? Do I have to rename these functions for example as?

write_phy_mmd  ---->    phy_write_mmd_cl45
read_phy_mmd   ---->    phy_read_mmd_cl45

I've also another doubt. I put this code in phy_device.c. Is it correct?

Maybe, it could be better have it in phy.c? What do you think?

>> [...]
>>> diff --git a/include/linux/mdio.h b/include/linux/mdio.h
>>> index dfb9479..a2dfe86 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_EEE_CAP		20	/* EEE Capability register */
>>> +#define MDIO_EEE_WK_ERR		22	/* EEE wake error counter */
>>>  #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
>>> +#define MDIO_EEE_ADV		60	/* EEE advertisement */
>>> +#define MDIO_EEE_PART_LINK	61	/* EEE link partner ability */
>>>  
>>>  /* Media-dependent registers. */
>>>  #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
>>
>> The convention I tried to set here was that register numbers defined for
>> only one MMD are named beginning with MDIO_<mmd>_.  I also used 'LP' for
>> link partner and 'ABLE' for capability/ability.
>>
>> So for consistency I think those should be named MDIO_PCS_EEE_ABLE,
>> MDIO_PCS_EEE_WK_ERR, MDIO_AN_EEE_ADV, MDIO_AN_EEE_LPABLE.
> [...]

Perfect, I'll adopt this name convention.

> 
> And note we already have MDIO_AN_EEE_ADV under 'Media-dependent
> registers'.  I think that may be the wrong section so feel free to move
> it up to 'Generic MDIO registers', but don't make two definitions.

This is my fault and I'll fix it at once, sorry!

Peppe

> 
> Ben.
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next 2/4] net: ethtool: add the EEE support
  2012-03-06 16:56         ` Ben Hutchings
@ 2012-03-08 15:14           ` Giuseppe CAVALLARO
  0 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-08 15:14 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, davem, rayagond

Hello Ben

On 3/6/2012 5:56 PM, Ben Hutchings wrote:
> On Tue, 2012-03-06 at 09:28 +0100, Giuseppe CAVALLARO wrote:
>> This patch adds two new functions to detect if Energy-Efficient
>> Ethernet (EEE) is supported and the way to enable/disable it.
> [...]
> 
> You haven't fixed any of the problems in the previous version of this
> patch.

Yes you are right,  sorry :-(

Below there is what you suggested and inline my comments.

Welcome advice!

On 2/29/2012 6:00 PM, Ben Hutchings wrote:

> It is certainly necessary to distinguish:
> a. PHY is advertising EEE
> from
> b. Link partner is advertising EEE
> or
> c. EEE will be used (= a && b)

you are perfectly right and indeed I wanted to do that.

> I haven't had anything to do with PHY drivers for a while but it looks
> like you should be able to map MDIO register 3.20 to supported flags,
> 7.60 to advertising and 7.61 to lp_advertising.

I have added a function named:

    phy_check_eee

For example, the stmmac driver (only if its HW core supports the EEE
feature) calls the phy_check_eee to understand if the the points a) and
b) above are satisfied.

On the Ethtool side, within the driver the .get_eee will pass to the
user-space if the EEE is used (just point c).
The .set_eee should used to force the MAC to disable/enable the EEE (if
actually supported by MAC+PHY).
I had added this option because the Synopsys GMAC manages the TX LPI
path through a SW timer :-( that in this case can be disabled via ethtool.
Indeed, no action should be taken by the user for the PHY side.
The only thing that could be changed is the clock stop enable bit (3.0.10).

What do you think?

Peppe

>
> Even if your particular device doesn't support these MDIO registers,
> other devices will.  So I think you should define the flags and then if
> you don't have that fine control you should check in your set_settings
> implementation that the advertising value either has all the EEE mode
> flags clear or has all the modes the hardware supports set.
>
> Ben.
>




> Ben.
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-03-08 14:54             ` Giuseppe CAVALLARO
@ 2012-03-08 18:29               ` Ben Hutchings
  2012-03-09 14:39                 ` Giuseppe CAVALLARO
  0 siblings, 1 reply; 23+ messages in thread
From: Ben Hutchings @ 2012-03-08 18:29 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev, davem, rayagond

On Thu, 2012-03-08 at 15:54 +0100, Giuseppe CAVALLARO wrote:
> Hello Ben
> 
> thanks for your review and sorry for my delay.
> 
> On 3/6/2012 6:05 PM, Ben Hutchings wrote:
[...]
> >>> +static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
> >>> +				int addr)
> >> [...]
> >>> +/**
> >>> + * read_phy_mmd - reads data from the MMC register (clause 22 to access to
> >>> + * clause 45)
> >> [...]
> >>> +/**
> >>> + * write_phy_mmd - writes data to the MMC register (clause 22 to access to
> >>> + * clause 45)
> >>
> >> These names need to be changed as phylib also supports (or is intended
> >> to support) real clause 45 PHYs.
> 
> 
> What do you suggest? Do I have to rename these functions for example as?
> 
> write_phy_mmd  ---->    phy_write_mmd_cl45
> read_phy_mmd   ---->    phy_read_mmd_cl45

These are a means to access MMDs through the clause 22 MDIO protocol, so
it seems to me that the name should include '22' and not '45'.  But
perhaps it would be more obvious to use the word 'indirect'.

> I've also another doubt. I put this code in phy_device.c. Is it correct?
> 
> Maybe, it could be better have it in phy.c? What do you think?
[...]

No idea, I don't have any involvement in phylib.

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	[flat|nested] 23+ messages in thread

* Re: [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs
  2012-03-08 18:29               ` Ben Hutchings
@ 2012-03-09 14:39                 ` Giuseppe CAVALLARO
  0 siblings, 0 replies; 23+ messages in thread
From: Giuseppe CAVALLARO @ 2012-03-09 14:39 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, davem, rayagond

On 3/8/2012 7:29 PM, Ben Hutchings wrote:
> On Thu, 2012-03-08 at 15:54 +0100, Giuseppe CAVALLARO wrote:
>> Hello Ben
>>
>> thanks for your review and sorry for my delay.
>>
>> On 3/6/2012 6:05 PM, Ben Hutchings wrote:
> [...]
>>>>> +static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
>>>>> +				int addr)
>>>> [...]
>>>>> +/**
>>>>> + * read_phy_mmd - reads data from the MMC register (clause 22 to access to
>>>>> + * clause 45)
>>>> [...]
>>>>> +/**
>>>>> + * write_phy_mmd - writes data to the MMC register (clause 22 to access to
>>>>> + * clause 45)
>>>>
>>>> These names need to be changed as phylib also supports (or is intended
>>>> to support) real clause 45 PHYs.
>>
>>
>> What do you suggest? Do I have to rename these functions for example as?
>>
>> write_phy_mmd  ---->    phy_write_mmd_cl45
>> read_phy_mmd   ---->    phy_read_mmd_cl45
> 
> These are a means to access MMDs through the clause 22 MDIO protocol, so

yes indeed :-)

> it seems to me that the name should include '22' and not '45'.  But
> perhaps it would be more obvious to use the word 'indirect'.

ok for phy_write/read_mmd_indirect

> 
>> I've also another doubt. I put this code in phy_device.c. Is it correct?
>>
>> Maybe, it could be better have it in phy.c? What do you think?
> [...]
> 
> No idea, I don't have any involvement in phylib.

ok. I'll keep the code in phy_device unless to have further feedback
from other developers.

peppe

> 
> Ben.
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2012-03-09 14:40 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-28 12:44 [PATCH 0/4 (net.git)] stmmac EEE support Giuseppe CAVALLARO
2012-02-28 12:44 ` [PATCH 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
2012-02-28 12:44 ` [PATCH 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
2012-02-28 15:45   ` Ben Hutchings
2012-02-29 16:12     ` Giuseppe CAVALLARO
2012-02-29 17:00       ` Ben Hutchings
2012-02-28 12:44 ` [PATCH 3/4] stmmac: update the driver Documentation and add EEE Giuseppe CAVALLARO
2012-02-28 12:44 ` [PATCH 4/4] stmmac: add the Energy Efficient Ethernet support Giuseppe CAVALLARO
2012-02-28 12:46 ` [PATCH] ethtool: add the EEE option Giuseppe CAVALLARO
2012-02-28 20:18 ` [PATCH 0/4 (net.git)] stmmac EEE support David Miller
2012-02-29 16:07   ` Giuseppe CAVALLARO
2012-03-06  8:28     ` [net-next 0/4] stmmac: add the " Giuseppe CAVALLARO
2012-03-06  8:28       ` [net-next 1/4] phy: add the EEE support and the way to access to the MMD regs Giuseppe CAVALLARO
2012-03-06 16:55         ` Ben Hutchings
2012-03-06 17:05           ` Ben Hutchings
2012-03-08 14:54             ` Giuseppe CAVALLARO
2012-03-08 18:29               ` Ben Hutchings
2012-03-09 14:39                 ` Giuseppe CAVALLARO
2012-03-06  8:28       ` [net-next 2/4] net: ethtool: add the EEE support Giuseppe CAVALLARO
2012-03-06 16:56         ` Ben Hutchings
2012-03-08 15:14           ` Giuseppe CAVALLARO
2012-03-06  8:28       ` [net-next 3/4] stmmac: update the driver Documentation and add EEE Giuseppe CAVALLARO
2012-03-06  8:28       ` [net-next 4/4] stmmac: add the Energy Efficient Ethernet support Giuseppe CAVALLARO

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).