* [net-next.git 2/9] stmmac: add IEEE 1588-2002 PTP support
From: Giuseppe CAVALLARO @ 2013-03-07 10:50 UTC (permalink / raw)
To: netdev; +Cc: bh74.an, ayagond, Rayagond Kokatanur
In-Reply-To: <1362653419-1047-1-git-send-email-peppe.cavallaro@st.com>
From: Rayagond Kokatanur <rayagond@vayavyalabs.com>
This patch enhances the stmmac driver to support IEEE 1588-2002
PTP (Precision Time Protocol) version 1.
IEEE 1588-2002 standard defines a protocol, Precision Time
Protocol(PTP),
which enables precise synchronization of clocks in measurement and
control systems implemented with technologies such as network
communication,local computing, & distributed objects.
HW Timestamp support can be enabled while configuring the Kernel and
the Koption is: STMMAC_USE_HWSTAMP
At runtime, the support is verified by looking at the HW capability
register.
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 +
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 23 ++-
drivers/net/ethernet/stmicro/stmmac/common.h | 27 ++-
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 1 -
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 37 +++
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 34 +++
drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 14 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 8 +
.../net/ethernet/stmicro/stmmac/stmmac_hwstamp.c | 129 ++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 255 +++++++++++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 72 ++++++
12 files changed, 588 insertions(+), 24 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c
create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index c0ea838..ef703b3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -71,5 +71,16 @@ config STMMAC_CHAINED
endchoice
+config STMMAC_USE_HWSTAMP
+ bool "Use IEEE 1588 Precision Time Protocol"
+ depends on STMMAC_ETH
+ select PTP_1588_CLOCK
+ default n
+ ---help---
+ Enable this option to support the IEEE 1588 Precision Time Protocol
+ (PTP) and HW Timestamps.
+ At runtime, on new chip generations, the hardware capability
+ register will be used to verify if either the IEEE 1588-2008 Advanced
+ Timestamping (PTPv2) or IEEE 1588-2002 (PTPv1) is actually supported.
endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index c8e8ea6..cc97c07 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -3,6 +3,7 @@ stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
+stmmac-$(CONFIG_STMMAC_USE_HWSTAMP) += stmmac_hwstamp.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index ad3d75f..dd60f6b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -92,16 +92,35 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
return ret;
}
-static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
+ struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+ if (priv->hwts_rx_en)
+ /* NOTE: Device will overwrite des3 with timestamp value if
+ * 1588-2002 time stamping is enabled, hence reinitialize it
+ * to keep explicit chaining in the descriptor.
+ */
+ p->des3 = (unsigned int)(priv->dma_rx +
+ ((priv->dirty_rx) + 1) % priv->dma_rx_size);
}
static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
{
}
-static void stmmac_clean_desc3(struct dma_desc *p)
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p,
+ int tstamp_taken)
{
+ struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+ if (tstamp_taken && priv->hw->desc->get_tx_ls(p))
+ /* NOTE: Device will overwrite des3 with timestamp value if
+ * 1588-2002 time stamping is enabled, hence reinitialize it
+ * to keep explicit chaining in the descriptor.
+ */
+ p->des3 = (unsigned int)(priv->dma_tx +
+ ((priv->dirty_tx + 1) % priv->dma_tx_size));
}
static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 186d148..fa8ff9b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -290,6 +290,16 @@ struct stmmac_desc_ops {
/* Return the reception status looking at the RDES1 */
int (*rx_status) (void *data, struct stmmac_extra_stats *x,
struct dma_desc *p);
+ /* Set tx timestamp enable bit */
+ void (*enable_tx_timestamp) (struct dma_desc *p);
+ /* get tx timestamp status */
+ int (*get_tx_timestamp_status) (struct dma_desc *p);
+ /* get tx/rx timestamp low value */
+ u32 (*get_timestamp_low) (struct dma_desc *p);
+ /* get tx/rx timestamp high value */
+ u32 (*get_timestamp_high) (struct dma_desc *p);
+ /* get rx timestamp status */
+ int (*get_rx_timestamp_status) (struct dma_desc *p);
};
struct stmmac_dma_ops {
@@ -346,6 +356,15 @@ struct stmmac_ops {
void (*set_eee_pls) (void __iomem *ioaddr, int link);
};
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+struct stmmac_hwtimestamp {
+ void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
+ void (*config_sub_second_increment) (void __iomem *ioaddr);
+ int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
+ int (*config_addend)(void __iomem *ioaddr, u32 addend);
+};
+#endif
+
struct mac_link {
int port;
int duplex;
@@ -360,11 +379,11 @@ struct mii_regs {
struct stmmac_ring_mode_ops {
unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
- void (*refill_desc3) (int bfsize, struct dma_desc *p);
+ void (*refill_desc3) (void *priv, struct dma_desc *p);
void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
unsigned int size);
- void (*clean_desc3) (struct dma_desc *p);
+ void (*clean_desc3) (void *priv, struct dma_desc *p, int tstamp_taken);
int (*set_16kib_bfsize) (int mtu);
};
@@ -373,6 +392,9 @@ struct mac_device_info {
const struct stmmac_desc_ops *desc;
const struct stmmac_dma_ops *dma;
const struct stmmac_ring_mode_ops *ring;
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+ const struct stmmac_hwtimestamp *ptp;
+#endif
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
unsigned int synopsys_uid;
@@ -390,5 +412,4 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);
extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
extern const struct stmmac_ring_mode_ops ring_mode_ops;
-
#endif /* __COMMON_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 491d7e9..8c4ea93 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -286,4 +286,3 @@ void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
addr[4] = hi_addr & 0xff;
addr[5] = (hi_addr >> 8) & 0xff;
}
-
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index 2fc8ef9..4d635d5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -323,6 +323,38 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
return p->des01.erx.frame_length;
}
+static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
+{
+ p->des01.etx.time_stamp_enable = 1;
+}
+
+static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
+{
+ return p->des01.etx.time_stamp_status;
+}
+
+static u32 enh_desc_get_timestamp_low(struct dma_desc *p)
+{
+ /* FIXME if Enhance descriptor with 8 DWORDS is enabled */
+ return p->des2;
+}
+
+static u32 enh_desc_get_timestamp_high(struct dma_desc *p)
+{
+ /* FIXME if Enhance descriptor with 8 DWORDS is enabled */
+ return p->des3;
+}
+
+static int enh_desc_get_rx_timestamp_status(struct dma_desc *p)
+{
+ /* FIXME if Enhance descriptor with 8 DWORDS is enabled */
+ if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ /* timestamp is currupted, hence don't store it */
+ return 0;
+ else
+ return 1;
+}
+
const struct stmmac_desc_ops enh_desc_ops = {
.tx_status = enh_desc_get_tx_status,
.rx_status = enh_desc_get_rx_status,
@@ -339,4 +371,9 @@ const struct stmmac_desc_ops enh_desc_ops = {
.set_tx_owner = enh_desc_set_tx_owner,
.set_rx_owner = enh_desc_set_rx_owner,
.get_rx_frame_len = enh_desc_get_rx_frame_len,
+ .enable_tx_timestamp = enh_desc_enable_tx_timestamp,
+ .get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
+ .get_timestamp_low = enh_desc_get_timestamp_low,
+ .get_timestamp_high = enh_desc_get_timestamp_high,
+ .get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 68962c5..edb5e88 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -215,6 +215,35 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
return p->des01.rx.frame_length;
}
+static void ndesc_enable_tx_timestamp(struct dma_desc *p)
+{
+ p->des01.tx.time_stamp_enable = 1;
+}
+
+static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
+{
+ return p->des01.tx.time_stamp_status;
+}
+
+static u32 ndesc_get_timestamp_low(struct dma_desc *p)
+{
+ return p->des2;
+}
+
+static u32 ndesc_get_timestamp_high(struct dma_desc *p)
+{
+ return p->des3;
+}
+
+static int ndesc_get_rx_timestamp_status(struct dma_desc *p)
+{
+ if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ /* timestamp is currupted, hence don't store it */
+ return 0;
+ else
+ return 1;
+}
+
const struct stmmac_desc_ops ndesc_ops = {
.tx_status = ndesc_get_tx_status,
.rx_status = ndesc_get_rx_status,
@@ -231,4 +260,9 @@ const struct stmmac_desc_ops ndesc_ops = {
.set_tx_owner = ndesc_set_tx_owner,
.set_rx_owner = ndesc_set_rx_owner,
.get_rx_frame_len = ndesc_get_rx_frame_len,
+ .enable_tx_timestamp = ndesc_enable_tx_timestamp,
+ .get_tx_timestamp_status = ndesc_get_tx_timestamp_status,
+ .get_timestamp_low = ndesc_get_timestamp_low,
+ .get_timestamp_high = ndesc_get_timestamp_high,
+ .get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 839e349..94a1c2f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -85,11 +85,14 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
return ret;
}
-static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
- /* Fill DES3 in case of RING mode */
- if (bfsize >= BUF_SIZE_8KiB)
- p->des3 = p->des2 + BUF_SIZE_8KiB;
+ struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+ if (unlikely(priv->plat->has_gmac))
+ /* Fill DES3 in case of RING mode */
+ if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
}
/* In ring mode we need to fill the desc3 because it is used
@@ -105,7 +108,8 @@ static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
{
}
-static void stmmac_clean_desc3(struct dma_desc *p)
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p,
+ int tstamp_taken)
{
if (unlikely(p->des3))
p->des3 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 013a7d5..665f2a2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -94,6 +94,11 @@ struct stmmac_priv {
u32 tx_coal_timer;
int use_riwt;
u32 rx_riwt;
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+ int hwts_tx_en;
+ int hwts_rx_en;
+ unsigned int default_addend;
+#endif
};
extern int phyaddr;
@@ -103,6 +108,9 @@ extern int stmmac_mdio_register(struct net_device *ndev);
extern void stmmac_set_ethtool_ops(struct net_device *netdev);
extern const struct stmmac_desc_ops enh_desc_ops;
extern const struct stmmac_desc_ops ndesc_ops;
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+extern const struct stmmac_hwtimestamp stmmac_ptp;
+#endif
int stmmac_freeze(struct net_device *ndev);
int stmmac_restore(struct net_device *ndev);
int stmmac_resume(struct net_device *ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c
new file mode 100644
index 0000000..be9e399
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ Copyright (C) 2013 Vayavya Labs Pvt Ltd
+
+ This implements all the API for managing HW timestamp & PTP.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "common.h"
+#include "stmmac_ptp.h"
+
+static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
+{
+ writel(data, ioaddr + PTP_TCR);
+}
+
+static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
+{
+ u32 value = readl(ioaddr + PTP_TCR);
+ unsigned long data;
+
+ /* Convert the ptp_clock to nano second
+ * formula = (1/ptp_clock) * 1000000000
+ * where, ptp_clock = 50MHz for FINE correction method &
+ * ptp_clock = STMMAC_SYSCLOCK for COARSE correction method
+ */
+ if (value & PTP_TCR_TSCFUPDT)
+ data = (1000000000ULL / 50000000);
+ else
+ data = (1000000000ULL / STMMAC_SYSCLOCK);
+
+ writel(data, ioaddr + PTP_SSIR);
+}
+
+static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
+{
+ int limit;
+ u32 value;
+
+ /* wait for previous(if any) system time initialize to complete */
+ limit = 100;
+ while (limit--) {
+ if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSINIT))
+ break;
+ mdelay(10);
+ }
+
+ if (limit < 0)
+ return -EBUSY;
+
+ writel(sec, ioaddr + PTP_STSUR);
+ writel(nsec, ioaddr + PTP_STNSUR);
+ /* issue command to initialize the system time value */
+ value = readl(ioaddr + PTP_TCR);
+ value |= PTP_TCR_TSINIT;
+ writel(value, ioaddr + PTP_TCR);
+
+ /* wait for present system time initialize to complete */
+ limit = 100;
+ while (limit--) {
+ if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSINIT))
+ break;
+ mdelay(10);
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int stmmac_config_addend(void __iomem *ioaddr, u32 addend)
+{
+ u32 value;
+ int limit;
+
+ /* wait for previous (if any) addend update to complete */
+ limit = 100;
+ while (limit--) {
+ if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSADDREG))
+ break;
+ mdelay(10);
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ writel(addend, ioaddr + PTP_TAR);
+ /* issue command to update the addend value */
+ value = readl(ioaddr + PTP_TCR);
+ value |= PTP_TCR_TSADDREG;
+ writel(value, ioaddr + PTP_TCR);
+
+ /* wait for present addend update to complete */
+ limit = 100;
+ while (limit--) {
+ if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSADDREG))
+ break;
+ mdelay(10);
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+const struct stmmac_hwtimestamp stmmac_ptp = {
+ .config_hw_tstamping = stmmac_config_hw_tstamping,
+ .init_systime = stmmac_init_systime,
+ .config_sub_second_increment = stmmac_config_sub_second_increment,
+ .config_addend = stmmac_config_addend,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 260af93..3bbd554 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -47,6 +47,10 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#endif
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+#include <linux/net_tstamp.h>
+#include "stmmac_ptp.h"
+#endif
#include "stmmac.h"
#undef STMMAC_DEBUG
@@ -304,6 +308,192 @@ static void stmmac_eee_adjust(struct stmmac_priv *priv)
priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
}
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+/* stmmac_get_tx_hwtstamp:
+ * @priv : pointer to private device structure.
+ * @p : pointer to desc structure.
+ * @skb : the socket buffer
+ * Description :
+ * This function will read timestamp from the descriptor & pass it to stack.
+ * and also perform some sanity checks.
+ * Return value :
+ * 1 if time stamp is taken & 0 if time stamp is not taken.
+ */
+static unsigned int stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
+ struct dma_desc *p,
+ struct sk_buff *skb)
+{
+ struct skb_shared_hwtstamps shhwtstamp;
+ u64 ns;
+
+ if (!priv->hwts_tx_en)
+ return 0;
+
+ /* if skb doesn't support hw tstamp */
+ if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
+ return 0;
+
+ /* check tx tstamp status */
+ if (!priv->hw->desc->get_tx_timestamp_status(p))
+ return 0;
+
+ /* get the valid tstamp */
+ ns = priv->hw->desc->get_timestamp_low(p);
+ /* convert high/sec time stamp value to nanosecond */
+ ns += priv->hw->desc->get_timestamp_high(p) * 1000000000ULL;
+
+ memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
+ shhwtstamp.hwtstamp = ns_to_ktime(ns);
+ /* pass tstamp to stack */
+ skb_tstamp_tx(skb, &shhwtstamp);
+
+ return 1;
+}
+
+/* stmmac_get_rx_hwtstamp:
+ * @priv : pointer to private device structure.
+ * @p : pointer to desc structure.
+ * @skb : the socket buffer
+ * Description :
+ * This function will read received packet's timestamp from the descriptor
+ * and pass it to stack. It also perform some sanity checks.
+ */
+static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
+ struct sk_buff *skb)
+{
+ struct skb_shared_hwtstamps *shhwtstamp = NULL;
+ u64 ns;
+
+ if (!priv->hwts_rx_en)
+ return;
+
+ /* if rx tstamp is not valid */
+ if (!priv->hw->desc->get_rx_timestamp_status(p))
+ return;
+
+ /* get valid tstamp */
+ ns = priv->hw->desc->get_timestamp_low(p);
+ /* convert high/sec time stamp value to nanosecond */
+ ns += priv->hw->desc->get_timestamp_high(p) * 1000000000ULL;
+ shhwtstamp = skb_hwtstamps(skb);
+ memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
+ shhwtstamp->hwtstamp = ns_to_ktime(ns);
+}
+
+/**
+ * stmmac_hwtstamp_ioctl - control hardware timestamping.
+ * @dev: device pointer.
+ * @ifr: An IOCTL specefic structure, that can contain a pointer to
+ * a proprietary structure used to pass information to the driver.
+ * Description:
+ * This function configures the MAC to enable/disable both outgoing(TX)
+ * and incoming(RX) packets time stamping based on user input.
+ * Return Value:
+ * 0 on success and an appropriate -ve integer on failure.
+ */
+static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+ struct hwtstamp_config config;
+ struct timespec now;
+ u64 temp = 0;
+
+ if (!priv->dma_cap.time_stamp) {
+ netdev_alert(priv->dev, "No HW time stamping supported\n");
+ priv->hwts_tx_en = 0;
+ priv->hwts_rx_en = 0;
+
+ return -EOPNOTSUPP;
+ }
+
+ if (copy_from_user(&config, ifr->ifr_data,
+ sizeof(struct hwtstamp_config)))
+ return -EFAULT;
+
+ pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
+ __func__, config.flags, config.tx_type, config.rx_filter);
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ priv->hwts_tx_en = 0;
+ break;
+ case HWTSTAMP_TX_ON:
+ priv->hwts_tx_en = 1;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ config.rx_filter = HWTSTAMP_FILTER_NONE;
+ break;
+ default:
+ /* PTP v1, UDP, any kind of event packet */
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+ break;
+ }
+ priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
+
+ if (!priv->hwts_tx_en && !priv->hwts_rx_en)
+ priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
+ else {
+ priv->hw->ptp->config_hw_tstamping(priv->ioaddr,
+ (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT));
+
+ /* program Sub Second Increment reg */
+ priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
+
+ /* calculate default added value:
+ * formula is :
+ * addend = (2^32)/freq_div_ratio;
+ * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
+ * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
+ * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
+ * achive 20ns accuracy.
+ *
+ * 2^x * y == (y << x), hence
+ * 2^32 * 50000000 ==> (50000000 << 32)
+ */
+ temp = (u64)(50000000ULL << 32);
+ priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
+ priv->hw->ptp->config_addend(priv->ioaddr,
+ priv->default_addend);
+
+ /* initialize system time */
+ getnstimeofday(&now);
+ priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
+ now.tv_nsec);
+ }
+
+ return copy_to_user(ifr->ifr_data, &config,
+ sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
+}
+
+static void stmmac_init_ptp(struct stmmac_priv *priv)
+{
+ if (priv->dma_cap.time_stamp)
+ pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+ if (priv->dma_cap.atime_stamp)
+ pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
+
+ priv->hw->ptp = &stmmac_ptp;
+
+ priv->hwts_tx_en = 0;
+ priv->hwts_rx_en = 0;
+
+}
+#else
+#define stmmac_hwtstamp_ioctl(dev, ifr) (-EOPNOTSUPP)
+#define stmmac_get_rx_hwtstamp(priv, p, skb)
+#define stmmac_get_tx_hwtstamp(priv, p, skb) 0
+#define stmmac_init_ptp(priv)
+#endif /* CONFIG_STMMAC_USE_HWSTAMP */
+
/**
* stmmac_adjust_link
* @dev: net device structure
@@ -712,6 +902,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
while (priv->dirty_tx != priv->cur_tx) {
int last;
+ unsigned int ts = 0;
unsigned int entry = priv->dirty_tx % txsize;
struct sk_buff *skb = priv->tx_skbuff[entry];
struct dma_desc *p = priv->dma_tx + entry;
@@ -732,6 +923,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
priv->xstats.tx_pkt_n++;
} else
priv->dev->stats.tx_errors++;
+
+ ts = stmmac_get_tx_hwtstamp(priv, p, skb);
}
TX_DBG("%s: curr %d, dirty %d\n", __func__,
priv->cur_tx, priv->dirty_tx);
@@ -743,7 +936,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
DMA_TO_DEVICE);
priv->tx_skbuff_dma[entry] = 0;
}
- priv->hw->ring->clean_desc3(p);
+ priv->hw->ring->clean_desc3(priv, p, ts);
if (likely(skb != NULL)) {
dev_kfree_skb(skb);
@@ -1027,6 +1220,7 @@ static int stmmac_open(struct net_device *dev)
goto open_error;
}
+
/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
@@ -1093,6 +1287,8 @@ static int stmmac_open(struct net_device *dev)
stmmac_mmc_setup(priv);
+ stmmac_init_ptp(priv);
+
#ifdef CONFIG_STMMAC_DEBUG_FS
ret = stmmac_init_fs(dev);
if (ret < 0)
@@ -1325,7 +1521,17 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
- skb_tx_timestamp(skb);
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+ if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+ priv->hwts_tx_en)) {
+ /* declare that device is doing timestamping */
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ priv->hw->desc->enable_tx_timestamp(first);
+ }
+
+ if (!priv->hwts_tx_en)
+#endif /* CONFIG_STMMAC_USE_HWSTAMP */
+ skb_tx_timestamp(skb);
priv->hw->dma->enable_dma_transmission(priv->ioaddr);
@@ -1357,8 +1563,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
(p + entry)->des2 = priv->rx_skbuff_dma[entry];
- if (unlikely(priv->plat->has_gmac))
- priv->hw->ring->refill_desc3(bfsize, p + entry);
+ priv->hw->ring->refill_desc3(priv, p + entry);
RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
}
@@ -1398,9 +1603,22 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
/* read the status of the incoming frame */
status = (priv->hw->desc->rx_status(&priv->dev->stats,
&priv->xstats, p));
- if (unlikely(status == discard_frame))
+ if (unlikely(status == discard_frame)) {
priv->dev->stats.rx_errors++;
- else {
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
+ if (priv->hwts_rx_en) {
+ /* DESC2 & DESC3 will be overwitten by device
+ * with timestamp value, hence reinitialize
+ * them in stmmac_rx_refill() function so that
+ * device can reuse it.
+ */
+ priv->rx_skbuff[entry] = NULL;
+ dma_unmap_single(priv->device,
+ priv->rx_skbuff_dma[entry],
+ priv->dma_buf_sz, DMA_FROM_DEVICE);
+ }
+#endif /* CONFIG_STMMAC_USE_HWSTAMP */
+ } else {
struct sk_buff *skb;
int frame_len;
@@ -1429,6 +1647,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
prefetch(skb->data - NET_IP_ALIGN);
priv->rx_skbuff[entry] = NULL;
+ stmmac_get_rx_hwtstamp(priv, p, skb);
+
skb_put(skb, frame_len);
dma_unmap_single(priv->device,
priv->rx_skbuff_dma[entry],
@@ -1666,21 +1886,30 @@ static void stmmac_poll_controller(struct net_device *dev)
* a proprietary structure used to pass information to the driver.
* @cmd: IOCTL command
* Description:
- * Currently there are no special functionality supported in IOCTL, just the
- * phy_mii_ioctl(...) can be invoked.
+ * Currently it supports just the phy_mii_ioctl(...) and HW time stamping.
*/
static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
- int ret;
+ int ret = -EOPNOTSUPP;
if (!netif_running(dev))
return -EINVAL;
- if (!priv->phydev)
- return -EINVAL;
-
- ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ if (!priv->phydev)
+ return -EINVAL;
+ ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+ break;
+ case SIOCSHWTSTAMP:
+ ret = stmmac_hwtstamp_ioctl(dev, rq);
+ break;
+ default:
+ break;
+ }
return ret;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
new file mode 100644
index 0000000..d557696
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ PTP Header file
+
+ Copyright (C) 2013 Vayavya Labs Pvt Ltd
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+******************************************************************************/
+
+#ifndef __STMMAC_PTP_H__
+#define __STMMAC_PTP_H__
+
+#define STMMAC_SYSCLOCK 62500000
+
+/* IEEE 1588 PTP register offsets */
+#define PTP_TCR 0x0700 /* Timestamp Control Reg */
+#define PTP_SSIR 0x0704 /* Sub-Second Increment Reg */
+#define PTP_STSR 0x0708 /* System Time – Seconds Regr */
+#define PTP_STNSR 0x070C /* System Time – Nanoseconds Reg */
+#define PTP_STSUR 0x0710 /* System Time – Seconds Update Reg */
+#define PTP_STNSUR 0x0714 /* System Time – Nanoseconds Update Reg */
+#define PTP_TAR 0x0718 /* Timestamp Addend Reg */
+#define PTP_TTSR 0x071C /* Target Time Seconds Reg */
+#define PTP_TTNSR 0x0720 /* Target Time Nanoseconds Reg */
+#define PTP_STHWSR 0x0724 /* System Time - Higher Word Seconds Reg */
+#define PTP_TSR 0x0728 /* Timestamp Status */
+
+/* PTP TCR defines */
+#define PTP_TCR_TSENA 0x00000001 /* Timestamp Enable */
+#define PTP_TCR_TSCFUPDT 0x00000002 /* Timestamp Fine/Coarse Update */
+#define PTP_TCR_TSINIT 0x00000004 /* Timestamp Initialize */
+#define PTP_TCR_TSUPDT 0x00000008 /* Timestamp Update */
+/* Timestamp Interrupt Trigger Enable */
+#define PTP_TCR_TSTRIG 0x00000010
+#define PTP_TCR_TSADDREG 0x00000020 /* Addend Reg Update */
+#define PTP_TCR_TSENALL 0x00000100 /* Enable Timestamp for All Frames */
+/* Timestamp Digital or Binary Rollover Control */
+#define PTP_TCR_TSCTRLSSR 0x00000200
+
+/* Enable PTP packet Processing for Version 2 Format */
+#define PTP_TCR_TSVER2ENA 0x00000400
+/* Enable Processing of PTP over Ethernet Frames */
+#define PTP_TCR_TSIPENA 0x00000800
+/* Enable Processing of PTP Frames Sent over IPv6-UDP */
+#define PTP_TCR_TSIPV6ENA 0x00001000
+/* Enable Processing of PTP Frames Sent over IPv4-UDP */
+#define PTP_TCR_TSIPV4ENA 0x00002000
+/* Enable Timestamp Snapshot for Event Messages */
+#define PTP_TCR_TSEVNTENA 0x00004000
+/* Enable Snapshot for Messages Relevant to Master */
+#define PTP_TCR_TSMSTRENA 0x00008000
+/* Select PTP packets for Taking Snapshots */
+#define PTP_TCR_SNAPTYPSEL_1 0x00010000
+/* Enable MAC address for PTP Frame Filtering */
+#define PTP_TCR_TSENMACADDR 0x00040000
+
+#endif /* __STMMAC_PTP_H__ */
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 5/9] stmmac: add IEEE 1588-2008 PTP V2 support
From: Giuseppe CAVALLARO @ 2013-03-07 10:50 UTC (permalink / raw)
To: netdev; +Cc: bh74.an, ayagond, Rayagond Kokatanur
In-Reply-To: <1362653419-1047-1-git-send-email-peppe.cavallaro@st.com>
From: Rayagond Kokatanur <rayagond@vayavyalabs.com>
This patch enhances the stmmac driver to support IEEE 1588-2008 PTP v2
timestamping.
Basic TimeStamps (IEEE 1588-2002 Precision Time Protocol) is selected
by using the STMMAC_USE_HWSTAMP option and at run-time, thanks to
the HW capability register, we verify if the support can be used.
This "basic" TimeStamp support can be used on chips that have the
normal descriptor structures.
To support the IEEE 1588-2008 Precision Time Protocol (Advanced
TimeStamping) the HW has to be the Extended descriptors (DES4-5-6-7)
so this is firtly solved by Kconfig and at runtime all is verified
according to the HW capability register.
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 24 ++-
drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 26 ++-
drivers/net/ethernet/stmicro/stmmac/common.h | 10 +-
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 39 +++--
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 10 +-
drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 3 +-
.../net/ethernet/stmicro/stmmac/stmmac_hwstamp.c | 4 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 192 +++++++++++++++++---
8 files changed, 242 insertions(+), 66 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 4fa974c..cdd63a5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -72,16 +72,32 @@ config STMMAC_CHAINED
endchoice
config STMMAC_USE_HWSTAMP
- bool "Use IEEE 1588 Precision Time Protocol"
+ bool "IEEE 1588-2002 Precision Time Protocol (HW TimeStamping)"
depends on STMMAC_ETH
select PTP_1588_CLOCK
default n
---help---
- Enable this option to support the IEEE 1588 Precision Time Protocol
- (PTP) and HW Timestamps.
+ Enable this option to support the IEEE 1588-2008 Precision Time
+ Protocol (PTP) and HW Timestamps.
+ At runtime, on new chip generations, the hardware capability
+ register will be used to verify if IEEE 1588-2002 is actually
+ supported.
+ This mode can be also supported by chip with normal descriptor
+ structures and w/o Extended descriptors.
+
+config STMMAC_USE_HW_A_STAMP
+ bool "IEEE 1588-2008 Precision Time Protocol (Advanced TimeStamping)"
+ depends on STMMAC_ETH
+ select STMMAC_USE_HWSTAMP
+ select STMMAC_EXTENDED_DESC
+ default n
+ ---help---
+ Enable this option to support the IEEE 1588-2008 Precision Time
+ Protocol (PTP) Advanced HW Timestamps.
At runtime, on new chip generations, the hardware capability
register will be used to verify if either the IEEE 1588-2008 Advanced
- Timestamping (PTPv2) or IEEE 1588-2002 (PTPv1) is actually supported.
+ Timestamping. To support this, it is mandatory to have the extended
+ descriptor support.
config STMMAC_EXTENDED_DESC
bool "Enable Extended descriptors (DES4-5-6-7)"
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index dd60f6b..61e870f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -94,6 +94,7 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
if (priv->hwts_rx_en)
@@ -101,26 +102,29 @@ static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
* 1588-2002 time stamping is enabled, hence reinitialize it
* to keep explicit chaining in the descriptor.
*/
- p->des3 = (unsigned int)(priv->dma_rx +
- ((priv->dirty_rx) + 1) % priv->dma_rx_size);
+ p->des3 = (unsigned int)(priv->dma_rx_phy +
+ (((priv->dirty_rx) + 1) %
+ priv->dma_rx_size) *
+ sizeof(struct dma_desc));
+#endif /* CONFIG_STMMAC_USE_HWSTAMP */
}
static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
{
}
-static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p,
- int tstamp_taken)
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
{
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
- if (tstamp_taken && priv->hw->desc->get_tx_ls(p))
- /* NOTE: Device will overwrite des3 with timestamp value if
- * 1588-2002 time stamping is enabled, hence reinitialize it
- * to keep explicit chaining in the descriptor.
- */
- p->des3 = (unsigned int)(priv->dma_tx +
- ((priv->dirty_tx + 1) % priv->dma_tx_size));
+ if (priv->hwts_tx_en && priv->hw->desc->get_tx_ls(p)
+ && !priv->dma_cap.atime_stamp)
+ p->des3 = (unsigned int)(priv->dma_tx_phy +
+ (((priv->dirty_tx + 1) %
+ priv->dma_tx_size) *
+ sizeof(struct dma_desc)));
+#endif /* CONFIG_STMMAC_USE_HWSTAMP */
}
static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index a10974c..f5965b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -315,16 +315,18 @@ struct stmmac_desc_ops {
/* Return the reception status looking at the RDES1 */
int (*rx_status) (void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, int atds);
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
/* Set tx timestamp enable bit */
void (*enable_tx_timestamp) (struct dma_desc *p);
/* get tx timestamp status */
int (*get_tx_timestamp_status) (struct dma_desc *p);
/* get tx/rx timestamp low value */
- u32 (*get_timestamp_low) (struct dma_desc *p);
+ u32 (*get_timestamp_low) (struct dma_desc *p, u32 ats);
/* get tx/rx timestamp high value */
- u32 (*get_timestamp_high) (struct dma_desc *p);
+ u32 (*get_timestamp_high) (struct dma_desc *p, u32 ats);
/* get rx timestamp status */
- int (*get_rx_timestamp_status) (struct dma_desc *p);
+ int (*get_rx_timestamp_status) (struct dma_desc *p, u32 ats);
+#endif
};
struct stmmac_dma_ops {
@@ -412,7 +414,7 @@ struct stmmac_ring_mode_ops {
void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
unsigned int size);
- void (*clean_desc3) (void *priv, struct dma_desc *p, int tstamp_taken);
+ void (*clean_desc3) (void *priv, struct dma_desc *p);
int (*set_16kib_bfsize) (int mtu);
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index 50707c5..581f82b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -377,6 +377,7 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
return p->des01.erx.frame_length;
}
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
{
p->des01.etx.time_stamp_enable = 1;
@@ -387,27 +388,39 @@ static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
return p->des01.etx.time_stamp_status;
}
-static u32 enh_desc_get_timestamp_low(struct dma_desc *p)
+static u32 enh_desc_get_timestamp_low(struct dma_desc *p, u32 ats)
{
- /* FIXME if Enhance descriptor with 8 DWORDS is enabled */
- return p->des2;
+#ifdef CONFIG_STMMAC_USE_HW_A_STAMP
+ if (ats)
+ return p->des6;
+ else
+#endif /* CONFIG_STMMAC_USE_HW_A_STAMP */
+ return p->des2;
}
-static u32 enh_desc_get_timestamp_high(struct dma_desc *p)
+static u32 enh_desc_get_timestamp_high(struct dma_desc *p, u32 ats)
{
- /* FIXME if Enhance descriptor with 8 DWORDS is enabled */
- return p->des3;
+#ifdef CONFIG_STMMAC_USE_HW_A_STAMP
+ if (ats)
+ return p->des7;
+ else
+#endif /* CONFIG_STMMAC_USE_HW_A_STAMP */
+ return p->des2;
}
-static int enh_desc_get_rx_timestamp_status(struct dma_desc *p)
+static int enh_desc_get_rx_timestamp_status(struct dma_desc *p, u32 ats)
{
- /* FIXME if Enhance descriptor with 8 DWORDS is enabled */
- if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ if (ats)
+ return p->des01.erx.ipc_csum_error;
+ else {
/* timestamp is currupted, hence don't store it */
- return 0;
- else
- return 1;
+ if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ return 0;
+ else
+ return 1;
+ }
}
+#endif /* CONFIG_STMMAC_USE_HWSTAMP */
const struct stmmac_desc_ops enh_desc_ops = {
.tx_status = enh_desc_get_tx_status,
@@ -425,9 +438,11 @@ const struct stmmac_desc_ops enh_desc_ops = {
.set_tx_owner = enh_desc_set_tx_owner,
.set_rx_owner = enh_desc_set_rx_owner,
.get_rx_frame_len = enh_desc_get_rx_frame_len,
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
.enable_tx_timestamp = enh_desc_enable_tx_timestamp,
.get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
.get_timestamp_low = enh_desc_get_timestamp_low,
.get_timestamp_high = enh_desc_get_timestamp_high,
.get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
+#endif
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 9eefb6c..3770942 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -215,6 +215,7 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
return p->des01.rx.frame_length;
}
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
static void ndesc_enable_tx_timestamp(struct dma_desc *p)
{
p->des01.tx.time_stamp_enable = 1;
@@ -225,17 +226,17 @@ static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
return p->des01.tx.time_stamp_status;
}
-static u32 ndesc_get_timestamp_low(struct dma_desc *p)
+static u32 ndesc_get_timestamp_low(struct dma_desc *p, u32 ats)
{
return p->des2;
}
-static u32 ndesc_get_timestamp_high(struct dma_desc *p)
+static u32 ndesc_get_timestamp_high(struct dma_desc *p, u32 ats)
{
return p->des3;
}
-static int ndesc_get_rx_timestamp_status(struct dma_desc *p)
+static int ndesc_get_rx_timestamp_status(struct dma_desc *p, u32 ats)
{
if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
/* timestamp is currupted, hence don't store it */
@@ -243,6 +244,7 @@ static int ndesc_get_rx_timestamp_status(struct dma_desc *p)
else
return 1;
}
+#endif
const struct stmmac_desc_ops ndesc_ops = {
.tx_status = ndesc_get_tx_status,
@@ -260,9 +262,11 @@ const struct stmmac_desc_ops ndesc_ops = {
.set_tx_owner = ndesc_set_tx_owner,
.set_rx_owner = ndesc_set_rx_owner,
.get_rx_frame_len = ndesc_get_rx_frame_len,
+#ifdef CONFIG_STMMAC_USE_HWSTAMP
.enable_tx_timestamp = ndesc_enable_tx_timestamp,
.get_tx_timestamp_status = ndesc_get_tx_timestamp_status,
.get_timestamp_low = ndesc_get_timestamp_low,
.get_timestamp_high = ndesc_get_timestamp_high,
.get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
+#endif
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 94a1c2f..fbcc454 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -108,8 +108,7 @@ static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
{
}
-static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p,
- int tstamp_taken)
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
{
if (unlikely(p->des3))
p->des3 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c
index bec2278..5c71836 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwstamp.c
@@ -48,6 +48,10 @@ static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
else
data = (1000000000ULL / STMMAC_SYSCLOCK);
+ /* 0.465ns accuracy */
+ if (value & PTP_TCR_TSCTRLSSR)
+ data = (data * 100) / 465;
+
writel(data, ioaddr + PTP_SSIR);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 009abf8..ae92191 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -316,38 +316,36 @@ static void stmmac_eee_adjust(struct stmmac_priv *priv)
* Description :
* This function will read timestamp from the descriptor & pass it to stack.
* and also perform some sanity checks.
- * Return value :
- * 1 if time stamp is taken & 0 if time stamp is not taken.
*/
-static unsigned int stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
- struct dma_desc *p,
- struct sk_buff *skb)
+static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
+ struct sk_buff *skb)
{
struct skb_shared_hwtstamps shhwtstamp;
+ u32 ats = priv->dma_cap.atime_stamp;
u64 ns;
if (!priv->hwts_tx_en)
- return 0;
+ return;
/* if skb doesn't support hw tstamp */
if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
- return 0;
+ return;
/* check tx tstamp status */
if (!priv->hw->desc->get_tx_timestamp_status(p))
- return 0;
+ return;
/* get the valid tstamp */
- ns = priv->hw->desc->get_timestamp_low(p);
+ ns = priv->hw->desc->get_timestamp_low(p, ats);
/* convert high/sec time stamp value to nanosecond */
- ns += priv->hw->desc->get_timestamp_high(p) * 1000000000ULL;
+ ns += (priv->hw->desc->get_timestamp_high(p, ats) * 1000000000ULL);
memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
shhwtstamp.hwtstamp = ns_to_ktime(ns);
/* pass tstamp to stack */
skb_tstamp_tx(skb, &shhwtstamp);
- return 1;
+ return;
}
/* stmmac_get_rx_hwtstamp:
@@ -362,19 +360,20 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
struct sk_buff *skb)
{
struct skb_shared_hwtstamps *shhwtstamp = NULL;
+ u32 ats = priv->dma_cap.atime_stamp;
u64 ns;
if (!priv->hwts_rx_en)
return;
/* if rx tstamp is not valid */
- if (!priv->hw->desc->get_rx_timestamp_status(p))
+ if (!priv->hw->desc->get_rx_timestamp_status(p, ats))
return;
/* get valid tstamp */
- ns = priv->hw->desc->get_timestamp_low(p);
+ ns = priv->hw->desc->get_timestamp_low(p, ats);
/* convert high/sec time stamp value to nanosecond */
- ns += priv->hw->desc->get_timestamp_high(p) * 1000000000ULL;
+ ns += (priv->hw->desc->get_timestamp_high(p, ats) * 1000000000ULL);
shhwtstamp = skb_hwtstamps(skb);
memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
shhwtstamp->hwtstamp = ns_to_ktime(ns);
@@ -397,8 +396,17 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
struct hwtstamp_config config;
struct timespec now;
u64 temp = 0;
-
- if (!priv->dma_cap.time_stamp) {
+ u32 ptp_v2 = 0;
+ u32 tstamp_all = 0;
+ u32 ptp_over_ipv4_udp = 0;
+ u32 ptp_over_ipv6_udp = 0;
+ u32 ptp_over_ethernet = 0;
+ u32 snap_type_sel = 0;
+ u32 ts_master_en = 0;
+ u32 ts_event_en = 0;
+ u32 value = 0;
+
+ if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) {
netdev_alert(priv->dev, "No HW time stamping supported\n");
priv->hwts_tx_en = 0;
priv->hwts_rx_en = 0;
@@ -428,22 +436,147 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
return -ERANGE;
}
- switch (config.rx_filter) {
- case HWTSTAMP_FILTER_NONE:
- config.rx_filter = HWTSTAMP_FILTER_NONE;
- break;
- default:
+ if (priv->dma_cap.atime_stamp) {
+ switch (config.rx_filter) {
+ /* time stamp no incoming packet at all */
+ case HWTSTAMP_FILTER_NONE:
+ config.rx_filter = HWTSTAMP_FILTER_NONE;
+ break;
+
/* PTP v1, UDP, any kind of event packet */
- config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
- break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+ /* take time stamp for all event messages */
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ break;
+
+ /* PTP v1, UDP, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
+ /* take time stamp for SYNC messages only */
+ ts_event_en = PTP_TCR_TSEVNTENA;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ break;
+
+ /* PTP v1, UDP, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
+ /* take time stamp for Delay_Req messages only */
+ ts_master_en = PTP_TCR_TSMSTRENA;
+ ts_event_en = PTP_TCR_TSEVNTENA;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ break;
+
+ /* PTP v2, UDP, any kind of event packet */
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+ ptp_v2 = PTP_TCR_TSVER2ENA;
+ /* take time stamp for all event messages */
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ break;
+
+ /* PTP v2, UDP, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
+ ptp_v2 = PTP_TCR_TSVER2ENA;
+ /* take time stamp for SYNC messages only */
+ ts_event_en = PTP_TCR_TSEVNTENA;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ break;
+
+ /* PTP v2, UDP, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
+ ptp_v2 = PTP_TCR_TSVER2ENA;
+ /* take time stamp for Delay_Req messages only */
+ ts_master_en = PTP_TCR_TSMSTRENA;
+ ts_event_en = PTP_TCR_TSEVNTENA;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ break;
+
+ /* PTP v2/802.AS1, any layer, any kind of event packet */
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ ptp_v2 = PTP_TCR_TSVER2ENA;
+ /* take time stamp for all event messages */
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ ptp_over_ethernet = PTP_TCR_TSIPENA;
+ break;
+
+ /* PTP v2/802.AS1, any layer, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
+ ptp_v2 = PTP_TCR_TSVER2ENA;
+ /* take time stamp for SYNC messages only */
+ ts_event_en = PTP_TCR_TSEVNTENA;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ ptp_over_ethernet = PTP_TCR_TSIPENA;
+ break;
+
+ /* PTP v2/802.AS1, any layer, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
+ ptp_v2 = PTP_TCR_TSVER2ENA;
+ /* take time stamp for Delay_Req messages only */
+ ts_master_en = PTP_TCR_TSMSTRENA;
+ ts_event_en = PTP_TCR_TSEVNTENA;
+
+ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+ ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+ ptp_over_ethernet = PTP_TCR_TSIPENA;
+ break;
+
+ /* time stamp any incoming packet */
+ case HWTSTAMP_FILTER_ALL:
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ tstamp_all = PTP_TCR_TSENALL;
+ break;
+
+ default:
+ return -ERANGE;
+ }
+ } else {
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ config.rx_filter = HWTSTAMP_FILTER_NONE;
+ break;
+ default:
+ /* PTP v1, UDP, any kind of event packet */
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+ break;
+ }
}
+
priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
if (!priv->hwts_tx_en && !priv->hwts_rx_en)
priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
else {
- priv->hw->ptp->config_hw_tstamping(priv->ioaddr,
- (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT));
+ value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
+ tstamp_all | ptp_v2 | ptp_over_ethernet |
+ ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
+ ts_master_en | snap_type_sel);
+
+ priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
/* program Sub Second Increment reg */
priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
@@ -454,7 +587,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
* where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
* hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
* NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
- * achive 20ns accuracy.
+ * achive 20ns accuracy.
*
* 2^x * y == (y << x), hence
* 2^32 * 50000000 ==> (50000000 << 32)
@@ -502,7 +635,7 @@ static void stmmac_release_ptp(struct stmmac_priv *priv)
#else
#define stmmac_hwtstamp_ioctl(dev, ifr) (-EOPNOTSUPP)
#define stmmac_get_rx_hwtstamp(priv, p, skb)
-#define stmmac_get_tx_hwtstamp(priv, p, skb) 0
+#define stmmac_get_tx_hwtstamp(priv, p, skb)
#define stmmac_init_ptp(priv) 0
#define stmmac_release_ptp(priv)
#endif /* CONFIG_STMMAC_USE_HWSTAMP */
@@ -915,7 +1048,6 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
while (priv->dirty_tx != priv->cur_tx) {
int last;
- unsigned int ts = 0;
unsigned int entry = priv->dirty_tx % txsize;
struct sk_buff *skb = priv->tx_skbuff[entry];
struct dma_desc *p = priv->dma_tx + entry;
@@ -937,7 +1069,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
} else
priv->dev->stats.tx_errors++;
- ts = stmmac_get_tx_hwtstamp(priv, p, skb);
+ stmmac_get_tx_hwtstamp(priv, p, skb);
}
TX_DBG("%s: curr %d, dirty %d\n", __func__,
priv->cur_tx, priv->dirty_tx);
@@ -949,7 +1081,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
DMA_TO_DEVICE);
priv->tx_skbuff_dma[entry] = 0;
}
- priv->hw->ring->clean_desc3(priv, p, ts);
+ priv->hw->ring->clean_desc3(priv, p);
if (likely(skb != NULL)) {
dev_kfree_skb(skb);
--
1.7.4.4
^ permalink raw reply related
* [PATCH] bgmac: register MII bus
From: Rafał Miłecki @ 2013-03-07 11:42 UTC (permalink / raw)
To: netdev, David S. Miller; +Cc: Rafał Miłecki
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
drivers/net/ethernet/broadcom/bgmac.c | 80 ++++++++++++++++++++++++++++++++-
drivers/net/ethernet/broadcom/bgmac.h | 1 +
2 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index da5f439..e5af5fb 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
+#include <linux/phy.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <bcm47xx_nvram.h>
@@ -1313,6 +1314,73 @@ static const struct ethtool_ops bgmac_ethtool_ops = {
};
/**************************************************
+ * MII
+ **************************************************/
+
+static int bgmac_mii_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ return bgmac_phy_read(bus->priv, mii_id, regnum);
+}
+
+static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum,
+ u16 value)
+{
+ return bgmac_phy_write(bus->priv, mii_id, regnum, value);
+}
+
+static int bgmac_mii_register(struct bgmac *bgmac)
+{
+ struct mii_bus *mii_bus;
+ int i, err = 0;
+
+ mii_bus = mdiobus_alloc();
+ if (!mii_bus)
+ return -ENOMEM;
+
+ mii_bus->name = "bgmac mii bus";
+ sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num,
+ bgmac->core->core_unit);
+ mii_bus->priv = bgmac;
+ mii_bus->read = bgmac_mii_read;
+ mii_bus->write = bgmac_mii_write;
+ mii_bus->parent = &bgmac->core->dev;
+ mii_bus->phy_mask = ~(1 << bgmac->phyaddr);
+
+ mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!mii_bus->irq) {
+ err = -ENOMEM;
+ goto err_free_bus;
+ }
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ mii_bus->irq[i] = PHY_POLL;
+
+ err = mdiobus_register(mii_bus);
+ if (err) {
+ bgmac_err(bgmac, "Registration of mii bus failed\n");
+ goto err_free_irq;
+ }
+
+ bgmac->mii_bus = mii_bus;
+
+ return err;
+
+err_free_irq:
+ kfree(mii_bus->irq);
+err_free_bus:
+ mdiobus_free(mii_bus);
+ return err;
+}
+
+static void bgmac_mii_unregister(struct bgmac *bgmac)
+{
+ struct mii_bus *mii_bus = bgmac->mii_bus;
+
+ mdiobus_unregister(mii_bus);
+ kfree(mii_bus->irq);
+ mdiobus_free(mii_bus);
+}
+
+/**************************************************
* BCMA bus ops
**************************************************/
@@ -1404,11 +1472,18 @@ static int bgmac_probe(struct bcma_device *core)
if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");
+ err = bgmac_mii_register(bgmac);
+ if (err) {
+ bgmac_err(bgmac, "Cannot register MDIO\n");
+ err = -ENOTSUPP;
+ goto err_dma_free;
+ }
+
err = register_netdev(bgmac->net_dev);
if (err) {
bgmac_err(bgmac, "Cannot register net device\n");
err = -ENOTSUPP;
- goto err_dma_free;
+ goto err_mii_unregister;
}
netif_carrier_off(net_dev);
@@ -1417,6 +1492,8 @@ static int bgmac_probe(struct bcma_device *core)
return 0;
+err_mii_unregister:
+ bgmac_mii_unregister(bgmac);
err_dma_free:
bgmac_dma_free(bgmac);
@@ -1433,6 +1510,7 @@ static void bgmac_remove(struct bcma_device *core)
netif_napi_del(&bgmac->napi);
unregister_netdev(bgmac->net_dev);
+ bgmac_mii_unregister(bgmac);
bgmac_dma_free(bgmac);
bcma_set_drvdata(core, NULL);
free_netdev(bgmac->net_dev);
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 4ede614..98d4b5f 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -399,6 +399,7 @@ struct bgmac {
struct bcma_device *cmn; /* Reference to CMN core for BCM4706 */
struct net_device *net_dev;
struct napi_struct napi;
+ struct mii_bus *mii_bus;
/* DMA */
struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS];
--
1.7.10.4
^ permalink raw reply related
* Re: [net 1/3] e1000e: fix pci-device enable-counter balance
From: Jeff Kirsher @ 2013-03-07 11:19 UTC (permalink / raw)
To: davem; +Cc: Konstantin Khlebnikov, netdev, gospo, sassmann, Bruce Allan,
Stable
In-Reply-To: <1362654925-26088-2-git-send-email-jeffrey.t.kirsher@intel.com>
[-- Attachment #1: Type: text/plain, Size: 1470 bytes --]
On Thu, 2013-03-07 at 03:15 -0800, Jeff Kirsher wrote:
> From: Konstantin Khlebnikov <khlebnikov@openvz.org>
>
> This patch removes redundant and unbalanced pci_disable_device() from
> __e1000_shutdown(). pci_clear_master() is enough, device can go into
> suspended state with elevated enable_cnt.
>
> Bug was introduced in commit 23606cf5d1192c2b17912cb2ef6e62f9b11de133
> ("e1000e / PCI / PM: Add basic runtime PM support (rev. 4)") in v2.6.35
>
> Cc: Bruce Allan <bruce.w.allan@intel.com>
CC: stable <stable@vger.kernel.org>
This time with the correct email for stable.
> Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Tested-by: Borislav Petkov <bp@suse.de>
> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
> drivers/net/ethernet/intel/e1000e/netdev.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
> index a177b8b..1799021 100644
> --- a/drivers/net/ethernet/intel/e1000e/netdev.c
> +++ b/drivers/net/ethernet/intel/e1000e/netdev.c
> @@ -5986,7 +5986,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
> */
> e1000e_release_hw_control(adapter);
>
> - pci_disable_device(pdev);
> + pci_clear_master(pdev);
>
> return 0;
> }
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] iputils: fix memory leaks
From: jb @ 2013-03-07 11:18 UTC (permalink / raw)
To: netdev
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B7181@saturn3.aculab.com>
David Laight <David.Laight <at> ACULAB.COM> writes:
>
> > Fix memory leaks
> ...
> > +#ifdef USE_IDN
> > + free(idn);
> > + idn = NULL;
> > +#endif
> > exit(2);
>
> There is no point calling free() before exit(), nor any need
> to free items that aren't allocated inside loops.
>
> David
A matter of good style ? Overzealous ?
Flame ?
http://stackoverflow.com/questions/654754/what-really-happens-when-you-dont-free-after-malloc
jb
^ permalink raw reply
* [net 0/3][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2013-03-07 11:15 UTC (permalink / raw)
To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann, bruce.w.allan
This series contains updates to e1000e only.
All three patches come from Konstantin Khlebnikov to resolve power
management issues. The first patch removes redundant and unbalanced
pci_disable_device() from the shutdown function. The second patch
removes redundant actions from the driver and fixes the interaction
with actions in pci-bus runtime power management code. The third
and last patch fixes some messages like 'Error reading PHY register'
and 'Hardware Erorr' and saves several seconds on reboot.
The following are changes since commit f8af75f3517a24838a36eb5797a1a3e60bf9e276:
tun: add a missing nf_reset() in tun_net_xmit()
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master
Konstantin Khlebnikov (3):
e1000e: fix pci-device enable-counter balance
e1000e: fix runtime power management transitions
e1000e: fix accessing to suspended device
drivers/net/ethernet/intel/e1000e/ethtool.c | 13 +++++
drivers/net/ethernet/intel/e1000e/netdev.c | 82 ++++++++---------------------
2 files changed, 34 insertions(+), 61 deletions(-)
--
1.7.11.7
^ permalink raw reply
* [net 2/3] e1000e: fix runtime power management transitions
From: Jeff Kirsher @ 2013-03-07 11:15 UTC (permalink / raw)
To: davem
Cc: Konstantin Khlebnikov, netdev, gospo, sassmann, Bruce Allan,
Jeff Kirsher
In-Reply-To: <1362654925-26088-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Konstantin Khlebnikov <khlebnikov@openvz.org>
This patch removes redundant actions from driver and fixes its interaction
with actions in pci-bus runtime power management code.
It removes pci_save_state() from __e1000_shutdown() for normal adapters,
PCI bus callbacks pci_pm_*() will do all this for us. Now __e1000_shutdown()
switches to D3-state only quad-port adapters, because they needs quirk for
clearing false-positive error from downsteam pci-e port.
pci_save_state() now called after clearing bus-master bit, thus __e1000_resume()
and e1000_io_slot_reset() must set it back after restoring configuration space.
This patch set get_link_status before calling pm_runtime_put() in e1000_open()
to allow e1000_idle() get real link status and schedule first runtime suspend.
This patch also enables wakeup for device if management mode is enabled
(like for WoL) as result pci_prepare_to_sleep() would setup wakeup without
special actions like custom 'enable_wakeup' sign.
Cc: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Borislav Petkov <bp@suse.de>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/netdev.c | 78 +++++++-----------------------
1 file changed, 18 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 1799021..2954cc7 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4303,6 +4303,7 @@ static int e1000_open(struct net_device *netdev)
netif_start_queue(netdev);
adapter->idle_check = true;
+ hw->mac.get_link_status = true;
pm_runtime_put(&pdev->dev);
/* fire a link status change interrupt to start the watchdog */
@@ -5887,8 +5888,7 @@ release:
return retval;
}
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
- bool runtime)
+static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -5912,10 +5912,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
}
e1000e_reset_interrupt_capability(adapter);
- retval = pci_save_state(pdev);
- if (retval)
- return retval;
-
status = er32(STATUS);
if (status & E1000_STATUS_LU)
wufc &= ~E1000_WUFC_LNKC;
@@ -5971,13 +5967,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
ew32(WUFC, 0);
}
- *enable_wake = !!wufc;
-
- /* make sure adapter isn't asleep if manageability is enabled */
- if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
- (hw->mac.ops.check_mng_mode(hw)))
- *enable_wake = true;
-
if (adapter->hw.phy.type == e1000_phy_igp_3)
e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
@@ -5988,26 +5977,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
pci_clear_master(pdev);
- return 0;
-}
-
-static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake)
-{
- if (sleep && wake) {
- pci_prepare_to_sleep(pdev);
- return;
- }
-
- pci_wake_from_d3(pdev, wake);
- pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
- bool wake)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev_priv(netdev);
-
/* The pci-e switch on some quad port adapters will report a
* correctable error when the MAC transitions from D0 to D3. To
* prevent this we need to mask off the correctable errors on the
@@ -6021,12 +5990,13 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL,
(devctl & ~PCI_EXP_DEVCTL_CERE));
- e1000_power_off(pdev, sleep, wake);
+ pci_save_state(pdev);
+ pci_prepare_to_sleep(pdev);
pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl);
- } else {
- e1000_power_off(pdev, sleep, wake);
}
+
+ return 0;
}
#ifdef CONFIG_PCIEASPM
@@ -6084,9 +6054,7 @@ static int __e1000_resume(struct pci_dev *pdev)
if (aspm_disable_flag)
e1000e_disable_aspm(pdev, aspm_disable_flag);
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- pci_save_state(pdev);
+ pci_set_master(pdev);
e1000e_set_interrupt_capability(adapter);
if (netif_running(netdev)) {
@@ -6152,14 +6120,8 @@ static int __e1000_resume(struct pci_dev *pdev)
static int e1000_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
- int retval;
- bool wake;
-
- retval = __e1000_shutdown(pdev, &wake, false);
- if (!retval)
- e1000_complete_shutdown(pdev, true, wake);
- return retval;
+ return __e1000_shutdown(pdev, false);
}
static int e1000_resume(struct device *dev)
@@ -6182,13 +6144,10 @@ static int e1000_runtime_suspend(struct device *dev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- if (e1000e_pm_ready(adapter)) {
- bool wake;
-
- __e1000_shutdown(pdev, &wake, true);
- }
+ if (!e1000e_pm_ready(adapter))
+ return 0;
- return 0;
+ return __e1000_shutdown(pdev, true);
}
static int e1000_idle(struct device *dev)
@@ -6226,12 +6185,7 @@ static int e1000_runtime_resume(struct device *dev)
static void e1000_shutdown(struct pci_dev *pdev)
{
- bool wake = false;
-
- __e1000_shutdown(pdev, &wake, false);
-
- if (system_state == SYSTEM_POWER_OFF)
- e1000_complete_shutdown(pdev, false, wake);
+ __e1000_shutdown(pdev, false);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -6352,9 +6306,9 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
"Cannot re-enable PCI device after reset.\n");
result = PCI_ERS_RESULT_DISCONNECT;
} else {
- pci_set_master(pdev);
pdev->state_saved = true;
pci_restore_state(pdev);
+ pci_set_master(pdev);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -6783,7 +6737,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
- device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+ /* make sure adapter isn't asleep if manageability is enabled */
+ if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) ||
+ (hw->mac.ops.check_mng_mode(hw)))
+ device_wakeup_enable(&pdev->dev);
/* save off EEPROM version number */
e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
--
1.7.11.7
^ permalink raw reply related
* [net 3/3] e1000e: fix accessing to suspended device
From: Jeff Kirsher @ 2013-03-07 11:15 UTC (permalink / raw)
To: davem
Cc: Konstantin Khlebnikov, netdev, gospo, sassmann, Bruce Allan,
Jeff Kirsher
In-Reply-To: <1362654925-26088-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Konstantin Khlebnikov <khlebnikov@openvz.org>
This patch fixes some annoying messages like 'Error reading PHY register' and
'Hardware Erorr' and saves several seconds on reboot.
Cc: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Borislav Petkov <bp@suse.de>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/ethtool.c | 13 +++++++++++++
drivers/net/ethernet/intel/e1000e/netdev.c | 2 ++
2 files changed, 15 insertions(+)
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 2c18137..f91a8f3 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/mdio.h>
+#include <linux/pm_runtime.h>
#include "e1000.h"
@@ -2229,7 +2230,19 @@ static int e1000e_get_ts_info(struct net_device *netdev,
return 0;
}
+static int e1000e_ethtool_begin(struct net_device *netdev)
+{
+ return pm_runtime_get_sync(netdev->dev.parent);
+}
+
+static void e1000e_ethtool_complete(struct net_device *netdev)
+{
+ pm_runtime_put_sync(netdev->dev.parent);
+}
+
static const struct ethtool_ops e1000_ethtool_ops = {
+ .begin = e1000e_ethtool_begin,
+ .complete = e1000e_ethtool_complete,
.get_settings = e1000_get_settings,
.set_settings = e1000_set_settings,
.get_drvinfo = e1000_get_drvinfo,
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 2954cc7..948b86ff 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4663,6 +4663,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
(adapter->hw.phy.media_type == e1000_media_type_copper)) {
int ret_val;
+ pm_runtime_get_sync(&adapter->pdev->dev);
ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr);
ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr);
ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise);
@@ -4673,6 +4674,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus);
if (ret_val)
e_warn("Error reading PHY register\n");
+ pm_runtime_put_sync(&adapter->pdev->dev);
} else {
/* Do not read PHY registers if link is not up
* Set values to typical power-on defaults
--
1.7.11.7
^ permalink raw reply related
* [net 1/3] e1000e: fix pci-device enable-counter balance
From: Jeff Kirsher @ 2013-03-07 11:15 UTC (permalink / raw)
To: davem
Cc: Konstantin Khlebnikov, netdev, gospo, sassmann, Bruce Allan,
Stable, Jeff Kirsher
In-Reply-To: <1362654925-26088-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Konstantin Khlebnikov <khlebnikov@openvz.org>
This patch removes redundant and unbalanced pci_disable_device() from
__e1000_shutdown(). pci_clear_master() is enough, device can go into
suspended state with elevated enable_cnt.
Bug was introduced in commit 23606cf5d1192c2b17912cb2ef6e62f9b11de133
("e1000e / PCI / PM: Add basic runtime PM support (rev. 4)") in v2.6.35
Cc: Bruce Allan <bruce.w.allan@intel.com>
CC: Stable <stable@kernel.org>
Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Borislav Petkov <bp@suse.de>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/netdev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index a177b8b..1799021 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5986,7 +5986,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
*/
e1000e_release_hw_control(adapter);
- pci_disable_device(pdev);
+ pci_clear_master(pdev);
return 0;
}
--
1.7.11.7
^ permalink raw reply related
* Re: BCM5709 hang and state dump...
From: Michael Chan @ 2013-03-07 11:00 UTC (permalink / raw)
To: Daniel J Blueman; +Cc: Eilon Greenstein, Steffen Persvold, netdev
In-Reply-To: <51386B82.5050900@numascale-asia.com>
On Thu, 2013-03-07 at 18:27 +0800, Daniel J Blueman wrote:
> We've hit this again [1], with 3.8.0 this time. Any success on the debug
> patches?
I have 2 suggestions at this point:
1. Some users who report similar issues say that upgrading the BIOS has
fixed the issue. So please try upgarding the BIOS if possible.
2. You can also disable MSIX and see if it runs any better. Use sysfs
to do that or simply use bnx2 parameter disable_msi=1.
I suspect that some MSIX IRQ messages are not delivered to the CPU for
some reason. Please try one or both suggestions and let me know.
Thanks.
>
>
^ permalink raw reply
* [PATCH 3/3] netfilter: nfnetlink: silence warning if CONFIG_PROVE_RCU isn't set
From: pablo @ 2013-03-07 11:00 UTC (permalink / raw)
To: netdev; +Cc: davem, netfilter-devel
In-Reply-To: <1362654002-4405-1-git-send-email-pablo@netfilter.org>
From: Paul Bolle <pebolle@tiscali.nl>
Since commit c14b78e7decd0d1d5add6a4604feb8609fe920a9 ("netfilter:
nfnetlink: add mutex per subsystem") building nefnetlink.o without
CONFIG_PROVE_RCU set, triggers this GCC warning:
net/netfilter/nfnetlink.c:65:22: warning: ‘nfnl_get_lock’ defined but not used [-Wunused-function]
The cause of that warning is, in short, that rcu_lockdep_assert()
compiles away if CONFIG_PROVE_RCU is not set. Silence this warning by
open coding nfnl_get_lock() in the sole place it was called, which
allows to remove that function.
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nfnetlink.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index d578ec2..0b1b32c 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -62,11 +62,6 @@ void nfnl_unlock(__u8 subsys_id)
}
EXPORT_SYMBOL_GPL(nfnl_unlock);
-static struct mutex *nfnl_get_lock(__u8 subsys_id)
-{
- return &table[subsys_id].mutex;
-}
-
int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
{
nfnl_lock(n->subsys_id);
@@ -199,7 +194,7 @@ replay:
rcu_read_unlock();
nfnl_lock(subsys_id);
if (rcu_dereference_protected(table[subsys_id].subsys,
- lockdep_is_held(nfnl_get_lock(subsys_id))) != ss ||
+ lockdep_is_held(&table[subsys_id].mutex)) != ss ||
nfnetlink_find_client(type, ss) != nc)
err = -EAGAIN;
else if (nc->call)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/3] netfilter: xt_AUDIT: only generate audit log when audit enabled
From: pablo @ 2013-03-07 11:00 UTC (permalink / raw)
To: netdev; +Cc: davem, netfilter-devel
In-Reply-To: <1362654002-4405-1-git-send-email-pablo@netfilter.org>
From: Gao feng <gaofeng@cn.fujitsu.com>
We should stop generting audit log if audit is disabled.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/xt_AUDIT.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index ba92824..3228d7f 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -124,6 +124,9 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
const struct xt_audit_info *info = par->targinfo;
struct audit_buffer *ab;
+ if (audit_enabled == 0)
+ goto errout;
+
ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
if (ab == NULL)
goto errout;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/3] netfilter: nf_ct_helper: Fix logging for dropped packets
From: pablo @ 2013-03-07 11:00 UTC (permalink / raw)
To: netdev; +Cc: davem, netfilter-devel
In-Reply-To: <1362654002-4405-1-git-send-email-pablo@netfilter.org>
From: Joe Perches <joe@perches.com>
Update nf_ct_helper_log to emit args along with the format.
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_helper.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 013cdf6..bb4188f 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -341,6 +341,13 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
{
const struct nf_conn_help *help;
const struct nf_conntrack_helper *helper;
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
/* Called from the helper function, this call never fails */
help = nfct_help(ct);
@@ -349,7 +356,9 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
helper = rcu_dereference(help->helper);
nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL,
- "nf_ct_%s: dropping packet: %s ", helper->name, fmt);
+ "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf);
+
+ va_end(args);
}
EXPORT_SYMBOL_GPL(nf_ct_helper_log);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/3] netfilter fixes for your net tree
From: pablo @ 2013-03-07 10:59 UTC (permalink / raw)
To: netdev; +Cc: davem, netfilter-devel
From: Pablo Neira Ayuso <pablo@netfilter.org>
Hi David,
The following patchset contains Netfilter fixes for your net tree,
they are:
* Don't generate audit log message if audit is not enabled, from Gao Feng.
* Fix logging formatting for packets dropped by helpers, by Joe Perches.
* Fix a compilation warning in nfnetlink if CONFIG_PROVE_RCU is not set,
from Paul Bolle.
You can pull these changes from:
git://1984.lsi.us.es/nf master
Thanks!
Gao feng (1):
netfilter: xt_AUDIT: only generate audit log when audit enabled
Joe Perches (1):
netfilter: nf_ct_helper: Fix logging for dropped packets
Paul Bolle (1):
netfilter: nfnetlink: silence warning if CONFIG_PROVE_RCU isn't set
net/netfilter/nf_conntrack_helper.c | 11 ++++++++++-
net/netfilter/nfnetlink.c | 7 +------
net/netfilter/xt_AUDIT.c | 3 +++
3 files changed, 14 insertions(+), 7 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [net-next.git 8/9] stmmac: initial support to manage pcs modes
From: Giuseppe CAVALLARO @ 2013-03-07 10:50 UTC (permalink / raw)
To: netdev; +Cc: bh74.an, ayagond, Giuseppe Cavallaro
In-Reply-To: <1362653419-1047-1-git-send-email-peppe.cavallaro@st.com>
This patch adds the minimal support to manage the PCS
modes (RGMII/SGMII) and restart the ANE.
Both TBI and RTBI are not yet supported.
Thanks to Byungho that wrote some part of this code
and tested SGMII too.
The only thing to be fixed is the get/set pause in
ethtool.
Signed-off-by: Byungho An <bh74.an@samsung.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 21 +++++
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 34 +++++++
.../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 64 +++++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 94 ++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 59 ++++++++++---
6 files changed, 257 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 42e2a87..a9f8e77 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -121,6 +121,9 @@ struct stmmac_extra_stats {
unsigned long irq_pcs_ane_n;
unsigned long irq_pcs_link_n;
unsigned long irq_rgmii_n;
+ unsigned long pcs_link;
+ unsigned long pcs_duplex;
+ unsigned long pcs_speed;
#ifdef CONFIG_STMMAC_EXTENDED_DESC
/* Extended RDES status */
unsigned long ip_hdr_err;
@@ -167,6 +170,12 @@ struct stmmac_extra_stats {
#define FLOW_TX 2
#define FLOW_AUTO (FLOW_TX | FLOW_RX)
+/* PCS defines */
+#define STMMAC_PCS_RGMII (1 << 0)
+#define STMMAC_PCS_SGMII (1 << 1)
+#define STMMAC_PCS_TBI (1 << 2)
+#define STMMAC_PCS_RTBI (1 << 3)
+
#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
/* DAM HW feature register fields */
@@ -232,6 +241,16 @@ enum dma_irq_status {
#define CORE_PCS_LINK_STATUS (1 << 6)
#define CORE_RGMII_IRQ (1 << 7)
+struct rgmii_adv {
+ unsigned int pause;
+ unsigned int duplex;
+ unsigned int lp_pause;
+ unsigned int lp_duplex;
+};
+
+#define STMMAC_PCS_PAUSE 1
+#define STMMAC_PCS_ASYM_PAUSE 2
+
/* DMA HW capabilities */
struct dma_features {
unsigned int mbps_10_100;
@@ -384,6 +403,8 @@ struct stmmac_ops {
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);
+ void (*ctrl_ane) (void __iomem *ioaddr, bool restart);
+ void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
};
#ifdef CONFIG_STMMAC_USE_HWSTAMP
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 6dd689e..57f4e8f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -98,6 +98,38 @@ enum power_event {
#define GMAC_TBI 0x000000d4 /* TBI extend status */
#define GMAC_S_R_GMII 0x000000d8 /* SGMII RGMII status */
+/* AN Configuration defines */
+#define GMAC_AN_CTRL_RAN 0x00000200 /* Restart Auto-Negotiation */
+#define GMAC_AN_CTRL_ANE 0x00001000 /* Auto-Negotiation Enable */
+#define GMAC_AN_CTRL_ELE 0x00004000 /* External Loopback Enable */
+#define GMAC_AN_CTRL_ECD 0x00010000 /* Enable Comma Detect */
+#define GMAC_AN_CTRL_LR 0x00020000 /* Lock to Reference */
+#define GMAC_AN_CTRL_SGMRAL 0x00040000 /* SGMII RAL Control */
+
+/* AN Status defines */
+#define GMAC_AN_STATUS_LS 0x00000004 /* Link Status 0:down 1:up */
+#define GMAC_AN_STATUS_ANA 0x00000008 /* Auto-Negotiation Ability */
+#define GMAC_AN_STATUS_ANC 0x00000020 /* Auto-Negotiation Complete */
+#define GMAC_AN_STATUS_ES 0x00000100 /* Extended Status */
+
+/* Register 54 (SGMII/RGMII status register) */
+#define GMAC_S_R_GMII_LINK 0x8
+#define GMAC_S_R_GMII_SPEED 0x5
+#define GMAC_S_R_GMII_SPEED_SHIFT 0x1
+#define GMAC_S_R_GMII_MODE 0x1
+#define GMAC_S_R_GMII_SPEED_125 2
+#define GMAC_S_R_GMII_SPEED_25 1
+
+/* Common ADV and LPA defines */
+#define GMAC_ANE_FD (1 << 5)
+#define GMAC_ANE_HD (1 << 6)
+#define GMAC_ANE_PSE (3 << 7)
+#define GMAC_ANE_PSE_SHIFT 7
+
+ /* GMAC Configuration defines */
+#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */
+#define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */
+
/* GMAC Configuration defines */
#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */
#define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */
@@ -232,5 +264,7 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
+
+
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index ff4c79e..29138da 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -28,6 +28,7 @@
#include <linux/crc32.h>
#include <linux/slab.h>
+#include <linux/ethtool.h>
#include <asm/io.h>
#include "dwmac1000.h"
@@ -193,7 +194,6 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
writel(pmt, ioaddr + GMAC_PMT);
}
-
static int dwmac1000_irq_status(void __iomem *ioaddr,
struct stmmac_extra_stats *x)
{
@@ -252,9 +252,30 @@ static int dwmac1000_irq_status(void __iomem *ioaddr,
x->irq_pcs_ane_n++;
}
if (intr_status & rgmii_irq) {
- CHIP_DBG(KERN_INFO "GMAC RGMII IRQ status\n");
- readl(ioaddr + GMAC_S_R_GMII);
+ u32 status = readl(ioaddr + GMAC_S_R_GMII);
+ CHIP_DBG(KERN_INFO "GMAC RGMII/SGMII interrupt\n");
x->irq_rgmii_n++;
+
+ /* Save and dump the link status. */
+ if (status & GMAC_S_R_GMII_LINK) {
+ int speed_value = (status & GMAC_S_R_GMII_SPEED) >>
+ GMAC_S_R_GMII_SPEED_SHIFT;
+ x->pcs_duplex = (status & GMAC_S_R_GMII_MODE);
+
+ if (speed_value == GMAC_S_R_GMII_SPEED_125)
+ x->pcs_speed = SPEED_1000;
+ else if (speed_value == GMAC_S_R_GMII_SPEED_25)
+ x->pcs_speed = SPEED_100;
+ else
+ x->pcs_speed = SPEED_10;
+
+ x->pcs_link = 1;
+ pr_debug("Link is Up - %d/%s\n", (int) x->pcs_speed,
+ x->pcs_duplex ? "Full" : "Half");
+ } else {
+ x->pcs_link = 0;
+ pr_debug("Link is Down\n");
+ }
}
return ret;
@@ -309,6 +330,41 @@ static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
writel(value, ioaddr + LPI_TIMER_CTRL);
}
+static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
+{
+ u32 value;
+
+ value = readl(ioaddr + GMAC_AN_CTRL);
+ /* auto negotiation enable and External Loopback enable */
+ value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;
+
+ if (restart)
+ value |= GMAC_AN_CTRL_RAN;
+
+ writel(value, ioaddr + GMAC_AN_CTRL);
+}
+
+static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv)
+{
+ u32 value = readl(ioaddr + GMAC_ANE_ADV);
+
+ if (value & GMAC_ANE_FD)
+ adv->duplex = DUPLEX_FULL;
+ if (value & GMAC_ANE_HD)
+ adv->duplex |= DUPLEX_HALF;
+
+ adv->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
+
+ value = readl(ioaddr + GMAC_ANE_LPA);
+
+ if (value & GMAC_ANE_FD)
+ adv->lp_duplex = DUPLEX_FULL;
+ if (value & GMAC_ANE_HD)
+ adv->lp_duplex = DUPLEX_HALF;
+
+ adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
+}
+
static const struct stmmac_ops dwmac1000_ops = {
.core_init = dwmac1000_core_init,
.rx_ipc = dwmac1000_rx_ipc_enable,
@@ -323,6 +379,8 @@ static const struct stmmac_ops dwmac1000_ops = {
.reset_eee_mode = dwmac1000_reset_eee_mode,
.set_eee_timer = dwmac1000_set_eee_timer,
.set_eee_pls = dwmac1000_set_eee_pls,
+ .ctrl_ane = dwmac1000_ctrl_ane,
+ .get_adv = dwmac1000_get_adv,
};
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a9a10dd..200011d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -99,6 +99,7 @@ struct stmmac_priv {
u32 tx_coal_timer;
int use_riwt;
u32 rx_riwt;
+ int pcs;
#ifdef CONFIG_STMMAC_USE_HWSTAMP
int hwts_tx_en;
int hwts_rx_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index d78234e..f5cc5ce 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -247,6 +247,70 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
struct stmmac_priv *priv = netdev_priv(dev);
struct phy_device *phy = priv->phydev;
int rc;
+
+ if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
+ struct rgmii_adv adv;
+
+ if (!priv->xstats.pcs_link) {
+ ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+ cmd->duplex = DUPLEX_UNKNOWN;
+ return 0;
+ }
+ cmd->duplex = priv->xstats.pcs_duplex;
+
+ ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed);
+
+ /* Get and convert ADV/LP_ADV from the HW AN registers */
+ if (priv->hw->mac->get_adv)
+ priv->hw->mac->get_adv(priv->ioaddr, &adv);
+ else
+ return -EOPNOTSUPP; /* should never happen indeed */
+
+ /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */
+
+ if (adv.pause & STMMAC_PCS_PAUSE)
+ cmd->advertising |= ADVERTISED_Pause;
+ if (adv.pause & STMMAC_PCS_ASYM_PAUSE)
+ cmd->advertising |= ADVERTISED_Asym_Pause;
+ if (adv.lp_pause & STMMAC_PCS_PAUSE)
+ cmd->lp_advertising |= ADVERTISED_Pause;
+ if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE)
+ cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+
+ /* Reg49[3] always set because ANE is always supported */
+ cmd->autoneg = ADVERTISED_Autoneg;
+ cmd->supported |= SUPPORTED_Autoneg;
+ cmd->advertising |= ADVERTISED_Autoneg;
+ cmd->lp_advertising |= ADVERTISED_Autoneg;
+
+ if (adv.duplex) {
+ cmd->supported |= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_10baseT_Full);
+ cmd->advertising |= (ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Full);
+ } else {
+ cmd->supported |= (SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Half);
+ cmd->advertising |= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Half);
+ }
+ if (adv.lp_duplex)
+ cmd->lp_advertising |= (ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Full);
+ else
+ cmd->lp_advertising |= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Half);
+ cmd->port = PORT_OTHER;
+
+ return 0;
+ }
+
if (phy == NULL) {
pr_err("%s: %s: PHY is not registered\n",
__func__, dev->name);
@@ -271,6 +335,30 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
struct phy_device *phy = priv->phydev;
int rc;
+ if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
+ u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
+
+ /* Only support ANE */
+ if (cmd->autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ mask &= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full);
+
+ spin_lock(&priv->lock);
+ if (priv->hw->mac->ctrl_ane)
+ priv->hw->mac->ctrl_ane(priv->ioaddr, 1);
+ spin_unlock(&priv->lock);
+ }
+
+ return 0;
+ }
+
spin_lock(&priv->lock);
rc = phy_ethtool_sset(phy, cmd);
spin_unlock(&priv->lock);
@@ -340,6 +428,9 @@ stmmac_get_pauseparam(struct net_device *netdev,
{
struct stmmac_priv *priv = netdev_priv(netdev);
+ if (priv->pcs) /* FIXME */
+ return;
+
spin_lock(&priv->lock);
pause->rx_pause = 0;
@@ -363,6 +454,9 @@ stmmac_set_pauseparam(struct net_device *netdev,
int new_pause = FLOW_OFF;
int ret = 0;
+ if (priv->pcs) /* FIXME */
+ return -EOPNOTSUPP;
+
spin_lock(&priv->lock);
if (pause->rx_pause)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 7d2ee6f..a25b54c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -733,6 +733,24 @@ static void stmmac_adjust_link(struct net_device *dev)
DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
}
+static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
+{
+ int interface = priv->plat->interface;
+
+ if (priv->dma_cap.pcs) {
+ if ((interface & PHY_INTERFACE_MODE_RGMII) ||
+ (interface & PHY_INTERFACE_MODE_RGMII_ID) ||
+ (interface & PHY_INTERFACE_MODE_RGMII_RXID) ||
+ (interface & PHY_INTERFACE_MODE_RGMII_TXID)) {
+ pr_debug("STMMAC: PCS RGMII support enable\n");
+ priv->pcs = STMMAC_PCS_RGMII;
+ } else if (interface & PHY_INTERFACE_MODE_SGMII) {
+ pr_debug("STMMAC: PCS SGMII support enable\n");
+ priv->pcs = STMMAC_PCS_SGMII;
+ }
+ }
+}
+
/**
* stmmac_init_phy - PHY initialization
* @dev: net device structure
@@ -1372,13 +1390,15 @@ static int stmmac_open(struct net_device *dev)
stmmac_check_ether_addr(priv);
- ret = stmmac_init_phy(dev);
- if (unlikely(ret)) {
- pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
- goto open_error;
+ if (!priv->pcs) {
+ ret = stmmac_init_phy(dev);
+ if (unlikely(ret)) {
+ pr_err("%s: Cannot attach to PHY (error: %d)\n",
+ __func__, ret);
+ goto open_error;
+ }
}
-
/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
@@ -1469,7 +1489,12 @@ static int stmmac_open(struct net_device *dev)
phy_start(priv->phydev);
priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
- priv->eee_enabled = stmmac_eee_init(priv);
+
+ /* Using PCS we cannot dial with the phy registers at this stage
+ * so we do not support extra feature like EEE.
+ */
+ if (!priv->pcs)
+ priv->eee_enabled = stmmac_eee_init(priv);
stmmac_init_tx_coalesce(priv);
@@ -1478,6 +1503,9 @@ static int stmmac_open(struct net_device *dev)
priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
}
+ if (priv->pcs && priv->hw->mac->ctrl_ane)
+ priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+
napi_enable(&priv->napi);
netif_start_queue(dev);
@@ -2437,12 +2465,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
else
priv->clk_csr = priv->plat->clk_csr;
- /* MDIO bus Registration */
- ret = stmmac_mdio_register(ndev);
- if (ret < 0) {
- pr_debug("%s: MDIO bus (id: %d) registration failed",
- __func__, priv->plat->bus_id);
- goto error_mdio_register;
+ stmmac_check_pcs_mode(priv);
+
+ if (!priv->pcs) {
+ /* MDIO bus Registration */
+ ret = stmmac_mdio_register(ndev);
+ if (ret < 0) {
+ pr_debug("%s: MDIO bus (id: %d) registration failed",
+ __func__, priv->plat->bus_id);
+ goto error_mdio_register;
+ }
}
return priv;
@@ -2475,7 +2507,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
priv->hw->dma->stop_tx(priv->ioaddr);
stmmac_set_mac(priv->ioaddr, false);
- stmmac_mdio_unregister(ndev);
+ if (!priv->pcs)
+ stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
free_netdev(ndev);
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 9/9] stmmac: update the Doc and Version (PTP+SGMII)
From: Giuseppe CAVALLARO @ 2013-03-07 10:50 UTC (permalink / raw)
To: netdev; +Cc: bh74.an, ayagond, Giuseppe Cavallaro
In-Reply-To: <1362653419-1047-1-git-send-email-peppe.cavallaro@st.com>
This patch updates the stmmac.txt file adding
information related to the PTP and SGMII/RGMII
supports.
Also the patch updates the driver version to:
March_2013.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
Documentation/networking/stmmac.txt | 39 ++++++++++++++++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +-
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index f9fa6db..f7d8c3d 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -326,6 +326,41 @@ 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:
+7) Extended descriptors
+The CONFIG_STMMAC_EXTENDED_DESC option can be enabled to use the
+the extended status in the descriptors. For RDESC, that gives some
+information about the receive Ethernet payload when it is carrying PTP
+packets or TCP/UDP/ICMP over IP.
+This option cannot be used on GMAC Synopsys older than the 3.50
+so the driver's probe will fail in this scenario.
+This option also is mandatory for PTPv2 because the extra descriptors
+are used for saving the hardware timestamps.
+
+8) Precision Time Protocol (PTP)
+The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP),
+which enables precise synchronization of clocks in measurement and
+control systems implemented with technologies such as network
+communication.
+This is the Kernel option to enable it: CONFIG_STMMAC_USE_HWSTAMP
+
+In addition to the basic timestamp features mentioned in IEEE 1588-2002
+Timestamps, new GMAC cores support the advanced timestamp features.
+IEEE 1588-2008 that can be enabled when configure the Kernel. This is
+its option: CONFIG_STMMAC_USE_HW_A_STAMP
+To use this support the HW has to have the extended descriptors.
+At run time this will be verified by looking at the HW capability
+register.
+
+9) SGMII/RGMII supports
+New GMAC devices provide own way to manage RGMII/SGMII.
+This information is available at run-time by looking at the
+HW capability register. This means that the stmmac can manage
+auto-negotiation and link status w/o using the PHYLIB stuff
+In fact, the HW provides a subset of extended registers to
+restart the ANE, verify Full/Half duplex mode and Speed.
+Also thanks to these registers it is possible to look at the
+Auto-negotiated Link Parter Ability.
+
+10) TODO:
o XGMAC is not supported.
- o Add the PTP - precision time protocol
+ o Complete the TBI & RTBI support.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 200011d..78bc4d1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -24,7 +24,7 @@
#define __STMMAC_H__
#define STMMAC_RESOURCE_NAME "stmmaceth"
-#define DRV_MODULE_VERSION "Nov_2012"
+#define DRV_MODULE_VERSION "March_2013"
#include <linux/clk.h>
#include <linux/stmmac.h>
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 7/9] stmmac: start adding pcs and rgmii core irq
From: Giuseppe CAVALLARO @ 2013-03-07 10:50 UTC (permalink / raw)
To: netdev; +Cc: bh74.an, ayagond, Giuseppe Cavallaro, Udit Kumar
In-Reply-To: <1362653419-1047-1-git-send-email-peppe.cavallaro@st.com>
This patch starts adding in the main ISR the management of the PCS and
RGMII/SGMII core interrupts. This is to help further development
on this area. Currently the core irq handler only clears the
PCS and S-R_MII interrupts and reports the event in the ethtool stats.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Tested-by: Byungho An <bh74.an@samsung.com>
Cc: Udit Kumar <udit-dlh.kumar@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 25 ++++++-----
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 5 +-
.../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 44 ++++++++++++-------
.../net/ethernet/stmicro/stmmac/dwmac100_core.c | 3 +-
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 3 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 24 ++---------
6 files changed, 54 insertions(+), 50 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index f5965b6..42e2a87 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -117,6 +117,10 @@ struct stmmac_extra_stats {
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;
+ /* PCS */
+ unsigned long irq_pcs_ane_n;
+ unsigned long irq_pcs_link_n;
+ unsigned long irq_rgmii_n;
#ifdef CONFIG_STMMAC_EXTENDED_DESC
/* Extended RDES status */
unsigned long ip_hdr_err;
@@ -219,16 +223,14 @@ enum dma_irq_status {
handle_tx = 0x8,
};
-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,
-};
+#define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 1)
+#define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 2)
+#define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 3)
+#define CORE_IRQ_RX_PATH_EXIT_LPI_MODE (1 << 4)
+
+#define CORE_PCS_ANE_COMPLETE (1 << 5)
+#define CORE_PCS_LINK_STATUS (1 << 6)
+#define CORE_RGMII_IRQ (1 << 7)
/* DMA HW capabilities */
struct dma_features {
@@ -364,7 +366,8 @@ struct stmmac_ops {
/* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */
- int (*host_irq_status) (void __iomem *ioaddr);
+ int (*host_irq_status) (void __iomem *ioaddr,
+ struct stmmac_extra_stats *x);
/* Multicast filter setting */
void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 85466e5..6dd689e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -89,13 +89,14 @@ enum power_event {
(reg * 8))
#define GMAC_MAX_PERFECT_ADDRESSES 32
+/* PCS registers (AN/TBI/SGMII/RGMII) offset */
#define GMAC_AN_CTRL 0x000000c0 /* AN control */
#define GMAC_AN_STATUS 0x000000c4 /* AN status */
#define GMAC_ANE_ADV 0x000000c8 /* Auto-Neg. Advertisement */
-#define GMAC_ANE_LINK 0x000000cc /* Auto-Neg. link partener ability */
+#define GMAC_ANE_LPA 0x000000cc /* Auto-Neg. link partener ability */
#define GMAC_ANE_EXP 0x000000d0 /* ANE expansion */
#define GMAC_TBI 0x000000d4 /* TBI extend status */
-#define GMAC_GMII_STATUS 0x000000d8 /* S/R-GMII status */
+#define GMAC_S_R_GMII 0x000000d8 /* SGMII RGMII status */
/* GMAC Configuration defines */
#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index bfe0226..ff4c79e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -194,58 +194,70 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
}
-static int dwmac1000_irq_status(void __iomem *ioaddr)
+static int dwmac1000_irq_status(void __iomem *ioaddr,
+ struct stmmac_extra_stats *x)
{
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
- int status = 0;
+ int ret = 0;
/* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_TX_INTR));
- status |= core_mmc_tx_irq;
+ x->mmc_tx_irq_n++;
}
if (unlikely(intr_status & mmc_rx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_INTR));
- status |= core_mmc_rx_irq;
+ x->mmc_rx_irq_n++;
}
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;
+ x->mmc_rx_csum_offload_irq_n++;
}
if (unlikely(intr_status & pmt_irq)) {
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;
+ x->irq_receive_pmt_irq_n++;
}
/* 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);
+ ret = readl(ioaddr + LPI_CTRL_STATUS);
- if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
+ if (ret & LPI_CTRL_STATUS_TLPIEN) {
CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
- status |= core_irq_tx_path_in_lpi_mode;
+ x->irq_tx_path_in_lpi_mode_n++;
}
- if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
+ if (ret & LPI_CTRL_STATUS_TLPIEX) {
CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
- status |= core_irq_tx_path_exit_lpi_mode;
+ x->irq_tx_path_exit_lpi_mode_n++;
}
- if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
+ if (ret & LPI_CTRL_STATUS_RLPIEN) {
CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
- status |= core_irq_rx_path_in_lpi_mode;
+ x->irq_rx_path_in_lpi_mode_n++;
}
- if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
+ if (ret & LPI_CTRL_STATUS_RLPIEX) {
CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
- status |= core_irq_rx_path_exit_lpi_mode;
+ x->irq_rx_path_exit_lpi_mode_n++;
}
}
- return status;
+ if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) {
+ CHIP_DBG(KERN_INFO "GMAC PCS ANE IRQ\n");
+ readl(ioaddr + GMAC_AN_STATUS);
+ x->irq_pcs_ane_n++;
+ }
+ if (intr_status & rgmii_irq) {
+ CHIP_DBG(KERN_INFO "GMAC RGMII IRQ status\n");
+ readl(ioaddr + GMAC_S_R_GMII);
+ x->irq_rgmii_n++;
+ }
+
+ return ret;
}
static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index f83210e..cb86a58 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,7 +72,8 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
return 0;
}
-static int dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(void __iomem *ioaddr,
+ struct stmmac_extra_stats *x)
{
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 88d2d25..d78234e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -108,6 +108,9 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
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),
+ /* PCS */
+ STMMAC_STAT(irq_pcs_ane_n),
+ STMMAC_STAT(irq_rgmii_n),
#ifdef CONFIG_STMMAC_EXTENDED_DESC
/* Extended RDES status */
STMMAC_STAT(ip_hdr_err),
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8786939..7d2ee6f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1998,30 +1998,14 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
/* To handle GMAC own interrupts */
if (priv->plat->has_gmac) {
int status = priv->hw->mac->host_irq_status((void __iomem *)
- dev->base_addr);
+ dev->base_addr,
+ &priv->xstats);
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++;
+ if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
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++;
+ if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
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++;
}
}
--
1.7.4.4
^ permalink raw reply related
* Re: [PATCH] 8139too: send NETDEV_CHANGE manually when autoneg is disabled
From: Veaceslav Falico @ 2013-03-07 10:27 UTC (permalink / raw)
To: David Miller
Cc: bhutchings, netdev, wfp5p, jasowang, junchangwang, greearb,
ivecera
In-Reply-To: <20130306.155323.344491888348815531.davem@davemloft.net>
On Wed, Mar 06, 2013 at 03:53:23PM -0500, David Miller wrote:
>From: Ben Hutchings <bhutchings@solarflare.com>
>Date: Wed, 6 Mar 2013 20:22:52 +0000
>
>> On Wed, 2013-03-06 at 20:06 +0100, Veaceslav Falico wrote:
>>> When setting autoneg off (with any additional parameters, like
>>> speed/duplex), 8139too doesn't do an interface reset, and thus doesn't
>>> notify anyone that its speed/duplex might have changed (bonding and bridge
>>> will not see the speed changes, per example).
>>>
>>> Verify if we've force_media and send notification manually, so that the
>>> listeners have a chance to see the changes. It's quite ugly, however I
>>> don't see anything better.
>>
>> Isn't this really a bug in mii_check_media()? It shouldn't shortcut the
>> calls to netif_carrier_{off,on}() just because mii->force_media is set.
>
>I think mii_check_media() is responsible for handling this too.
The mii_check_media() doesn't get called, AFAIK. The problem here is that,
after we call ethtool -s eth0 autoneg off speed X, with eth0 being
8139too, the speed/autoneg options are changed via mii_ethtool_sset(),
however the interface itself isn't down'ed/up'ed, and thus no NETDEV_
notifications are sent.
Other drivers either explicitly reset the interface after
ethtool.set_settings() call (like netxen_nic using ndo_close()/ndo_open()),
do it on the logic level (tg3) without involving mii_ethtool_sset(), or
just reset on their own (e100 iirc), so that most of them are responsible
for somehow triggering these events.
Silently changing speed can break things a bit - bonding relies on
interface speeds for 802.3ad/alb/tlb/active-backup iirc, bridge relies on
stp port cost etc. and they all get it via NETDEV_ notifications. So
without them, they would end up with outdated data, per example (eth2 being
8139too):
darkmag:~#grep 'Interface\|Speed' /proc/net/bonding/bond0
Slave Interface: eth0
Speed: 100 Mbps
Slave Interface: eth2
Speed: 100 Mbps
darkmag:~#ethtool -s eth2 autoneg off speed 10
darkmag:~#cat /sys/class/net/eth2/speed
10
darkmag:~#grep 'Interface\|Speed' /proc/net/bonding/bond0
Slave Interface: eth0
Speed: 100 Mbps
Slave Interface: eth2
Speed: 100 Mbps
However, I think that mii_check_media() is also wrong :), though I didn't
really dig into it. I'll check it when I'll have time.
^ permalink raw reply
* Re: BCM5709 hang and state dump...
From: Daniel J Blueman @ 2013-03-07 10:27 UTC (permalink / raw)
To: Michael Chan; +Cc: Eilon Greenstein, Steffen Persvold, netdev
In-Reply-To: <5126D912.9000800@numascale-asia.com>
On 22/02/2013 10:33, Daniel J Blueman wrote:
> Hi Michael,
>
> Thanks for your reply.
>
> We'll probably be able to reproduce it next week and collect the output
> with your debug patches if useful.
>
> Thanks again,
> Daniel
>
> On 22/02/2013 05:59, Michael Chan wrote:
>> On Thu, 2013-02-21 at 13:26 +0800, Daniel J Blueman wrote:
>>> Hi Michael/Eilon,
>>>
>>> On a large system with 552 cores, 1.5TB memory and linux 3.7, under some
>>> particular workloads, we've seem the Broadcom 5709 network controller
>>> hang [1]. It's running boot code 6.2.0 and NCSI code 2.0.11.
>>>
>>> We suspect completion timeouts may be occurring due to possible
>>> starvation.
>>>
>>> Is there anything significant/indicative from the state dumped?
>>
>> The firmware state seems to be ok, although we see some MSIX interrupts
>> being asserted internally which is a sign that they don't get serviced.
>>
>> Is this easily reproducible? Can we send you some debug patches to dump
>> more data?
We've hit this again [1], with 3.8.0 this time. Any success on the debug
patches?
Many thanks,
Daniel
--- [1]
WARNING: at net/sched/sch_generic.c:254 dev_watchdog+0x239/0x250()
Hardware name: IBM System X3755 M3 -[7164Z63]-
NETDEV WATCHDOG: eth0 (bnx2): transmit queue 3 timed out
Pid: 0, comm: swapper/0 Not tainted 3.8.0-advanced+ #2
Call Trace:
<IRQ> [<ffffffff817a2889>] ? dev_watchdog+0x239/0x250
[<ffffffff8105f914>] ? warn_slowpath_common+0x74/0xb0
[<ffffffff8105f9c5>] ? warn_slowpath_fmt+0x45/0x50
[<ffffffff817a2889>] ? dev_watchdog+0x239/0x250
[<ffffffff817a2650>] ? pfifo_fast_dequeue+0xd0/0xd0
[<ffffffff8106b4fa>] ? call_timer_fn.isra.27+0x2a/0x90
[<ffffffff8106b6d4>] ? run_timer_softirq+0x174/0x240
[<ffffffff810663b4>] ? __do_softirq+0xa4/0x150
[<ffffffff81089005>] ? sched_clock_local+0x15/0x80
[<ffffffff818670cc>] ? call_softirq+0x1c/0x30
[<ffffffff81036eed>] ? do_softirq+0x4d/0x80
[<ffffffff81066586>] ? irq_exit+0x86/0xa0
[<ffffffff81866d67>] ? reschedule_interrupt+0x67/0x70
<EOI> [<ffffffff81098ce0>] ? __tick_nohz_idle_enter+0x350/0x410
[<ffffffff8103cda0>] ? default_idle+0x20/0x40
[<ffffffff8103d686>] ? cpu_idle+0xb6/0xd0
[<ffffffff81ee0adf>] ? start_kernel+0x322/0x32d
[<ffffffff81ee05d5>] ? repair_env_string+0x5b/0x5b
---[ end trace 3d99e677c25b07a1 ]---
bnx2 0000:01:00.0 eth0: <--- start FTQ dump --->
bnx2 0000:01:00.0 eth0: RV2P_PFTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: RV2P_TFTQ_CTL 00020000
bnx2 0000:01:00.0 eth0: RV2P_MFTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: TBDR_FTQ_CTL 00004002
bnx2 0000:01:00.0 eth0: TDMA_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TXP_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TXP_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TPAT_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: RXP_CFTQ_CTL 00008000
bnx2 0000:01:00.0 eth0: RXP_FTQ_CTL 00100000
bnx2 0000:01:00.0 eth0: COM_COMXQ_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: COM_COMTQ_FTQ_CTL 00020000
bnx2 0000:01:00.0 eth0: COM_COMQ_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: CP_CPQ_FTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: CPU states:
bnx2 0000:01:00.0 eth0: 045000 mode b84c state 80001000 evt_mask 500 pc
8001280 pc 8001280 instr 30820001
bnx2 0000:01:00.0 eth0: 085000 mode b84c state 80005000 evt_mask 500 pc
8000a5c pc 8000a4c instr 1440fffc
bnx2 0000:01:00.0 eth0: 0c5000 mode b84c state 80001000 evt_mask 500 pc
8004c14 pc 8004c10 instr 8e900000
bnx2 0000:01:00.0 eth0: 105000 mode b8cc state 80000000 evt_mask 500 pc
8000a9c pc 8000a94 instr 8c420020
bnx2 0000:01:00.0 eth0: 145000 mode b880 state 80000000 evt_mask 500 pc
800b13c pc 800b13c instr 8f4201c8
bnx2 0000:01:00.0 eth0: 185000 mode b8cc state 80004000 evt_mask 500 pc
8000c6c pc 8000c50 instr 3c058000
bnx2 0000:01:00.0 eth0: <--- end FTQ dump --->
bnx2 0000:01:00.0 eth0: <--- start TBDC dump --->
bnx2 0000:01:00.0 eth0: TBDC free cnt: 32
bnx2 0000:01:00.0 eth0: LINE CID BIDX CMD VALIDS
bnx2 0000:01:00.0 eth0: 00 000800 a090 00 [0]
bnx2 0000:01:00.0 eth0: 01 000800 a090 00 [0]
bnx2 0000:01:00.0 eth0: 02 001100 9cf8 00 [0]
bnx2 0000:01:00.0 eth0: 03 0ddd00 fb58 fd [0]
bnx2 0000:01:00.0 eth0: 04 1fff80 ffc8 6f [0]
bnx2 0000:01:00.0 eth0: 05 0e9f80 9fa8 cf [0]
bnx2 0000:01:00.0 eth0: 06 1d7380 f7e8 ff [0]
bnx2 0000:01:00.0 eth0: 07 1d5f00 7bb0 bb [0]
bnx2 0000:01:00.0 eth0: 08 1edb80 ef78 6f [0]
bnx2 0000:01:00.0 eth0: 09 1e9e80 ee58 9e [0]
bnx2 0000:01:00.0 eth0: 0a 17e780 fff8 7c [0]
bnx2 0000:01:00.0 eth0: 0b 1d7e00 7db8 fc [0]
bnx2 0000:01:00.0 eth0: 0c 1f7780 bff8 cf [0]
bnx2 0000:01:00.0 eth0: 0d 1bff80 fff8 ff [0]
bnx2 0000:01:00.0 eth0: 0e 17ff80 3de8 fe [0]
bnx2 0000:01:00.0 eth0: 0f 1ff780 9cf0 ff [0]
bnx2 0000:01:00.0 eth0: 10 1f7f80 ff58 ef [0]
bnx2 0000:01:00.0 eth0: 11 1e7780 eaa8 7f [0]
bnx2 0000:01:00.0 eth0: 12 1f9d80 f5e8 f7 [0]
bnx2 0000:01:00.0 eth0: 13 07ef80 ffc8 77 [0]
bnx2 0000:01:00.0 eth0: 14 1fb780 57e8 bf [0]
bnx2 0000:01:00.0 eth0: 15 0fae80 df68 5f [0]
bnx2 0000:01:00.0 eth0: 16 0fff80 7ff8 ae [0]
bnx2 0000:01:00.0 eth0: 17 1fff80 fed8 c6 [0]
bnx2 0000:01:00.0 eth0: 18 03e380 fe70 7b [0]
bnx2 0000:01:00.0 eth0: 19 0bcd80 7db8 7f [0]
bnx2 0000:01:00.0 eth0: 1a 0ab180 bbd0 ef [0]
bnx2 0000:01:00.0 eth0: 1b 0dfd80 db78 db [0]
bnx2 0000:01:00.0 eth0: 1c 0bff80 7ff8 f3 [0]
bnx2 0000:01:00.0 eth0: 1d 0dfb80 f9f8 fc [0]
bnx2 0000:01:00.0 eth0: 1e 1a6e80 9be8 f7 [0]
bnx2 0000:01:00.0 eth0: 1f 1fab80 db78 50 [0]
bnx2 0000:01:00.0 eth0: <--- end TBDC dump --->
bnx2 0000:01:00.0 eth0: DEBUG: intr_sem[0] PCI_CMD[00100546]
bnx2 0000:01:00.0 eth0: DEBUG: PCI_PM[19002008] PCI_MISC_CFG[92000088]
bnx2 0000:01:00.0 eth0: DEBUG: EMAC_TX_STATUS[00000008]
EMAC_RX_STATUS[00000000]
bnx2 0000:01:00.0 eth0: DEBUG: RPM_MGMT_PKT_CTRL[40000088]
bnx2 0000:01:00.0 eth0: DEBUG: HC_STATS_INTERRUPT_STATUS[01b2004d]
bnx2 0000:01:00.0 eth0: DEBUG: PBA[00000000]
bnx2 0000:01:00.0 eth0: <--- start MCP states dump --->
bnx2 0000:01:00.0 eth0: DEBUG: MCP_STATE_P0[0003610e] MCP_STATE_P1[0003610e]
bnx2 0000:01:00.0 eth0: DEBUG: MCP mode[0000b880] state[80000000]
evt_mask[00000500]
bnx2 0000:01:00.0 eth0: DEBUG: pc[08001e3c] pc[0800d994] instr[27bd0020]
bnx2 0000:01:00.0 eth0: DEBUG: shmem states:
bnx2 0000:01:00.0 eth0: DEBUG: drv_mb[01030003] fw_mb[00000003]
link_status[8000006f]
drv_pulse_mb[0000431d]
bnx2 0000:01:00.0 eth0: DEBUG: dev_info_signature[44564903]
reset_type[01005254]
condition[0003610e]
bnx2 0000:01:00.0 eth0: DEBUG: 000001c0: 01005254 42530088 0003610e 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 000003cc: 44444444 44444444 44444444 00000a14
bnx2 0000:01:00.0 eth0: DEBUG: 000003dc: 0004ffff 00000000 00000000 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 000003ec: 00000000 00000000 00000000 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 0x3fc[0000ffff]
bnx2 0000:01:00.0 eth0: <--- end MCP states dump --->
bnx2 0000:01:00.0 eth0: NIC Copper Link is Down
bnx2 0000:01:00.0 eth0: NIC Copper Link is Up, 1000 Mbps full duplex
bnx2 0000:01:00.0 eth0: <--- start FTQ dump --->
bnx2 0000:01:00.0 eth0: RV2P_PFTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: RV2P_TFTQ_CTL 00020000
bnx2 0000:01:00.0 eth0: RV2P_MFTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: TBDR_FTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: TDMA_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TXP_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TXP_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TPAT_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: RXP_CFTQ_CTL 00008000
bnx2 0000:01:00.0 eth0: RXP_FTQ_CTL 00100000
bnx2 0000:01:00.0 eth0: COM_COMXQ_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: COM_COMTQ_FTQ_CTL 00020000
bnx2 0000:01:00.0 eth0: COM_COMQ_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: CP_CPQ_FTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: CPU states:
bnx2 0000:01:00.0 eth0: 045000 mode b84c state 80001000 evt_mask 500 pc
8001280 pc 8001288 instr 30820001
bnx2 0000:01:00.0 eth0: 085000 mode b84c state 80009000 evt_mask 500 pc
8000a5c pc 8000a5c instr 10400016
bnx2 0000:01:00.0 eth0: 0c5000 mode b84c state 80001000 evt_mask 500 pc
8004c20 pc 8004c1c instr 10e00088
bnx2 0000:01:00.0 eth0: 105000 mode b8cc state 80000000 evt_mask 500 pc
8000a98 pc 8000a9c instr 8821
bnx2 0000:01:00.0 eth0: 145000 mode b880 state 80000000 evt_mask 500 pc
8000058 pc 800d930 instr afb00028
bnx2 0000:01:00.0 eth0: 185000 mode b8cc state 80000000 evt_mask 500 pc
8000918 pc 8000c58 instr 10a30010
bnx2 0000:01:00.0 eth0: <--- end FTQ dump --->
bnx2 0000:01:00.0 eth0: <--- start TBDC dump --->
bnx2 0000:01:00.0 eth0: TBDC free cnt: 32
bnx2 0000:01:00.0 eth0: LINE CID BIDX CMD VALIDS
bnx2 0000:01:00.0 eth0: 00 001200 0038 00 [0]
bnx2 0000:01:00.0 eth0: 01 000800 01e8 00 [0]
bnx2 0000:01:00.0 eth0: 02 001100 9cf8 00 [0]
bnx2 0000:01:00.0 eth0: 03 0ddd00 fb58 fd [0]
bnx2 0000:01:00.0 eth0: 04 1fff80 ffc8 6f [0]
bnx2 0000:01:00.0 eth0: 05 0e9f80 9fa8 cf [0]
bnx2 0000:01:00.0 eth0: 06 1d7380 f7e8 ff [0]
bnx2 0000:01:00.0 eth0: 07 1d5f00 7bb0 bb [0]
bnx2 0000:01:00.0 eth0: 08 1edb80 ef78 6f [0]
bnx2 0000:01:00.0 eth0: 09 1e9e80 ee58 9e [0]
bnx2 0000:01:00.0 eth0: 0a 17e780 fff8 7c [0]
bnx2 0000:01:00.0 eth0: 0b 1d7e00 7db8 fc [0]
bnx2 0000:01:00.0 eth0: 0c 1f7780 bff8 cf [0]
bnx2 0000:01:00.0 eth0: 0d 1bff80 fff8 ff [0]
bnx2 0000:01:00.0 eth0: 0e 17ff80 3de8 fe [0]
bnx2 0000:01:00.0 eth0: 0f 1ff780 9cf0 ff [0]
bnx2 0000:01:00.0 eth0: 10 1f7f80 ff58 ef [0]
bnx2 0000:01:00.0 eth0: 11 1e7780 eaa8 7f [0]
bnx2 0000:01:00.0 eth0: 12 1f9d80 f5e8 f7 [0]
bnx2 0000:01:00.0 eth0: 13 07ef80 ffc8 77 [0]
bnx2 0000:01:00.0 eth0: 14 1fb780 57e8 bf [0]
bnx2 0000:01:00.0 eth0: 15 0fae80 df68 5f [0]
bnx2 0000:01:00.0 eth0: 16 0fff80 7ff8 ae [0]
bnx2 0000:01:00.0 eth0: 17 1fff80 fed8 c6 [0]
bnx2 0000:01:00.0 eth0: 18 03e380 fe70 7b [0]
bnx2 0000:01:00.0 eth0: 19 0bcd80 7db8 7f [0]
bnx2 0000:01:00.0 eth0: 1a 0ab180 bbd0 ef [0]
bnx2 0000:01:00.0 eth0: 1b 0dfd80 db78 db [0]
bnx2 0000:01:00.0 eth0: 1c 0bff80 7ff8 f3 [0]
bnx2 0000:01:00.0 eth0: 1d 0dfb80 f9f8 fc [0]
bnx2 0000:01:00.0 eth0: 1e 1a6e80 9be8 f7 [0]
bnx2 0000:01:00.0 eth0: 1f 1fab80 db78 50 [0]
bnx2 0000:01:00.0 eth0: <--- end TBDC dump --->
bnx2 0000:01:00.0 eth0: DEBUG: intr_sem[0] PCI_CMD[00100546]
bnx2 0000:01:00.0 eth0: DEBUG: PCI_PM[19002008] PCI_MISC_CFG[92000088]
bnx2 0000:01:00.0 eth0: DEBUG: EMAC_TX_STATUS[00000008]
EMAC_RX_STATUS[00000000]
bnx2 0000:01:00.0 eth0: DEBUG: RPM_MGMT_PKT_CTRL[40000088]
bnx2 0000:01:00.0 eth0: DEBUG: HC_STATS_INTERRUPT_STATUS[01c0003f]
bnx2 0000:01:00.0 eth0: DEBUG: PBA[00000000]
bnx2 0000:01:00.0 eth0: <--- start MCP states dump --->
bnx2 0000:01:00.0 eth0: DEBUG: MCP_STATE_P0[0003610e] MCP_STATE_P1[0003610e]
bnx2 0000:01:00.0 eth0: DEBUG: MCP mode[0000b880] state[80000000]
evt_mask[00000500]
bnx2 0000:01:00.0 eth0: DEBUG: pc[0800d994] pc[0800b3a4] instr[8f420388]
bnx2 0000:01:00.0 eth0: DEBUG: shmem states:
bnx2 0000:01:00.0 eth0: DEBUG: drv_mb[01030006] fw_mb[00000006]
link_status[8000006f]
drv_pulse_mb[000043f8]
bnx2 0000:01:00.0 eth0: DEBUG: dev_info_signature[44564903]
reset_type[01005254]
condition[0003610e]
bnx2 0000:01:00.0 eth0: DEBUG: 000001c0: 01005254 42530085 0003610e 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 000003cc: 44444444 44444444 44444444 00000a14
bnx2 0000:01:00.0 eth0: DEBUG: 000003dc: 0004ffff 00000000 00000000 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 000003ec: 00000000 00000000 00000000 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 0x3fc[0000ffff]
bnx2 0000:01:00.0 eth0: <--- end MCP states dump --->
bnx2 0000:01:00.0 eth0: NIC Copper Link is Down
bnx2 0000:01:00.0 eth0: NIC Copper Link is Up, 1000 Mbps full duplex
bnx2 0000:01:00.0 eth0: <--- start FTQ dump --->
bnx2 0000:01:00.0 eth0: RV2P_PFTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: RV2P_TFTQ_CTL 00020000
bnx2 0000:01:00.0 eth0: RV2P_MFTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: TBDR_FTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: TDMA_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TXP_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TXP_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: TPAT_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: RXP_CFTQ_CTL 00008000
bnx2 0000:01:00.0 eth0: RXP_FTQ_CTL 00100000
bnx2 0000:01:00.0 eth0: COM_COMXQ_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: COM_COMTQ_FTQ_CTL 00020000
bnx2 0000:01:00.0 eth0: COM_COMQ_FTQ_CTL 00010000
bnx2 0000:01:00.0 eth0: CP_CPQ_FTQ_CTL 00004000
bnx2 0000:01:00.0 eth0: CPU states:
bnx2 0000:01:00.0 eth0: 045000 mode b84c state 80001000 evt_mask 500 pc
8001284 pc 8001284 instr 8e260000
bnx2 0000:01:00.0 eth0: 085000 mode b84c state 80001000 evt_mask 500 pc
8000a4c pc 8000a5c instr 10400016
bnx2 0000:01:00.0 eth0: 0c5000 mode b84c state 80001000 evt_mask 500 pc
8004c14 pc 8004c18 instr 32050003
bnx2 0000:01:00.0 eth0: 105000 mode b8cc state 80000000 evt_mask 500 pc
8000a90 pc 8000a98 instr 3c020800
bnx2 0000:01:00.0 eth0: 145000 mode b880 state 80000000 evt_mask 500 pc
800af54 pc 8003e30 instr 9062004d
bnx2 0000:01:00.0 eth0: 185000 mode b8cc state 80000000 evt_mask 500 pc
8000c7c pc 8000c6c instr 8ce800e8
bnx2 0000:01:00.0 eth0: <--- end FTQ dump --->
bnx2 0000:01:00.0 eth0: <--- start TBDC dump --->
bnx2 0000:01:00.0 eth0: TBDC free cnt: 32
bnx2 0000:01:00.0 eth0: LINE CID BIDX CMD VALIDS
bnx2 0000:01:00.0 eth0: 00 001200 0008 00 [0]
bnx2 0000:01:00.0 eth0: 01 001100 0010 00 [0]
bnx2 0000:01:00.0 eth0: 02 001100 9cf8 00 [0]
bnx2 0000:01:00.0 eth0: 03 0ddd00 fb58 fd [0]
bnx2 0000:01:00.0 eth0: 04 1fff80 ffc8 6f [0]
bnx2 0000:01:00.0 eth0: 05 0e9f80 9fa8 cf [0]
bnx2 0000:01:00.0 eth0: 06 1d7380 f7e8 ff [0]
bnx2 0000:01:00.0 eth0: 07 1d5f00 7bb0 bb [0]
bnx2 0000:01:00.0 eth0: 08 1edb80 ef78 6f [0]
bnx2 0000:01:00.0 eth0: 09 1e9e80 ee58 9e [0]
bnx2 0000:01:00.0 eth0: 0a 17e780 fff8 7c [0]
bnx2 0000:01:00.0 eth0: 0b 1d7e00 7db8 fc [0]
bnx2 0000:01:00.0 eth0: 0c 1f7780 bff8 cf [0]
bnx2 0000:01:00.0 eth0: 0d 1bff80 fff8 ff [0]
bnx2 0000:01:00.0 eth0: 0e 17ff80 3de8 fe [0]
bnx2 0000:01:00.0 eth0: 0f 1ff780 9cf0 ff [0]
bnx2 0000:01:00.0 eth0: 10 1f7f80 ff58 ef [0]
bnx2 0000:01:00.0 eth0: 11 1e7780 eaa8 7f [0]
bnx2 0000:01:00.0 eth0: 12 1f9d80 f5e8 f7 [0]
bnx2 0000:01:00.0 eth0: 13 07ef80 ffc8 77 [0]
bnx2 0000:01:00.0 eth0: 14 1fb780 57e8 bf [0]
bnx2 0000:01:00.0 eth0: 15 0fae80 df68 5f [0]
bnx2 0000:01:00.0 eth0: 16 0fff80 7ff8 ae [0]
bnx2 0000:01:00.0 eth0: 17 1fff80 fed8 c6 [0]
bnx2 0000:01:00.0 eth0: 18 03e380 fe70 7b [0]
bnx2 0000:01:00.0 eth0: 19 0bcd80 7db8 7f [0]
bnx2 0000:01:00.0 eth0: 1a 0ab180 bbd0 ef [0]
bnx2 0000:01:00.0 eth0: 1b 0dfd80 db78 db [0]
bnx2 0000:01:00.0 eth0: 1c 0bff80 7ff8 f3 [0]
bnx2 0000:01:00.0 eth0: 1d 0dfb80 f9f8 fc [0]
bnx2 0000:01:00.0 eth0: 1e 1a6e80 9be8 f7 [0]
bnx2 0000:01:00.0 eth0: 1f 1fab80 db78 50 [0]
bnx2 0000:01:00.0 eth0: <--- end TBDC dump --->
bnx2 0000:01:00.0 eth0: DEBUG: intr_sem[0] PCI_CMD[00100546]
bnx2 0000:01:00.0 eth0: DEBUG: PCI_PM[19002008] PCI_MISC_CFG[92000088]
bnx2 0000:01:00.0 eth0: DEBUG: EMAC_TX_STATUS[00000008]
EMAC_RX_STATUS[00000000]
bnx2 0000:01:00.0 eth0: DEBUG: RPM_MGMT_PKT_CTRL[40000088]
bnx2 0000:01:00.0 eth0: DEBUG: HC_STATS_INTERRUPT_STATUS[014600b9]
bnx2 0000:01:00.0 eth0: DEBUG: PBA[00000000]
bnx2 0000:01:00.0 eth0: <--- start MCP states dump --->
bnx2 0000:01:00.0 eth0: DEBUG: MCP_STATE_P0[0003610e] MCP_STATE_P1[0003610e]
bnx2 0000:01:00.0 eth0: DEBUG: MCP mode[0000b880] state[80000000]
evt_mask[00000500]
bnx2 0000:01:00.0 eth0: DEBUG: pc[08003d8c] pc[08000b10] instr[00021202]
bnx2 0000:01:00.0 eth0: DEBUG: shmem states:
bnx2 0000:01:00.0 eth0: DEBUG: drv_mb[01030009] fw_mb[00000009]
link_status[8000006f]
drv_pulse_mb[0000442d]
bnx2 0000:01:00.0 eth0: DEBUG: dev_info_signature[44564903]
reset_type[01005254]
condition[0003610e]
bnx2 0000:01:00.0 eth0: DEBUG: 000001c0: 01005254 42530085 0003610e 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 000003cc: 44444444 44444444 44444444 00000a14
bnx2 0000:01:00.0 eth0: DEBUG: 000003dc: 0004ffff 00000000 00000000 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 000003ec: 00000000 00000000 00000000 00000000
bnx2 0000:01:00.0 eth0: DEBUG: 0x3fc[0000ffff]
bnx2 0000:01:00.0 eth0: <--- end MCP states dump --->
bnx2 0000:01:00.0 eth0: NIC Copper Link is Down
bnx2 0000:01:00.0 eth0: NIC Copper Link is Up, 1000 Mbps full duplex
--
Daniel J Blueman
Principal Software Engineer, Numascale Asia
^ permalink raw reply
* Re: hv_netvsc: WARNING in softirq.c
From: Richard Genoud @ 2013-03-07 10:12 UTC (permalink / raw)
To: Haiyang Zhang
Cc: KY Srinivasan, devel@linuxdriverproject.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <4147bb5a7cf547c19c6a5a6b459a957d@DFM-DB3MBX15-06.exchange.corp.microsoft.com>
2013/3/6 Haiyang Zhang <haiyangz@microsoft.com>:
> I have found a simple way to reproduce this kind of warning:
> 1) reboot the VM (because this warning can be displayed only once.)
> 2) login to the host and open the VM [Settings]
> 3) Temporarily change the Network adapter's option [Virtual Switch] to "Not connected".
> 4) run dmesg, you should see the warning.
>
> The reason for the warning is -- netif_tx_disable() is called when the NIC
> is disconnected. And it's called within irq context. netif_tx_disable()
> calls local_bh_enable() which displays warning if in irq.
>
> The fix is to remove the unnecessary netif_tx_disable() in the netvsc_linkstatus_callback().
> I attached a patch. Would you like to test it on your side as well?
>
> Thanks,
> - Haiyang
>
Thanks for your reply.
I'll be able to test your patch in 2 or 3 weeks I guess (I haven't got
any access to the hyperV machine, the admin-sys is on holiday, and
it's a production server... So I don't want to mess with it right now
:) )
Regards,
Richard.
^ permalink raw reply
* RE: [PATCH] iputils: fix memory leaks
From: David Laight @ 2013-03-07 10:06 UTC (permalink / raw)
To: jb, netdev
In-Reply-To: <loom.20130307T103516-549@post.gmane.org>
> Fix memory leaks
...
> +#ifdef USE_IDN
> + free(idn);
> + idn = NULL;
> +#endif
> exit(2);
There is no point calling free() before exit(), nor any need
to free items that aren't allocated inside loops.
David
^ permalink raw reply
* Re: [PATCH net-next 00/12] IPVS optimizations
From: Jesper Dangaard Brouer @ 2013-03-07 10:09 UTC (permalink / raw)
To: Julian Anastasov; +Cc: Simon Horman, lvs-devel, netdev
In-Reply-To: <1362559342-18784-1-git-send-email-ja@ssi.bg>
On Wed, 2013-03-06 at 10:42 +0200, Julian Anastasov wrote:
> This is a first patchset for IPVS optimizations.
> Another patchset will address the locking in schedulers
> and moving the global _bh disabling from LOCAL_OUT to all
> locks. It is in TODO list.
Do you have any performance measurements?
Or is this code primarily cleanup optimizations, and the next patchset
will address the performance part?
--
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: [PATCH] netconsole: release the spinlock before __netpoll_cleanup()
From: Veaceslav Falico @ 2013-03-07 10:03 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, amwang, davem
In-Reply-To: <20130307000824.GA5702@neilslaptop.think-freely.org>
On Wed, Mar 06, 2013 at 07:08:24PM -0500, Neil Horman wrote:
>On Wed, Mar 06, 2013 at 03:46:43PM +0100, Veaceslav Falico wrote:
>> Commit 3335f0ca130c201f8680e97f63612053fbc16e22 removed spinlock unlocking
>> before __netpoll_cleanup() in netconsole_netdev_event(), however we still
>> might sleep in __netpoll_cleanup() - via synchronize_srcu(). Revert it and
>> add a comment.
>>
>> Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
>> ---
>> drivers/net/netconsole.c | 10 ++++++++++
>> 1 files changed, 10 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
>> index 37add21..dd62b4c 100644
>> --- a/drivers/net/netconsole.c
>> +++ b/drivers/net/netconsole.c
>> @@ -680,7 +680,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
>> * rtnl_lock already held
>> */
>> if (nt->np.dev) {
>> + /*
>> + * we still might sleep in
>> + * __netpoll_cleanup(), so release
>> + * the lock
>> + */
>> + spin_unlock_irqrestore(
>> + &target_list_lock,
>> + flags);
>> __netpoll_cleanup(&nt->np);
>> + spin_lock_irqsave(&target_list_lock,
>> + flags);
>> dev_put(nt->np.dev);
>> nt->np.dev = NULL;
>> }
>> --
>> 1.7.1
>>
>Thanks for noticing this Vaeceslav, but you can't just drop and re-acquire the
>lock like this, as it protect the list_for_each_entry loop that you're in. You
>can drop the lock in the above if clause, but then, after the nt->np.dev = NULL,
>go back an re-aquire the lock, and start the for loop. I thought we had already
>done this for some other purpose in this code using a label and a goto, but I
>suppose I was mistaken
You're right, I somehow missed that restart goto, which was removed
earlier. Does that feel right (I've also added back the
netconsole_target_put()):
Subject: [PATCH] netconsole: release the spinlock before __netpoll_cleanup()
__netpoll_cleanup() might sleep in synchronize_srcu(), which was added to
avoid race in another situation, so we can't call it with the spinlock
target_list_lock held.
Add spin_unlock/lock before/after it and restart the loop.
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/netconsole.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 37add21..267c26b 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -666,6 +666,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
goto done;
spin_lock_irqsave(&target_list_lock, flags);
+restart:
list_for_each_entry(nt, &target_list, list) {
netconsole_target_get(nt);
if (nt->np.dev == dev) {
@@ -680,9 +681,21 @@ static int netconsole_netdev_event(struct notifier_block *this,
* rtnl_lock already held
*/
if (nt->np.dev) {
+ /*
+ * we still might sleep in
+ * __netpoll_cleanup(), so release
+ * the lock and restart
+ */
+ spin_unlock_irqrestore(
+ &target_list_lock,
+ flags);
__netpoll_cleanup(&nt->np);
+ spin_lock_irqsave(&target_list_lock,
+ flags);
dev_put(nt->np.dev);
nt->np.dev = NULL;
+ netconsole_target_put(nt);
+ goto restart;
}
nt->enabled = 0;
stopped = true;
--
1.7.1
^ permalink raw reply related
* [PATCH] iputils: fix memory leaks
From: jb @ 2013-03-07 9:52 UTC (permalink / raw)
To: netdev
Fix memory leaks
Signed-off-by: JB <jb.1234abcd@gmail.com>
---
ping.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/ping.c b/ping.c
index c0366cd..04f5596 100644
--- a/ping.c
+++ b/ping.c
@@ -282,10 +282,15 @@ main(int argc, char **argv)
hp = gethostbyname(idn);
if (!hp) {
fprintf(stderr, "ping: unknown host %s\n", target);
+#ifdef USE_IDN
+ free(idn);
+ idn = NULL;
+#endif
exit(2);
}
#ifdef USE_IDN
free(idn);
+ idn = NULL;
#endif
memcpy(&whereto.sin_addr, hp->h_addr, 4);
#ifdef USE_IDN
@@ -301,6 +306,10 @@ main(int argc, char **argv)
hnamebuf[sizeof(hnamebuf) - 1] = 0;
#endif
hostname = hnamebuf;
+#ifdef USE_IDN
+ free(hnamebuf);
+ hnamebuf = NULL;
+#endif
}
if (argc > 1)
route[nroute++] = whereto.sin_addr.s_addr;
^ permalink raw reply related
* Re: upgrade to 3.8.1 : BUG Scheduling while atomic in bonding driver:
From: Michael Wang @ 2013-03-07 9:50 UTC (permalink / raw)
To: Linda Walsh
Cc: Eric Dumazet, Linux-Kernel, netdev, Jay Vosburgh, Jeff Kirsher,
Cong Wang
In-Reply-To: <513854E6.9010709@tlinx.org>
On 03/07/2013 04:50 PM, Linda Walsh wrote:
>
> I am *not* seeing the bug in 3.8.2 with the 2nd patch applied (in
> addition to the first)...
So that means bond lock is the reason, nice, but this is really not a
good fix if we just unlock it...
The better way is to move the cycle wait logical out of the
bond_update_speed_duplex() IMO, I think we need the folk who work on
this driver to make the decision ;-)
Regards,
Michael Wang
>
>
> Michael Wang wrote:
>>
>>
>> And both bond_enslave() and bond_mii_monitor() are using bond_update_speed_duplex()
>> with preempt disabled.
>>
>> Along with the changes in bond_enslave(), I think you also need this (untested):
>>
>> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>> index 11d01d6..9af143a 100644
>> --- a/drivers/net/bonding/bond_main.c
>> +++ b/drivers/net/bonding/bond_main.c
>> @@ -2373,7 +2373,9 @@ static void bond_miimon_commit(struct bonding *bond)
>> bond_set_backup_slave(slave);
>> }
>>
>> + read_unlock(&bond->lock);
>> bond_update_speed_duplex(slave);
>> + read_lock(&bond->lock);
>>
>> pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
>> bond->dev->name, slave->dev->name,
>>
>>
>> Regards,
>> Michael Wang
>>
>>
>>
>
^ 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