* [net-next.git 0/4] EEE for PAL and stmmac (V5)
From: Giuseppe CAVALLARO @ 2012-06-20 6:12 UTC (permalink / raw)
To: netdev
Cc: eric.dumazet, bhutchings, rayagond, davem, yuvalmin,
Giuseppe Cavallaro
These patches add the EEE support in the stmmac device driver
restoring an old work I had done some months ago and not
completed in time.
I've tested all on ST STB with the IC+ 101G PHY device that has
this feature.
The initial EEE support for the stmmac has been written by Rayagond
but I have reworked all his code adding new parts and especially
performing tests on a real hardware. Thx Rayagond!
In these patches, we can see that the stmmac supports the EEE
only if the DMA HW capability register says that this
feature is actually available. In that case, the driver can enter
in the Tx LPI mode by using a timer as recommended by Synopsys.
Note that EEE is supported in new chip generations; in particular
I used the 3.61a.
At any rate, further information about how the driver treats the EEE
can be found in the stmmac.txt file (there is a patch for that).
Another patch is for Physical Abstraction Layer now able to
manage the MMD registers (clause 45); it also provides the ethtool
support to manage supported/advertisement/lp adv features.
v3: fixed the "stmmac: do not use strict_strtoul but kstrtoint"
to use the kstrtoint.
v4: fixed the function to enable the EEE and add a check that verifies
if the link auto-negotiated matches with the bits in the adv and lp
registers.
v5: reviewed the way to get the negotiated settings
Giuseppe Cavallaro (4):
stmmac: do not use strict_strtoul but kstrtoint
stmmac: update the driver Documentation and add EEE
stmmac: add the Energy Efficient Ethernet support
phy: add the EEE support and the way to access to the MMD registers.
Documentation/networking/stmmac.txt | 36 ++-
drivers/net/ethernet/stmicro/stmmac/common.h | 31 ++-
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 20 ++
.../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 101 +++++++-
.../net/ethernet/stmicro/stmmac/dwmac100_core.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 8 +
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 57 ++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 193 ++++++++++++--
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +
drivers/net/phy/phy.c | 281 ++++++++++++++++++++
include/linux/mdio.h | 21 ++-
include/linux/mii.h | 9 +
include/linux/phy.h | 5 +
14 files changed, 724 insertions(+), 45 deletions(-)
--
1.7.4.4
^ permalink raw reply
* [net-next.git 3/4 (v5)] stmmac: add the Energy Efficient Ethernet support
From: Giuseppe CAVALLARO @ 2012-06-20 6:12 UTC (permalink / raw)
To: netdev
Cc: eric.dumazet, bhutchings, rayagond, davem, yuvalmin,
Giuseppe Cavallaro
In-Reply-To: <1340172774-27443-1-git-send-email-peppe.cavallaro@st.com>
This patch adds the Energy Efficient Ethernet support to the stmmac.
Please see the driver's documentation for further details about this support
in the driver.
Thanks also goes to Rayagond Kokatanur for his first implementation.
Note:
to clearly manage and expose the lpi interrupt status and eee ethtool
stats I've had to do some modifications to the driver's design and I
found really useful to move other parts of the code (e.g. mmc irq stat)
in the main directly. So this means that some core has been reworked
to introduce the EEE.
v1: initial patch
v2: fixed some sparse issues (typos)
v3: erroneously sent the v2 renamed as v3
v4:
o Fixed the return value of the stmmac_eee_init as suggested by D.Miller
o Totally reviewed the ethtool support for EEE
o Added a new internal parameter to tune the SW timer for TX LPI.
v5: do not change any eee setting in case of the stmmac_ethtool_op_set_eee fails
(it has to return -EOPNOTSUPP in that case).
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 31 ++++-
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 20 +++
.../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 101 +++++++++++-
.../net/ethernet/stmicro/stmmac/dwmac100_core.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 8 +
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 57 +++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 166 +++++++++++++++++++-
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +
9 files changed, 372 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index bcd54d6..e2d0832 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;
};
/* CSR Frequency Access Defines*/
@@ -162,6 +172,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;
@@ -208,6 +229,10 @@ struct dma_features {
#define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */
#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */
+/* Default LPI timers */
+#define STMMAC_DEFAULT_LIT_LS_TIMER 0x3E8
+#define STMMAC_DEFAULT_TWT_LS_TIMER 0x0
+
struct stmmac_desc_ops {
/* DMA RX descriptor ring initialization */
void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
@@ -278,7 +303,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, int id);
/* Flow control setting */
@@ -291,6 +316,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 23478bf..f90fcb5 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) (((reg > 15) ? 0x00000800 : 0x00000040) + \
(reg * 8))
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b5e4d02..bfe0226 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -194,26 +194,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 = {
@@ -226,6 +307,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 19e0f4e..f83210e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,9 +72,9 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
return 0;
}
-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 6e0360f..e678ce3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -70,6 +70,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 dc20c56..ab4c376 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -87,6 +87,12 @@ struct stmmac_priv {
#endif
int clk_csr;
int synopsys_id;
+ struct timer_list eee_ctrl_timer;
+ bool tx_path_in_lpi_mode;
+ int lpi_irq;
+ int eee_enabled;
+ int eee_active;
+ int tx_lpi_timer;
};
extern int phyaddr;
@@ -104,6 +110,8 @@ 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);
#ifdef CONFIG_HAVE_CLK
static inline int stmmac_clk_enable(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 ce43184..76fd61a 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,46 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
return 0;
}
+static int stmmac_ethtool_op_get_eee(struct net_device *dev,
+ struct ethtool_eee *edata)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ if (!priv->dma_cap.eee)
+ return -EOPNOTSUPP;
+
+ edata->eee_enabled = priv->eee_enabled;
+ edata->eee_active = priv->eee_active;
+ edata->tx_lpi_timer = priv->tx_lpi_timer;
+
+ return phy_ethtool_get_eee(priv->phydev, edata);
+}
+
+static int stmmac_ethtool_op_set_eee(struct net_device *dev,
+ struct ethtool_eee *edata)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ priv->eee_enabled = edata->eee_enabled;
+
+ if (!priv->eee_enabled)
+ stmmac_disable_eee_mode(priv);
+ else {
+ /* We are asking for enabling the EEE but it is safe
+ * to verify all by invoking the eee_init function.
+ * In case of failure it will return an error.
+ */
+ priv->eee_enabled = stmmac_eee_init(priv);
+ if (!priv->eee_enabled)
+ return -EOPNOTSUPP;
+
+ /* Do not change tx_lpi_timer in case of failure */
+ priv->tx_lpi_timer = edata->tx_lpi_timer;
+ }
+
+ return phy_ethtool_set_eee(priv->phydev, edata);
+}
+
static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -480,6 +535,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.get_strings = stmmac_get_strings,
.get_wol = stmmac_get_wol,
.set_wol = stmmac_set_wol,
+ .get_eee = stmmac_ethtool_op_get_eee,
+ .set_eee = stmmac_ethtool_op_set_eee,
.get_sset_count = stmmac_get_sset_count,
.get_ts_info = ethtool_op_get_ts_info,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index eba49cb..ea3bc09 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -133,6 +133,12 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_IFUP |
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
+#define STMMAC_DEFAULT_LPI_TIMER 1000
+static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
+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
@@ -161,6 +167,8 @@ static void stmmac_verify_args(void)
flow_ctrl = FLOW_OFF;
if (unlikely((pause < 0) || (pause > 0xffff)))
pause = PAUSE_TIME;
+ if (eee_timer < 0)
+ eee_timer = STMMAC_DEFAULT_LPI_TIMER;
}
static void stmmac_clk_csr_set(struct stmmac_priv *priv)
@@ -229,6 +237,85 @@ 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_init_eee(priv->phydev, 1))
+ goto out;
+
+ priv->eee_active = 1;
+ 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,
+ STMMAC_DEFAULT_LIT_LS_TIMER,
+ priv->tx_lpi_timer);
+
+ 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
@@ -249,6 +336,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);
@@ -315,6 +403,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");
@@ -332,7 +422,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;
@@ -346,11 +436,12 @@ static int stmmac_init_phy(struct net_device *dev)
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);
+ 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);
@@ -689,6 +780,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);
}
@@ -1027,6 +1123,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 (%d)\n",
+ __func__, priv->lpi_irq, ret);
+ goto open_error_lpiirq;
+ }
+ }
+
/* Enable the MAC Rx/Tx */
stmmac_set_mac(priv->ioaddr, true);
@@ -1062,12 +1169,19 @@ static int stmmac_open(struct net_device *dev)
if (priv->phydev)
phy_start(priv->phydev);
+ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
+ 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);
@@ -1093,6 +1207,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);
@@ -1115,6 +1232,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);
@@ -1164,6 +1283,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
@@ -1540,10 +1662,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;
@@ -2155,6 +2304,9 @@ static int __init stmmac_cmdline_opt(char *str)
} else if (!strncmp(opt, "pause:", 6)) {
if (kstrtoint(opt + 6, 0, &pause))
goto err;
+ } else if (!strncmp(opt, "eee_timer:", 6)) {
+ if (kstrtoint(opt + 10, 0, &eee_timer))
+ goto err;
#ifdef CONFIG_STMMAC_TIMER
} else if (!strncmp(opt, "tmrate:", 7)) {
if (kstrtoint(opt + 7, 0, &tmrate))
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 20eb502..7d36163 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -156,6 +156,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
* Re: [PATCH v2] ipv4: Early TCP socket demux.
From: David Miller @ 2012-06-20 6:14 UTC (permalink / raw)
To: eric.dumazet; +Cc: shemminger, netdev
In-Reply-To: <1340171489.4604.796.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 20 Jun 2012 07:51:29 +0200
> On Wed, 2012-06-20 at 07:49 +0200, Eric Dumazet wrote:
>
>> 2) small lived tcp sessions
>>
>> input dst is now dirtied because of the additional
>> dst_clone()/dst_release()
>
> Not realy a concern because we dirty cache line anyway
>
> dst_use_noref()
> {
> dst->__use++;
> dst->lastuse = time;
> }
Right, the costs probably even out for short TCP flows.
But better to do real tests than to believe what any of
us say. :-)
^ permalink raw reply
* Re: [PATCH v2] ipv4: Early TCP socket demux.
From: David Miller @ 2012-06-20 6:14 UTC (permalink / raw)
To: eric.dumazet; +Cc: shemminger, netdev
In-Reply-To: <1340171940.4604.799.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 20 Jun 2012 07:59:00 +0200
> On Tue, 2012-06-19 at 21:46 -0700, David Miller wrote:
>
>> These numbers can be decreased further, because since we're already
>> looking at the TCP header we can pre-cook the TCP control block in the
>> SKB and skip much of the stuff that tcp_v4_rcv() does since we've done
>> it already in the early demux code.
>
> It could be done at GRO level and remove one another demux.
>
> As routers probably have no use of GRO, no need of additional knob.
That's a great idea.
^ permalink raw reply
* Re: [patch net-next 00/19] team: couple of patches
From: Jesper Dangaard Brouer @ 2012-06-20 6:40 UTC (permalink / raw)
To: David Miller; +Cc: jpirko, netdev, eric.dumazet
In-Reply-To: <20120619.150124.1674713634175419404.davem@davemloft.net>
On Tue, 2012-06-19 at 15:01 -0700, David Miller wrote:
> From: Jiri Pirko <jpirko@redhat.com>
> Date: Tue, 19 Jun 2012 17:54:02 +0200
>
> > The main impact is this patchset provides an implementation of userspace driven
> > TX loadbalancing for team driver.
> >
> > Also couple of typos are fixed, minor issues fixes.
>
> Looks good, pushed, thanks Jiri.
Just for the record, I have also reviewed the patch series (before
submission), and ACK the series.
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: 10GBE performance drop with net.ipv4.tcp_timestamps=0
From: Stefan Priebe - Profihost AG @ 2012-06-20 7:00 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Linux Netdev List
In-Reply-To: <1340141493.4604.773.camel@edumazet-glaptop>
Am 19.06.2012 23:31, schrieb Eric Dumazet:
> On Tue, 2012-06-19 at 23:08 +0200, Stefan Priebe wrote:
>> i'm testing 10GBE speed with tweo servers. One with 3.5-rc3 nd thoe
>> other one whith RHEL 6 (2.6.32 kernel).
>>
>> I noticed that setting
>> net.ipv4.tcp_timestamps=0
>>
>> descreased the performance from 9,7 Full Duplex to 3-4Gb/s.
>>
>> Is this bahviour fine? What should / could i tet?
>>
>
> Really, you should provide more input than that, if you really want us
> to help.
*arg* forgot to add the pastebin links. Sorry. Speed degraded in this
case from 9,88Gbit/s to 2,45Gbit/s. When i turn on timestamps it's
perfect again. Server A has 3.5.0-rc3 and server B has an RHEL6 2.6.32
kernel.
Before:
http://pastebin.com/raw.php?i=1gVraWVc
After:
http://pastebin.com/raw.php?i=NSh8Y29s
Thanks,
Stefan
^ permalink raw reply
* Re: [PATCH v3] ipv4: Early TCP socket demux.
From: Julian Anastasov @ 2012-06-20 7:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120619.214957.1282277480138040899.davem@davemloft.net>
Hello,
On Tue, 19 Jun 2012, David Miller wrote:
> + if (sk->sk_state != TCP_TIME_WAIT) {
> + struct dst_entry *dst = sk->sk_rx_dst;
> + if (dst)
> + dst = dst_check(dst, 0);
What about checking rp_filter here or before dst_check:
rcu_read_lock();
in_dev = __in_dev_get_rcu(dst->dev);
if (skb->dev != dst->dev &&
(!in_dev || IN_DEV_RPFILTER(in_dev)))
dst = NULL;
rcu_read_unlock();
But may be it is a bad idea to return cached dst
that is with different dev. May be it is better a simple
check instead:
if (skb->dev != dst->dev)
dst = NULL;
It will work for the common case of traffic using
same dev.
> + if (dst) {
> + skb_dst_set_noref(skb, dst);
> + err = 0;
> + }
Also, is it a good idea to hide such optimizations
in a bit mask:
sysctl_net_optimizations & 1: optimize for end host
sysctl_net_optimizations & 2: optimize for router
...
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* [PATCH -v1 2/3] usbnet: decrease suspend count if returning -EBUSY for runtime suspend
From: Ming Lei @ 2012-06-20 7:15 UTC (permalink / raw)
To: David S. Miller, Greg Kroah-Hartman
Cc: Oliver Neukum, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA, Ming Lei
In-Reply-To: <1340176553-32225-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
This patch decreases dev->suspend_count in the -EBUSY failure path
of usbnet_suspend. Without the change, the later runtime suspend
will do nothing except for increasing dev->suspend_count.
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
drivers/net/usb/usbnet.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index f06cf9b..9bfa775 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1508,6 +1508,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
spin_lock_irq(&dev->txq.lock);
/* don't autosuspend while transmitting */
if (dev->txq.qlen && PMSG_IS_AUTO(message)) {
+ dev->suspend_count--;
spin_unlock_irq(&dev->txq.lock);
return -EBUSY;
} else {
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH -v1 3/3] usbnet: handle remote wakeup asap
From: Ming Lei @ 2012-06-20 7:15 UTC (permalink / raw)
To: David S. Miller, Greg Kroah-Hartman
Cc: Oliver Neukum, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA, Ming Lei
In-Reply-To: <1340176553-32225-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
If usbnet is resumed by remote wakeup, generally there are
some packets comming to be handled, so allocate and submit
rx URBs in usbnet_resume to avoid delays introduced by tasklet.
Otherwise, usbnet may have been runtime suspended before the
usbnet_bh is executed to schedule Rx URBs.
Without the patch, usbnet can't recieve any packets from peer
in runtime suspend state if runtime PM is enabled and
autosuspend_delay is set as zero.
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
drivers/net/usb/usbnet.c | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 9bfa775..a89d6c5 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1201,6 +1201,21 @@ deferred:
}
EXPORT_SYMBOL_GPL(usbnet_start_xmit);
+static void rx_alloc_submit(struct usbnet *dev, gfp_t flags)
+{
+ struct urb *urb;
+ int i;
+
+ /* don't refill the queue all at once */
+ for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {
+ urb = usb_alloc_urb(0, flags);
+ if (urb != NULL) {
+ if (rx_submit(dev, urb, flags) == -ENOLINK)
+ return;
+ }
+ }
+}
+
/*-------------------------------------------------------------------------*/
// tasklet (work deferred from completions, in_irq) or timer
@@ -1240,26 +1255,14 @@ static void usbnet_bh (unsigned long param)
!timer_pending (&dev->delay) &&
!test_bit (EVENT_RX_HALT, &dev->flags)) {
int temp = dev->rxq.qlen;
- int qlen = RX_QLEN (dev);
-
- if (temp < qlen) {
- struct urb *urb;
- int i;
-
- // don't refill the queue all at once
- for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
- urb = usb_alloc_urb (0, GFP_ATOMIC);
- if (urb != NULL) {
- if (rx_submit (dev, urb, GFP_ATOMIC) ==
- -ENOLINK)
- return;
- }
- }
+
+ if (temp < RX_QLEN(dev)) {
+ rx_alloc_submit(dev, GFP_ATOMIC);
if (temp != dev->rxq.qlen)
netif_dbg(dev, link, dev->net,
"rxqlen %d --> %d\n",
temp, dev->rxq.qlen);
- if (dev->rxq.qlen < qlen)
+ if (dev->rxq.qlen < RX_QLEN(dev))
tasklet_schedule (&dev->bh);
}
if (dev->txq.qlen < TX_QLEN (dev))
@@ -1565,6 +1568,13 @@ int usbnet_resume (struct usb_interface *intf)
spin_unlock_irq(&dev->txq.lock);
if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+ /* handle remote wakeup ASAP */
+ if (!dev->wait &&
+ netif_device_present(dev->net) &&
+ !timer_pending(&dev->delay) &&
+ !test_bit(EVENT_RX_HALT, &dev->flags))
+ rx_alloc_submit(dev, GFP_KERNEL);
+
if (!(dev->txq.qlen >= TX_QLEN(dev)))
netif_tx_wake_all_queues(dev->net);
tasklet_schedule (&dev->bh);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH -v1 0/3] usbnet: usbnet: PM related fixes
From: Ming Lei @ 2012-06-20 7:15 UTC (permalink / raw)
To: David S. Miller, Greg Kroah-Hartman; +Cc: Oliver Neukum, netdev, linux-usb
Hi David,
The 3 patches fix some PM related problems.
v1:
- one line fix in 3/3: GFP_ATOMIC -> flags in rx_alloc_submit
drivers/net/usb/usbnet.c | 47 +++++++++++++++++++++++++++++-----------------
1 file changed, 30 insertions(+), 17 deletions(-)
Thanks,
--
Ming Lei
^ permalink raw reply
* [PATCH -v1 1/3] usbnet: clear OPEN flag in failure path
From: Ming Lei @ 2012-06-20 7:15 UTC (permalink / raw)
To: David S. Miller, Greg Kroah-Hartman
Cc: Oliver Neukum, netdev, linux-usb, Ming Lei
In-Reply-To: <1340176553-32225-1-git-send-email-ming.lei@canonical.com>
Without clearing OPEN flag in failure path, runtime or system resume
may submit interrupt/rx URB and start tx queue mistakenly on a
interface in DOWN state.
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
drivers/net/usb/usbnet.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ac2e493..f06cf9b 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -793,11 +793,13 @@ int usbnet_open (struct net_device *net)
if (info->manage_power) {
retval = info->manage_power(dev, 1);
if (retval < 0)
- goto done;
+ goto done_manage_power_error;
usb_autopm_put_interface(dev->intf);
}
return retval;
+done_manage_power_error:
+ clear_bit(EVENT_DEV_OPEN, &dev->flags);
done:
usb_autopm_put_interface(dev->intf);
done_nopm:
--
1.7.9.5
^ permalink raw reply related
* Re: 10GBE performance drop with net.ipv4.tcp_timestamps=0
From: Eric Dumazet @ 2012-06-20 7:22 UTC (permalink / raw)
To: Stefan Priebe - Profihost AG; +Cc: Linux Netdev List
In-Reply-To: <4FE17522.5050005@profihost.ag>
On Wed, 2012-06-20 at 09:00 +0200, Stefan Priebe - Profihost AG wrote:
> Am 19.06.2012 23:31, schrieb Eric Dumazet:
> > On Tue, 2012-06-19 at 23:08 +0200, Stefan Priebe wrote:
> >> i'm testing 10GBE speed with tweo servers. One with 3.5-rc3 nd thoe
> >> other one whith RHEL 6 (2.6.32 kernel).
> >>
> >> I noticed that setting
> >> net.ipv4.tcp_timestamps=0
> >>
> >> descreased the performance from 9,7 Full Duplex to 3-4Gb/s.
> >>
> >> Is this bahviour fine? What should / could i tet?
> >>
> >
> > Really, you should provide more input than that, if you really want us
> > to help.
>
> *arg* forgot to add the pastebin links. Sorry. Speed degraded in this
> case from 9,88Gbit/s to 2,45Gbit/s. When i turn on timestamps it's
> perfect again. Server A has 3.5.0-rc3 and server B has an RHEL6 2.6.32
> kernel.
>
> Before:
> http://pastebin.com/raw.php?i=1gVraWVc
>
> After:
> http://pastebin.com/raw.php?i=NSh8Y29s
You have a lot of packet losses
add "tc -s -d qdisc" , "ifconfig -a " and "ethtool -S ethX" outputs for
both servers
^ permalink raw reply
* Warning! Your mailbox is almost full.
From: Publishers Clearing House @ 2012-06-20 7:16 UTC (permalink / raw)
Congratulations, your email address has won ($1,000,000.00USD) in the
on going Publishers Clearing House loto draw that was held today, pls
fill details bellow for claims. Email us back: onlinepch_213@ozledim.net
Name in full:.. Address:... Sex:.. Occupation:.. Present Country:..
!!!Once Again Congratulations!!!
Yours Sincerely,
Mrs.Reyna Cruz
ONLINE CO-ORDINATOR.
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
^ permalink raw reply
* [PATCH] netxen: Error return off by one in 'netxen_nic_set_pauseparam()'.
From: santosh nayak @ 2012-06-20 7:27 UTC (permalink / raw)
To: sony.chacko, rajesh.borundia; +Cc: netdev, kernel-janitors, Santosh Nayak
From: Santosh Nayak <santoshprasadnayak@gmail.com>
There are 'NETXEN_NIU_MAX_GBE_PORTS' GBE ports. Port indexing starts
from zero.
Hence we should also return error for "port == NETXEN_NIU_MAX_GBE_PORTS"
Signed-off-by: Santosh Nayak <santoshprasadnayak@gmail.com>
---
Destination tree "linux-next"
.../ethernet/qlogic/netxen/netxen_nic_ethtool.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 3973040..d4f179f 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -489,7 +489,7 @@ netxen_nic_get_pauseparam(struct net_device *dev,
int port = adapter->physical_port;
if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
return;
/* get flow control settings */
val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
@@ -534,7 +534,7 @@ netxen_nic_set_pauseparam(struct net_device *dev,
int port = adapter->physical_port;
/* read mode */
if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
return -EIO;
/* set flow control */
val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
--
1.7.4.4
^ permalink raw reply related
* Warning! Your mailbox is almost full.
From: Publishers Clearing House @ 2012-06-20 7:29 UTC (permalink / raw)
Congratulations, your email address has won ($1,000,000.00USD) in the
on going Publishers Clearing House loto draw that was held today, pls
fill details bellow for claims. Email us back: onlinepch_213@ozledim.net
Name in full:.. Address:... Sex:.. Occupation:.. Present Country:..
!!!Once Again Congratulations!!!
Yours Sincerely,
Mrs.Reyna Cruz
ONLINE CO-ORDINATOR.
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
^ permalink raw reply
* Re: [PATCH 02.5] mm: sl[au]b: first remove PFMEMALLOC flag then SLAB flag
From: Mel Gorman @ 2012-06-20 7:38 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Andrew Morton, Linux-MM, Linux-Netdev, LKML, David Miller,
Neil Brown, Peter Zijlstra, Mike Christie, Eric B Munson
In-Reply-To: <20120615155432.GA5498@breakpoint.cc>
On Fri, Jun 15, 2012 at 05:54:32PM +0200, Sebastian Andrzej Siewior wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>
> If we first remove the SLAB flag followed by the PFMEMALLOC flag then the
> removal of the latter will trigger the VM_BUG_ON() as it can be seen in
> | kernel BUG at include/linux/page-flags.h:474!
> | invalid opcode: 0000 [#1] PREEMPT SMP
> | Call Trace:
> | [<c10e2d77>] slab_destroy+0x27/0x70
> | [<c10e3285>] drain_freelist+0x55/0x90
> | [<c10e344e>] __cache_shrink+0x6e/0x90
> | [<c14e3211>] ? acpi_sleep_init+0xcf/0xcf
> | [<c10e349d>] kmem_cache_shrink+0x2d/0x40
>
> because the SLAB flag is gone. This patch simply changes the order.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Grr, yes of course. Thanks very much. I've folded this into patch 2 and
preserved credit.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH -v1 1/3] usbnet: clear OPEN flag in failure path
From: Oliver Neukum @ 2012-06-20 7:44 UTC (permalink / raw)
To: Ming Lei; +Cc: David S. Miller, Greg Kroah-Hartman, netdev, linux-usb
In-Reply-To: <1340176553-32225-2-git-send-email-ming.lei@canonical.com>
Am Mittwoch, 20. Juni 2012, 09:15:51 schrieb Ming Lei:
> Without clearing OPEN flag in failure path, runtime or system resume
> may submit interrupt/rx URB and start tx queue mistakenly on a
> interface in DOWN state.
>
> Signed-off-by: Ming Lei <ming.lei@canonical.com>
Acked-by: Oliver Neukum <oneukum@suse.de>
^ permalink raw reply
* Re: [PATCH] netxen: Error return off by one in 'netxen_nic_set_pauseparam()'.
From: Dan Carpenter @ 2012-06-20 7:44 UTC (permalink / raw)
To: santosh nayak; +Cc: sony.chacko, rajesh.borundia, netdev, kernel-janitors
In-Reply-To: <1340177259-14083-1-git-send-email-santoshprasadnayak@gmail.com>
On Wed, Jun 20, 2012 at 12:57:39PM +0530, santosh nayak wrote:
> From: Santosh Nayak <santoshprasadnayak@gmail.com>
>
> There are 'NETXEN_NIU_MAX_GBE_PORTS' GBE ports. Port indexing starts
> from zero.
> Hence we should also return error for "port == NETXEN_NIU_MAX_GBE_PORTS"
>
I don't know this code well enough to say if you are right or not,
but what about for port == NETXEN_NIU_MAX_XG_PORTS a few lines later
in both functions?
regards,
dan carpenter
^ permalink raw reply
* Re: [PATCH -v1 2/3] usbnet: decrease suspend count if returning -EBUSY for runtime suspend
From: Oliver Neukum @ 2012-06-20 7:45 UTC (permalink / raw)
To: Ming Lei
Cc: David S. Miller, Greg Kroah-Hartman,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1340176553-32225-3-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Am Mittwoch, 20. Juni 2012, 09:15:52 schrieb Ming Lei:
> This patch decreases dev->suspend_count in the -EBUSY failure path
> of usbnet_suspend. Without the change, the later runtime suspend
> will do nothing except for increasing dev->suspend_count.
>
> Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Acked-by: Oliver Neukum <oneukum-l3A5Bk7waGM@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH -v1 3/3] usbnet: handle remote wakeup asap
From: Oliver Neukum @ 2012-06-20 7:46 UTC (permalink / raw)
To: Ming Lei; +Cc: David S. Miller, Greg Kroah-Hartman, netdev, linux-usb
In-Reply-To: <1340176553-32225-4-git-send-email-ming.lei@canonical.com>
Am Mittwoch, 20. Juni 2012, 09:15:53 schrieb Ming Lei:
> If usbnet is resumed by remote wakeup, generally there are
> some packets comming to be handled, so allocate and submit
> rx URBs in usbnet_resume to avoid delays introduced by tasklet.
> Otherwise, usbnet may have been runtime suspended before the
> usbnet_bh is executed to schedule Rx URBs.
>
> Without the patch, usbnet can't recieve any packets from peer
> in runtime suspend state if runtime PM is enabled and
> autosuspend_delay is set as zero.
>
> Signed-off-by: Ming Lei <ming.lei@canonical.com>
Acked-by: Oliver Neukum <oneukum@suse.de>
^ permalink raw reply
* Re: [PATCH -v1 0/3] usbnet: usbnet: PM related fixes
From: Oliver Neukum @ 2012-06-20 7:46 UTC (permalink / raw)
To: Ming Lei; +Cc: David S. Miller, Greg Kroah-Hartman, netdev, linux-usb
In-Reply-To: <1340176553-32225-1-git-send-email-ming.lei@canonical.com>
Am Mittwoch, 20. Juni 2012, 09:15:50 schrieb Ming Lei:
> Hi David,
>
> The 3 patches fix some PM related problems.
The first two patches should go into stable.
Could you send them?
Regards
Oliver
^ permalink raw reply
* Re: [PATCH v3] ipv4: Early TCP socket demux.
From: David Miller @ 2012-06-20 7:57 UTC (permalink / raw)
To: ja; +Cc: netdev
In-Reply-To: <alpine.LFD.2.00.1206200937040.1912@ja.ssi.bg>
From: Julian Anastasov <ja@ssi.bg>
Date: Wed, 20 Jun 2012 10:00:37 +0300 (EEST)
> if (skb->dev != dst->dev)
> dst = NULL;
That makes the most sense.
> Also, is it a good idea to hide such optimizations
> in a bit mask:
>
> sysctl_net_optimizations & 1: optimize for end host
> sysctl_net_optimizations & 2: optimize for router
> ...
God, that's ugly as sin.
We're putting this down into GRO, so people can tune with
an existing knob there as they already do.
^ permalink raw reply
* Re: [PATCH] netxen: Error return off by one in 'netxen_nic_set_pauseparam()'.
From: Dan Carpenter @ 2012-06-20 7:57 UTC (permalink / raw)
To: santosh nayak; +Cc: sony.chacko, rajesh.borundia, netdev, kernel-janitors
In-Reply-To: <1340177259-14083-1-git-send-email-santoshprasadnayak@gmail.com>
On Wed, Jun 20, 2012 at 12:57:39PM +0530, santosh nayak wrote:
> From: Santosh Nayak <santoshprasadnayak@gmail.com>
>
> There are 'NETXEN_NIU_MAX_GBE_PORTS' GBE ports. Port indexing starts
> from zero.
> Hence we should also return error for "port == NETXEN_NIU_MAX_GBE_PORTS"
>
So my understanding is that you are guessing on this based on the
fact that, "Who counts from 0-4 inclusive?". I can't argue with
that logic.
Looking some more at NETXEN_NIU_MAX_XG_PORTS. It is used off by one
4 times and it's used correctly 1 time.
regards,
dan carpenter
^ permalink raw reply
* Re: [PATCH] netxen: Error return off by one in 'netxen_nic_set_pauseparam()'.
From: santosh prasad nayak @ 2012-06-20 7:59 UTC (permalink / raw)
To: Dan Carpenter, rajesh.borundia; +Cc: sony.chacko, netdev, kernel-janitors
In-Reply-To: <20120620074447.GS4400@mwanda>
On Wed, Jun 20, 2012 at 1:14 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote:
> On Wed, Jun 20, 2012 at 12:57:39PM +0530, santosh nayak wrote:
>> From: Santosh Nayak <santoshprasadnayak@gmail.com>
>>
>> There are 'NETXEN_NIU_MAX_GBE_PORTS' GBE ports. Port indexing starts
>> from zero.
>> Hence we should also return error for "port == NETXEN_NIU_MAX_GBE_PORTS"
>>
>
> I don't know this code well enough to say if you are right or not,
> but what about for port == NETXEN_NIU_MAX_XG_PORTS a few lines later
> in both functions?
I think "for port == NETXEN_NIU_MAX_XG_PORTS" error should be returned.
@Rajesh,
Can you please comment on it ?
regards
santosh
>
> regards,
> dan carpenter
>
^ permalink raw reply
* Re: [PATCH] usbnet: Activate halt interrupt endpoint before re-submit URB
From: Oliver Neukum @ 2012-06-20 8:00 UTC (permalink / raw)
To: Huajun Li
Cc: David Miller, tom.leiming-Re5JQEeQqe8AvxtiuMwx3w,
stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz,
linux-usb-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CA+v9cxZG6b1O7kOQpeTELtv0vHzqy-8NH84boMpim0BM+tp1eQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Am Montag, 18. Juni 2012, 18:25:15 schrieb Huajun Li:
> On Mon, Jun 18, 2012 at 3:23 PM, Oliver Neukum <oneukum-l3A5Bk7waGM@public.gmane.org> wrote:
> > Am Montag, 18. Juni 2012, 01:30:17 schrieb David Miller:
> >> From: Huajun Li <huajun.li.lee-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> Date: Wed, 13 Jun 2012 20:50:31 +0800
> >>
> >> > intr_complete() submits URB even the interrupt endpoint stalls.
> >> > This patch will try to activate the endpoint once the exception
> >> > occurs, and then re-submit the URB if the endpoint works again.
> >> >
> >> > Signed-off-by: Huajun Li <huajun.li.lee-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >>
> >> Review from USB experts would be appreciated.
> >
> > The code implements a minimum error handler correctly.
> > Did you observe a stall in actual hardware or is this a just
> > in case patch?
> >
>
> This one is just a patch, thanks for your comments.
Very well, on second thought, this patch makes sense.
Could you resend and I'll ack?
Regards
Oliver
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox