* Re: 3.4-rc: NETDEV WATCHDOG: eth0 (r8169): transmit queue 0 timed out
From: Tomas Papan @ 2012-06-12 14:34 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev
In-Reply-To: <CAMGsXDSsSMWfrV1vjnqkWH45ypZw+ZtYF7=ytc79MWRJ5RF5jQ@mail.gmail.com>
Hi Francois,
Unfortunately after the warning occurred once again after 28 000 seconds.
Is there anything else what can I do?
Regards
Tomas
[28914.344765] ------------[ cut here ]------------
[28914.344775] WARNING: at net/sched/sch_generic.c:256
dev_watchdog+0x16b/0x20f()
[28914.344779] Hardware name: SH55J
[28914.344782] NETDEV WATCHDOG: eth1 (r8169): transmit queue 0 timed out
[28914.344785] Modules linked in: vhost_net cls_route cls_u32 cls_fw
sch_sfq sch_htb ipt_REDIRECT ipt_MASQUERADE xt_limit xt_tcpudp
nf_conntrack_ipv6 nf_defrag_ipv6 xt_state iptable_nat nf_nat
nf_conntrack_ipv4 nf_conntrack nf_defrag_ipv4 ip6table_filter
ip6_tables iptable_filter ip_tables x_tables kvm_intel kvm fuse r8169
[28914.344819] Pid: 0, comm: swapper/2 Not tainted 3.4.2 #1
[28914.344822] Call Trace:
[28914.344825] <IRQ> [<ffffffff81026881>] ? warn_slowpath_common+0x78/0x8c
[28914.344837] [<ffffffff81026936>] ? warn_slowpath_fmt+0x45/0x4a
[28914.344843] [<ffffffff81042fc2>] ? scheduler_tick+0xaf/0xc3
[28914.344850] [<ffffffff81049f70>] ? ktime_get+0x5f/0xb9
[28914.344855] [<ffffffff812535a0>] ? dev_watchdog+0x16b/0x20f
[28914.344861] [<ffffffff8102f3ae>] ? run_timer_softirq+0x177/0x209
[28914.344868] [<ffffffff8103e7b3>] ? hrtimer_interrupt+0x100/0x19b
[28914.344872] [<ffffffff81253435>] ? qdisc_reset+0x35/0x35
[28914.344879] [<ffffffff8102b256>] ? __do_softirq+0x7f/0x106
[28914.344884] [<ffffffff812e298c>] ? call_softirq+0x1c/0x30
[28914.344890] [<ffffffff81003376>] ? do_softirq+0x31/0x67
[28914.344895] [<ffffffff8102b503>] ? irq_exit+0x44/0x75
[28914.344899] [<ffffffff810032b5>] ? do_IRQ+0x94/0xad
[28914.344905] [<ffffffff812e10a7>] ? common_interrupt+0x67/0x67
[28914.344908] <EOI> [<ffffffff81163f07>] ? intel_idle+0xde/0x103
[28914.344919] [<ffffffff81163ee3>] ? intel_idle+0xba/0x103
[28914.344926] [<ffffffff81220bfa>] ? cpuidle_idle_call+0x7e/0xc4
[28914.344933] [<ffffffff81008e92>] ? cpu_idle+0x53/0x7c
[28914.344937] ---[ end trace 3d8459064a9171b4 ]---
[28914.347829] r8169 0000:01:00.0: eth1: link up
^ permalink raw reply
* Re: [RFC] net/sched/em_canid: Ematch rule to match CAN frames according to their CAN IDs
From: Eric Dumazet @ 2012-06-12 14:33 UTC (permalink / raw)
To: Rostislav Lisovy; +Cc: netdev, linux-can, lartc, pisa, sojkam1
In-Reply-To: <1339509809.22704.149.camel@edumazet-glaptop>
On Tue, 2012-06-12 at 16:03 +0200, Eric Dumazet wrote:
> On Tue, 2012-06-12 at 15:48 +0200, Rostislav Lisovy wrote:
> > em_canid is an ematch capable of classifying CAN frames according to
> > their CAN IDs.
> >
> > This RFC/Patch contains a reworked classifier initially posted in
> > http://www.spinics.net/lists/netdev/msg200114.html
> > The functionality is the same however there is almost 50% reduction
> > in the source code length.
> >
> > There is a slight difference between this ematch and other available
> > ematches. Other ematches implement only a simple match operation and
> > are meant to be combined with logic conjunctions (e.g. AND, OR).
> > Our ematch makes it possible to use up to 32 rules in single
> > 'configuration statement' (with OR semantics). This allows us to take
> > the advantage of the bit field data-structure in the implementation of
> > the match function.
> >
> > Example: canid(sff 0x123 eff 0x124 sff 0x230:0x7f0)
> > This ematch would match CAN SFF frames with the following IDs:
> > 0x123, 0x230--0x23f or EFF frame with ID 0x124.
> >
> > Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
> > ---
> > include/linux/can.h | 3 +
> > include/linux/pkt_cls.h | 5 +-
> > net/sched/Kconfig | 10 +++
> > net/sched/Makefile | 1 +
> > net/sched/em_canid.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++
> > 5 files changed, 234 insertions(+), 2 deletions(-)
> > create mode 100644 net/sched/em_canid.c
> >
> > diff --git a/include/linux/can.h b/include/linux/can.h
> > index 9a19bcb..08d1610 100644
> > --- a/include/linux/can.h
> > +++ b/include/linux/can.h
> > @@ -38,6 +38,9 @@
> > */
> > typedef __u32 canid_t;
> >
> > +#define CAN_SFF_ID_BITS 11
> > +#define CAN_EFF_ID_BITS 29
> > +
>
> > +struct canid_match {
> > + struct can_filter rules_raw[EM_CAN_RULES_SIZE]; /* Raw rules copied
> > + from netlink message; Used for sending information to
> > + userspace (when 'tc filter show' is invoked) AND when
> > + matching EFF frames*/
> > + DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF CAN
> > + ID (11 bit) there is one record in this bitfield */
> > + int rules_count;
> > + int eff_rules_count;
> > + int sff_rules_count;
> > +
> > + struct rcu_head rcu;
> > +};
>
> The size of kmalloc() blob to hold this structure is 4 Mbytes
>
> This is a huge cost, and unlikely to succeed but shortly after boot...
>
> (this happens to be the largest possible kmalloc() allocation by the way
> on x86)
>
>
Oh well, I mixed CAN_SFF_ID_BITS / CAN_EFF_ID_BITS
^ permalink raw reply
* Re: [net-next.git 2/4] stmmac: do not use strict_strtoul but kstrtoul
From: Eric Dumazet @ 2012-06-12 14:28 UTC (permalink / raw)
To: Giuseppe CAVALLARO; +Cc: netdev, bhutchings, rayagond, davem, yuvalmin
In-Reply-To: <1339505153-26731-3-git-send-email-peppe.cavallaro@st.com>
On Tue, 2012-06-12 at 14:45 +0200, Giuseppe CAVALLARO wrote:
> This patch replaces the obsolete strict_strtoul with kstrtoul.
>
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 ++++++++-------------
> 1 files changed, 10 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 8899e10..e33abf5 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2126,42 +2126,36 @@ static int __init stmmac_cmdline_opt(char *str)
> return -EINVAL;
> while ((opt = strsep(&str, ",")) != NULL) {
> if (!strncmp(opt, "debug:", 6)) {
> - if (strict_strtoul(opt + 6, 0, (unsigned long *)&debug))
> + if (kstrtoul(opt + 6, 0, (unsigned long *)&debug))
> goto err;
int debug;
...
if (kstrtoul(opt + 6, 0, (unsigned long *)&debug))
Please get rid of these wrong casts.
^ permalink raw reply
* Re: [PATCH RFC] c_can_pci: generic module for c_can on PCI
From: Federico Vaga @ 2012-06-12 14:25 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: Wolfgang Grandegger, Giancarlo Asnaghi, Alan Cox,
Alessandro Rubini, linux-can, netdev, linux-kernel
In-Reply-To: <4FCCC077.7000303@pengutronix.de>
> > +out_free_clock:
> > + if (!priv->priv)
>
> ^^^
>
> looks fishy
Also c_can_platform.c use priv->priv when it needs to get clk. I can add
a comment to specify what the statement do.
--
Federico Vaga
^ permalink raw reply
* Re: [net-next.git 4/4 (v4)] stmmac: add the Energy Efficient Ethernet support
From: Giuseppe CAVALLARO @ 2012-06-12 14:24 UTC (permalink / raw)
To: Yuval Mintz
Cc: netdev@vger.kernel.org, bhutchings@solarflare.com,
rayagond@vayavyalabs.com, davem@davemloft.net
In-Reply-To: <979A8436335E3744ADCD3A9F2A2B68A5027BDB@SJEXCHMB10.corp.ad.broadcom.com>
On 6/12/2012 3:09 PM, Yuval Mintz wrote:
> Hi Giuseppe,
>
>> @@ -1541,10 +1663,37 @@ static irqreturn_t stmmac_interrupt(int irq,
>> void *dev_id)
>> + 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++;
>> +
>
> Are these EEE related?
>
>> + /* To handle DMA interrupts */
>
> Is this related?
>
To clearly manage and expose the lpi interrupt status and eee ethtool
stats I've had to do some modifications to the driver's design and I
found really useful to move other parts of the code (e.g. mmc irq stat)
in the main directly. So this just is the result of a complete reworking
made to introduce the EEE. I could better document it in the patch's
comment or create a separate patch that could take a while.
Cheers
Peppe
>
> Cheers,
> Yuval Mintz
>
>
>
^ permalink raw reply
* Re: [RFC] net/sched/em_canid: Ematch rule to match CAN frames according to their CAN IDs
From: Eric Dumazet @ 2012-06-12 14:03 UTC (permalink / raw)
To: Rostislav Lisovy; +Cc: netdev, linux-can, lartc, pisa, sojkam1
In-Reply-To: <1339508913-7784-1-git-send-email-lisovy@gmail.com>
On Tue, 2012-06-12 at 15:48 +0200, Rostislav Lisovy wrote:
> em_canid is an ematch capable of classifying CAN frames according to
> their CAN IDs.
>
> This RFC/Patch contains a reworked classifier initially posted in
> http://www.spinics.net/lists/netdev/msg200114.html
> The functionality is the same however there is almost 50% reduction
> in the source code length.
>
> There is a slight difference between this ematch and other available
> ematches. Other ematches implement only a simple match operation and
> are meant to be combined with logic conjunctions (e.g. AND, OR).
> Our ematch makes it possible to use up to 32 rules in single
> 'configuration statement' (with OR semantics). This allows us to take
> the advantage of the bit field data-structure in the implementation of
> the match function.
>
> Example: canid(sff 0x123 eff 0x124 sff 0x230:0x7f0)
> This ematch would match CAN SFF frames with the following IDs:
> 0x123, 0x230--0x23f or EFF frame with ID 0x124.
>
> Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
> ---
> include/linux/can.h | 3 +
> include/linux/pkt_cls.h | 5 +-
> net/sched/Kconfig | 10 +++
> net/sched/Makefile | 1 +
> net/sched/em_canid.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 234 insertions(+), 2 deletions(-)
> create mode 100644 net/sched/em_canid.c
>
> diff --git a/include/linux/can.h b/include/linux/can.h
> index 9a19bcb..08d1610 100644
> --- a/include/linux/can.h
> +++ b/include/linux/can.h
> @@ -38,6 +38,9 @@
> */
> typedef __u32 canid_t;
>
> +#define CAN_SFF_ID_BITS 11
> +#define CAN_EFF_ID_BITS 29
> +
> +struct canid_match {
> + struct can_filter rules_raw[EM_CAN_RULES_SIZE]; /* Raw rules copied
> + from netlink message; Used for sending information to
> + userspace (when 'tc filter show' is invoked) AND when
> + matching EFF frames*/
> + DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF CAN
> + ID (11 bit) there is one record in this bitfield */
> + int rules_count;
> + int eff_rules_count;
> + int sff_rules_count;
> +
> + struct rcu_head rcu;
> +};
The size of kmalloc() blob to hold this structure is 4 Mbytes
This is a huge cost, and unlikely to succeed but shortly after boot...
(this happens to be the largest possible kmalloc() allocation by the way
on x86)
^ permalink raw reply
* [RFC] net/sched/em_canid: Ematch rule to match CAN frames according to their CAN IDs
From: Rostislav Lisovy @ 2012-06-12 13:48 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, linux-can, lartc, pisa, sojkam1, Rostislav Lisovy
em_canid is an ematch capable of classifying CAN frames according to
their CAN IDs.
This RFC/Patch contains a reworked classifier initially posted in
http://www.spinics.net/lists/netdev/msg200114.html
The functionality is the same however there is almost 50% reduction
in the source code length.
There is a slight difference between this ematch and other available
ematches. Other ematches implement only a simple match operation and
are meant to be combined with logic conjunctions (e.g. AND, OR).
Our ematch makes it possible to use up to 32 rules in single
'configuration statement' (with OR semantics). This allows us to take
the advantage of the bit field data-structure in the implementation of
the match function.
Example: canid(sff 0x123 eff 0x124 sff 0x230:0x7f0)
This ematch would match CAN SFF frames with the following IDs:
0x123, 0x230--0x23f or EFF frame with ID 0x124.
Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
---
include/linux/can.h | 3 +
include/linux/pkt_cls.h | 5 +-
net/sched/Kconfig | 10 +++
net/sched/Makefile | 1 +
net/sched/em_canid.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 234 insertions(+), 2 deletions(-)
create mode 100644 net/sched/em_canid.c
diff --git a/include/linux/can.h b/include/linux/can.h
index 9a19bcb..08d1610 100644
--- a/include/linux/can.h
+++ b/include/linux/can.h
@@ -38,6 +38,9 @@
*/
typedef __u32 canid_t;
+#define CAN_SFF_ID_BITS 11
+#define CAN_EFF_ID_BITS 29
+
/*
* Controller Area Network Error Frame Mask structure
*
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index defbde2..6b16f90 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -451,8 +451,9 @@ enum {
#define TCF_EM_U32 3
#define TCF_EM_META 4
#define TCF_EM_TEXT 5
-#define TCF_EM_VLAN 6
-#define TCF_EM_MAX 6
+#define TCF_EM_VLAN 6
+#define TCF_EM_CANID 7
+#define TCF_EM_MAX 7
enum {
TCF_EM_PROG_TC
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 75b58f8..bc0ceab 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -485,6 +485,16 @@ config NET_EMATCH_TEXT
To compile this code as a module, choose M here: the
module will be called em_text.
+config NET_EMATCH_CANID
+ tristate "CAN ID"
+ depends on NET_EMATCH && CAN
+ ---help---
+ Say Y here if you want to be able to classify CAN frames based
+ on CAN ID.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_canid.
+
config NET_CLS_ACT
bool "Actions"
---help---
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 8cdf4e2..47f9262 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
obj-$(CONFIG_NET_EMATCH_TEXT) += em_text.o
+obj-$(CONFIG_NET_EMATCH_CANID) += em_canid.o
diff --git a/net/sched/em_canid.c b/net/sched/em_canid.c
new file mode 100644
index 0000000..ef68eef
--- /dev/null
+++ b/net/sched/em_canid.c
@@ -0,0 +1,217 @@
+/*
+ * net/sched/em_canid.c CAN ID ematch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Rostislav Lisovy (lisovy@gmail.com)
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <net/pkt_cls.h>
+#include <linux/can.h>
+
+#define EM_CAN_RULES_SIZE 32
+
+struct canid_match {
+ struct can_filter rules_raw[EM_CAN_RULES_SIZE]; /* Raw rules copied
+ from netlink message; Used for sending information to
+ userspace (when 'tc filter show' is invoked) AND when
+ matching EFF frames*/
+ DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF CAN
+ ID (11 bit) there is one record in this bitfield */
+ int rules_count;
+ int eff_rules_count;
+ int sff_rules_count;
+
+ struct rcu_head rcu;
+};
+
+/**
+ * em_canid_get_id() - Extracts Can ID out of the sk_buff structure.
+ */
+static canid_t em_canid_get_id(struct sk_buff *skb)
+{
+ /* CAN ID is stored within the data field */
+ struct can_frame *cf = (struct can_frame *)skb->data;
+
+ return cf->can_id;
+}
+
+static void em_canid_sff_match_add(struct canid_match *cm, u32 can_id, u32 can_mask)
+{
+ int i;
+
+ /* Limit can_mask and can_id to SFF range to
+ protect against write after end of array */
+ can_mask &= CAN_SFF_MASK;
+ can_id &= can_mask;
+
+ /* single frame */
+ if (can_mask == CAN_SFF_MASK) {
+ set_bit(can_id, cm->match_sff);
+ return;
+ }
+
+ /* all frames */
+ if (can_mask == 0) {
+ bitmap_fill(cm->match_sff, (1 << CAN_SFF_ID_BITS));
+ return;
+ }
+
+ /* individual frame filter */
+ /* Add record (set bit to 1) for each ID that
+ conforms particular rule */
+ for (i = 0; i < (1 << CAN_SFF_ID_BITS); i++) {
+ if ((i & can_mask) == can_id)
+ set_bit(i, cm->match_sff);
+ }
+}
+
+static inline struct canid_match *em_canid_priv(struct tcf_ematch *m)
+{
+ return (struct canid_match *) (m)->data;
+}
+
+static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m,
+ struct tcf_pkt_info *info)
+{
+ struct canid_match *cm = em_canid_priv(m);
+ canid_t can_id;
+ unsigned int match = false;
+ int i;
+
+ can_id = em_canid_get_id(skb);
+
+ if (can_id & CAN_EFF_FLAG) {
+ can_id &= CAN_EFF_MASK;
+
+ for (i = 0; i < cm->eff_rules_count; i++) {
+ if (!(((cm->rules_raw[i].can_id ^ can_id) &
+ cm->rules_raw[i].can_mask) & CAN_EFF_MASK)) {
+ match = true;
+ break;
+ }
+ }
+ } else { /* SFF */
+ can_id &= CAN_SFF_MASK;
+ match = test_bit(can_id, cm->match_sff);
+ }
+
+ if (match)
+ return 1;
+
+ return 0;
+}
+
+static int em_canid_change(struct tcf_proto *tp, void *data, int len,
+ struct tcf_ematch *m)
+{
+ struct can_filter *conf = data; /* Array with rules,
+ fixed size EM_CAN_RULES_SIZE */
+ struct canid_match *cm;
+ int err;
+ int i;
+
+ if (len < sizeof(struct can_filter))
+ return -EINVAL;
+
+ err = -ENOBUFS;
+ cm = kzalloc(sizeof(*cm), GFP_KERNEL);
+ if (cm == NULL)
+ goto errout;
+
+ cm->sff_rules_count = 0;
+ cm->eff_rules_count = 0;
+ cm->rules_count = len/sizeof(struct can_filter);
+ err = -EINVAL;
+ if (cm->rules_count > EM_CAN_RULES_SIZE) /* Be sure to fit into the array */
+ goto errout_free;
+
+ /* We need two for() loops for copying rules into
+ two contiguous areas in rules_raw */
+
+ /* Process EFF frame rules*/
+ for (i = 0; i < cm->rules_count; i++) {
+ if ((conf[i].can_id & CAN_EFF_FLAG) &&
+ (conf[i].can_mask & CAN_EFF_FLAG)) {
+ memcpy(cm->rules_raw + cm->eff_rules_count,
+ &conf[i],
+ sizeof(struct can_filter));
+ cm->eff_rules_count++;
+ } else {
+ continue;
+ }
+ }
+
+ /* Process SFF frame rules */
+ for (i = 0; i < cm->rules_count; i++) {
+ if ((conf[i].can_id & CAN_EFF_FLAG) &&
+ (conf[i].can_mask & CAN_EFF_FLAG)) {
+ continue;
+ } else {
+ memcpy(cm->rules_raw + cm->eff_rules_count + cm->sff_rules_count,
+ &conf[i],
+ sizeof(struct can_filter));
+ cm->sff_rules_count++;
+ em_canid_sff_match_add(cm,
+ conf[i].can_id, conf[i].can_mask);
+ }
+ }
+
+ m->datalen = sizeof(*cm);
+ m->data = (unsigned long) cm;
+
+ return 0;
+
+errout_free:
+ kfree(cm);
+errout:
+ return err;
+}
+
+static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
+{
+ struct canid_match *cm = em_canid_priv(m);
+
+ kfree(cm);
+}
+
+static int em_canid_dump(struct sk_buff *skb, struct tcf_ematch *m)
+{
+ return 0;
+}
+
+static struct tcf_ematch_ops em_canid_ops = {
+ .kind = TCF_EM_CANID,
+ .change = em_canid_change,
+ .match = em_canid_match,
+ .destroy = em_canid_destroy,
+ .dump = em_canid_dump,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_canid_ops.link)
+};
+
+static int __init init_em_canid(void)
+{
+ return tcf_em_register(&em_canid_ops);
+}
+
+static void __exit exit_em_canid(void)
+{
+ tcf_em_unregister(&em_canid_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_canid);
+module_exit(exit_em_canid);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_CANID);
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
From: Eric Dumazet @ 2012-06-12 13:34 UTC (permalink / raw)
To: Bogdan Hamciuc; +Cc: davem, netdev
In-Reply-To: <1339506917.22704.134.camel@edumazet-glaptop>
On Tue, 2012-06-12 at 15:15 +0200, Eric Dumazet wrote:
> On Tue, 2012-06-12 at 14:22 +0200, Eric Dumazet wrote:
> > Hmm, real question is why skb_realloc_headroom() is even necessary...
> >
> > I suspect we need to reserve more bytes.
> >
> > total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;
> >
> > or something like that ?
> >
> > Which driver triggers the bug ?
> >
In case you wonder why I try so hard to avoid the
skb_realloc_headroom() :
netpoll has complicated^Wspecial^Wnice skb cache, to make sure it can
work even if memory is exhausted.
But if we trigger skb_realloc_headroom() the whole thing is useless.
Thanks
^ permalink raw reply
* Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
From: Eric Dumazet @ 2012-06-12 13:15 UTC (permalink / raw)
To: Bogdan Hamciuc; +Cc: davem, netdev
In-Reply-To: <1339503766.22704.116.camel@edumazet-glaptop>
On Tue, 2012-06-12 at 14:22 +0200, Eric Dumazet wrote:
> On Tue, 2012-06-12 at 13:26 +0300, Bogdan Hamciuc wrote:
> > As skb->tail wasn't updated after skb_copy_to_linear_data(), subsequent
> > calls to skb_realloc_headroom() (as made by an ethernet driver's
> > ndo_start_xmit routine) would only effectively copy the packet headers,
> > leaving garbage in the payload.
> >
> > In the process, removed some unnecessary code.
> >
> > Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
> > ---
> > net/core/netpoll.c | 8 ++++----
> > 1 files changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> > index 3d84fb9..9a08068 100644
> > --- a/net/core/netpoll.c
> > +++ b/net/core/netpoll.c
> > @@ -362,22 +362,22 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
> >
> > void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
> > {
> > - int total_len, eth_len, ip_len, udp_len;
> > + int total_len, ip_len, udp_len;
> > struct sk_buff *skb;
> > struct udphdr *udph;
> > struct iphdr *iph;
> > struct ethhdr *eth;
> >
> > udp_len = len + sizeof(*udph);
> > - ip_len = eth_len = udp_len + sizeof(*iph);
> > - total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
> > + ip_len = udp_len + sizeof(*iph);
> > + total_len = ip_len + ETH_HLEN + NET_IP_ALIGN;
> >
> > skb = find_skb(np, total_len, total_len - len);
> > if (!skb)
> > return;
> >
> > skb_copy_to_linear_data(skb, msg, len);
> > - skb->len += len;
> > + skb_put(skb, len);
> >
> > skb_push(skb, sizeof(*udph));
> > skb_reset_transport_header(skb);
>
> Hmm, real question is why skb_realloc_headroom() is even necessary...
>
> I suspect we need to reserve more bytes.
>
> total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;
>
> or something like that ?
>
> Which driver triggers the bug ?
>
Please try the following :
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3d84fb9..1c6fb72 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -362,17 +362,18 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
- int total_len, eth_len, ip_len, udp_len;
+ int total_len, ip_len, udp_len;
struct sk_buff *skb;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
udp_len = len + sizeof(*udph);
- ip_len = eth_len = udp_len + sizeof(*iph);
- total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
+ ip_len = udp_len + sizeof(*iph);
+ total_len = ip_len + LL_RESERVED_SPACE(np->dev);
- skb = find_skb(np, total_len, total_len - len);
+ skb = find_skb(np, total_len + np->dev->needed_tailroom,
+ total_len - len);
if (!skb)
return;
^ permalink raw reply related
* Re: [PATCH v10] tilegx network driver: initial support
From: Chris Metcalf @ 2012-06-12 13:14 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, bhutchings, arnd, linux-kernel, netdev
In-Reply-To: <20120611.170336.1197560839526564340.davem@davemloft.net>
On 6/11/2012 8:03 PM, David Miller wrote:
> From: Chris Metcalf <cmetcalf@tilera.com>
> Date: Thu, 7 Jun 2012 16:45:02 -0400
>
>> This change adds support for the tilegx network driver based on the
>> GXIO IORPC support in the tilegx software stack, using the on-chip
>> mPIPE packet processing engine.
>>
>> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
> Applied.
Glad to hear it. Thanks for bearing with the multiple revisions. I (we)
appreciate all your feedback, and that of Ben, Eric, Arnd, and other folks
who contributed their time.
The driver does depend on tilegx iorpc framework code that is currently
only in linux-next, but it should all come together properly for 3.6.
--
Chris Metcalf, Tilera Corp.
http://www.tilera.com
^ permalink raw reply
* Re: [PATCH 1/4] drivers/net/ethernet/sfc: Add efx_ prefix to set_bit_le()
From: Arnd Bergmann @ 2012-06-12 13:12 UTC (permalink / raw)
To: Takuya Yoshikawa
Cc: Takuya Yoshikawa, bhutchings, grundler, avi, mtosatti,
linux-net-drivers, netdev, linux-kernel, linux-arch, kvm
In-Reply-To: <20120612220654.fd0246e6e687f7c79e5c988c@gmail.com>
On Tuesday 12 June 2012, Takuya Yoshikawa wrote:
> >
> > Hmm, any reason why we're not just using the existing non-atomic
> > __set_bit_le() here? I think the helpers in sfc and tulip can
> > just get removed if you use those.
>
> __set_bit_le() assumes long word alignment and does endian conversion
> when needed.
Ah, I see.
> To be honest, I am a bit scared of changing drivers which I cannot test
> on real hardware.
Ok, let's take your patches as they are then.
With the change to add clear_bit_le:
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: [PATCH 3/4] bitops: Introduce generic set_bit_le()
From: Takuya Yoshikawa @ 2012-06-12 13:10 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Takuya Yoshikawa, bhutchings, grundler, avi, mtosatti,
linux-net-drivers, netdev, linux-kernel, linux-arch, kvm
In-Reply-To: <201206111410.26359.arnd@arndb.de>
On Mon, 11 Jun 2012 14:10:26 +0000
Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 11 June 2012, Takuya Yoshikawa wrote:
> > From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
> >
> > Needed to replace test_and_set_bit_le() in virt/kvm/kvm_main.c which is
> > being used for this missing function.
> >
> > Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
> > Cc: Arnd Bergmann <arnd@arndb.de>
>
> I would recommend adding the corresponding clear_bit_le() along with
> set_bit_le, so the next person who needs that doesn't have to make
> yet another patch.
I will do in the next version.
Now I have also noticed that I need to add the same code to powerpc's
bitops file.
Takuya
^ permalink raw reply
* RE: [net-next.git 4/4 (v4)] stmmac: add the Energy Efficient Ethernet support
From: Yuval Mintz @ 2012-06-12 13:09 UTC (permalink / raw)
To: Giuseppe CAVALLARO, netdev@vger.kernel.org
Cc: bhutchings@solarflare.com, rayagond@vayavyalabs.com,
davem@davemloft.net
In-Reply-To: <1339505153-26731-5-git-send-email-peppe.cavallaro@st.com>
Hi Giuseppe,
> @@ -1541,10 +1663,37 @@ static irqreturn_t stmmac_interrupt(int irq,
> void *dev_id)
> + 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++;
> +
Are these EEE related?
> + /* To handle DMA interrupts */
Is this related?
Cheers,
Yuval Mintz
^ permalink raw reply
* Re: [PATCH 1/4] drivers/net/ethernet/sfc: Add efx_ prefix to set_bit_le()
From: Takuya Yoshikawa @ 2012-06-12 13:06 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Takuya Yoshikawa, bhutchings, grundler, avi, mtosatti,
linux-net-drivers, netdev, linux-kernel, linux-arch, kvm
In-Reply-To: <201206111409.16093.arnd@arndb.de>
On Mon, 11 Jun 2012 14:09:15 +0000
Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 11 June 2012, Takuya Yoshikawa wrote:
> >
> > /* Set bit in a little-endian bitfield */
> > -static inline void set_bit_le(unsigned nr, unsigned char *addr)
> > +static inline void efx_set_bit_le(unsigned nr, unsigned char *addr)
> > {
> > addr[nr / 8] |= (1 << (nr % 8));
> > }
> >
> > /* Clear bit in a little-endian bitfield */
> > -static inline void clear_bit_le(unsigned nr, unsigned char *addr)
> > +static inline void efx_clear_bit_le(unsigned nr, unsigned char *addr)
> > {
> > addr[nr / 8] &= ~(1 << (nr % 8));
> > }
>
> Hmm, any reason why we're not just using the existing non-atomic
> __set_bit_le() here? I think the helpers in sfc and tulip can
> just get removed if you use those.
__set_bit_le() assumes long word alignment and does endian conversion
when needed.
To be honest, I am a bit scared of changing drivers which I cannot test
on real hardware.
Takuya
^ permalink raw reply
* Re: [PATCH 1/1 v3] Ethtool: Add EEE support
From: Giuseppe CAVALLARO @ 2012-06-12 12:48 UTC (permalink / raw)
To: Yuval Mintz; +Cc: bhutchings, netdev, eilong
In-Reply-To: <1339318088-27126-1-git-send-email-yuvalmin@broadcom.com>
Hello Yuval.
On 6/10/2012 10:48 AM, Yuval Mintz wrote:
> This patch adds 2 new ethtool commands which can be
> used to manipulate network interfaces' support in
> EEE.
>
> Output of 'get' has the following form:
>
> EEE Settings for p2p1:
> EEE status: enabled - active
> Tx LPI: 1000 (us)
> Supported EEE link modes: 10000baseT/Full
> Advertised EEE link modes: 10000baseT/Full
> Link partner advertised EEE link modes: 10000baseT/Full
>
> Thanks goes to Giuseppe Cavallaro for his original patch.
>
> Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
> Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
I've tested it with the stmmac on STB SH4 platform and it seems to be ok
on my side.
peppe
> ---
> Changes from Version 2:
> - Changed --get-eee into --show-eee
> - Corrected EEE tests in test-cmdline.c
> - Corrected documentation
> ---
> ethtool.8.in | 32 +++++++++++++
> ethtool.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++--------
> test-cmdline.c | 11 +++++
> 3 files changed, 159 insertions(+), 20 deletions(-)
>
> diff --git a/ethtool.8.in b/ethtool.8.in
> index 70ae31d..178322b 100644
> --- a/ethtool.8.in
> +++ b/ethtool.8.in
> @@ -325,6 +325,16 @@ ethtool \- query or control network driver and hardware settings
> .I devname flag
> .A1 on off
> .RB ...
> +.HP
> +.B ethtool \-\-show\-eee
> +.I devname
> +.HP
> +.B ethtool \-\-set\-eee
> +.I devname
> +.B2 eee on off
> +.B2 tx-lpi on off
> +.BN tx-timer
> +.BN advertise
> .
> .\" Adjust lines (i.e. full justification) and hyphenate.
> .ad
> @@ -810,6 +820,28 @@ Sets the device's private flags as specified.
> .I flag
> .A1 on off
> Sets the state of the named private flag.
> +.TP
> +.B \-\-show\-eee
> +Queries the specified network device for its support of Efficient Energy
> +Ethernet (according to the IEEE 802.3az specifications)
> +.TP
> +.B \-\-set\-eee
> +Sets the device EEE behaviour.
> +.TP
> +.A2 eee on off
> +Enables/disables the device support of EEE.
> +.TP
> +.A2 tx-lpi on off
> +Determines whether the device should assert its Tx LPI.
> +.TP
> +.BI advertise \ N
> +Sets the speeds for which the device should advertise EEE capabiliities.
> +Values are as for
> +.B \-\-change advertise
> +.TP
> +.BI tx-timer \ N
> +Sets the amount of time the device should stay in idle mode prior to asserting
> +its Tx LPI (in microseconds). This has meaning only when Tx LPI is enabled.
> .SH BUGS
> Not supported (in part or whole) on all network drivers.
> .SH AUTHOR
> diff --git a/ethtool.c b/ethtool.c
> index f09a032..73e0e28 100644
> --- a/ethtool.c
> +++ b/ethtool.c
> @@ -416,7 +416,8 @@ static int do_version(struct cmd_context *ctx)
> return 0;
> }
>
> -static void dump_link_caps(const char *prefix, const char *an_prefix, u32 mask);
> +static void dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
> + int link_mode_only);
>
> static void dump_supported(struct ethtool_cmd *ep)
> {
> @@ -435,14 +436,15 @@ static void dump_supported(struct ethtool_cmd *ep)
> fprintf(stdout, "FIBRE ");
> fprintf(stdout, "]\n");
>
> - dump_link_caps("Supported", "Supports", mask);
> + dump_link_caps("Supported", "Supports", mask, 0);
> }
>
> /* Print link capability flags (supported, advertised or lp_advertised).
> * Assumes that the corresponding SUPPORTED and ADVERTISED flags are equal.
> */
> static void
> -dump_link_caps(const char *prefix, const char *an_prefix, u32 mask)
> +dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
> + int link_mode_only)
> {
> int indent;
> int did1;
> @@ -527,24 +529,26 @@ dump_link_caps(const char *prefix, const char *an_prefix, u32 mask)
> fprintf(stdout, "Not reported");
> fprintf(stdout, "\n");
>
> - fprintf(stdout, " %s pause frame use: ", prefix);
> - if (mask & ADVERTISED_Pause) {
> - fprintf(stdout, "Symmetric");
> - if (mask & ADVERTISED_Asym_Pause)
> - fprintf(stdout, " Receive-only");
> - fprintf(stdout, "\n");
> - } else {
> - if (mask & ADVERTISED_Asym_Pause)
> - fprintf(stdout, "Transmit-only\n");
> + if (!link_mode_only) {
> + fprintf(stdout, " %s pause frame use: ", prefix);
> + if (mask & ADVERTISED_Pause) {
> + fprintf(stdout, "Symmetric");
> + if (mask & ADVERTISED_Asym_Pause)
> + fprintf(stdout, " Receive-only");
> + fprintf(stdout, "\n");
> + } else {
> + if (mask & ADVERTISED_Asym_Pause)
> + fprintf(stdout, "Transmit-only\n");
> + else
> + fprintf(stdout, "No\n");
> + }
> +
> + fprintf(stdout, " %s auto-negotiation: ", an_prefix);
> + if (mask & ADVERTISED_Autoneg)
> + fprintf(stdout, "Yes\n");
> else
> fprintf(stdout, "No\n");
> }
> -
> - fprintf(stdout, " %s auto-negotiation: ", an_prefix);
> - if (mask & ADVERTISED_Autoneg)
> - fprintf(stdout, "Yes\n");
> - else
> - fprintf(stdout, "No\n");
> }
>
> static int dump_ecmd(struct ethtool_cmd *ep)
> @@ -552,10 +556,11 @@ static int dump_ecmd(struct ethtool_cmd *ep)
> u32 speed;
>
> dump_supported(ep);
> - dump_link_caps("Advertised", "Advertised", ep->advertising);
> + dump_link_caps("Advertised", "Advertised", ep->advertising, 0);
> if (ep->lp_advertising)
> dump_link_caps("Link partner advertised",
> - "Link partner advertised", ep->lp_advertising);
> + "Link partner advertised", ep->lp_advertising,
> + 0);
>
> fprintf(stdout, " Speed: ");
> speed = ethtool_cmd_speed(ep);
> @@ -1234,6 +1239,34 @@ static int dump_rxfhash(int fhash, u64 val)
> return 0;
> }
>
> +static void dump_eeecmd(struct ethtool_eee *ep)
> +{
> +
> + fprintf(stdout, " EEE status: ");
> + if (!ep->supported) {
> + fprintf(stdout, "not supported\n");
> + return;
> + } else if (!ep->eee_enabled) {
> + fprintf(stdout, "disabled\n");
> + } else {
> + fprintf(stdout, "enabled - ");
> + if (ep->eee_active)
> + fprintf(stdout, "active\n");
> + else
> + fprintf(stdout, "inactive\n");
> + }
> +
> + fprintf(stdout, " Tx LPI:");
> + if (ep->tx_lpi_enabled)
> + fprintf(stdout, " %d (us)\n", ep->tx_lpi_timer);
> + else
> + fprintf(stdout, " disabled\n");
> +
> + dump_link_caps("Supported EEE", "", ep->supported, 1);
> + dump_link_caps("Advertised EEE", "", ep->advertised, 1);
> + dump_link_caps("Link partner advertised EEE", "", ep->lp_advertised, 1);
> +}
> +
> #define N_SOTS 7
>
> static char *so_timestamping_labels[N_SOTS] = {
> @@ -3463,6 +3496,63 @@ static int do_getmodule(struct cmd_context *ctx)
> return 0;
> }
>
> +static int do_geee(struct cmd_context *ctx)
> +{
> + struct ethtool_eee eeecmd;
> +
> + if (ctx->argc != 0)
> + exit_bad_args();
> +
> + eeecmd.cmd = ETHTOOL_GEEE;
> + if (send_ioctl(ctx, &eeecmd)) {
> + perror("Cannot get EEE settings");
> + return 1;
> + }
> +
> + fprintf(stdout, "EEE Settings for %s:\n", ctx->devname);
> + dump_eeecmd(&eeecmd);
> +
> + return 0;
> +}
> +
> +static int do_seee(struct cmd_context *ctx)
> +{
> + int adv_c = -1, lpi_c = -1, lpi_time_c = -1, eee_c = -1;
> + int change = -1, change2 = -1;
> + struct ethtool_eee eeecmd;
> + struct cmdline_info cmdline_eee[] = {
> + { "advertise", CMDL_U32, &adv_c, &eeecmd.advertised },
> + { "tx-lpi", CMDL_BOOL, &lpi_c, &eeecmd.tx_lpi_enabled },
> + { "tx-timer", CMDL_U32, &lpi_time_c, &eeecmd.tx_lpi_timer},
> + { "eee", CMDL_BOOL, &eee_c, &eeecmd.eee_enabled},
> + };
> +
> + if (ctx->argc == 0)
> + exit_bad_args();
> +
> + parse_generic_cmdline(ctx, &change, cmdline_eee,
> + ARRAY_SIZE(cmdline_eee));
> +
> + eeecmd.cmd = ETHTOOL_GEEE;
> + if (send_ioctl(ctx, &eeecmd)) {
> + perror("Cannot get EEE settings");
> + return 1;
> + }
> +
> + do_generic_set(cmdline_eee, ARRAY_SIZE(cmdline_eee), &change2);
> +
> + if (change2) {
> +
> + eeecmd.cmd = ETHTOOL_SEEE;
> + if (send_ioctl(ctx, &eeecmd)) {
> + perror("Cannot set EEE settings");
> + return 1;
> + }
> + }
> +
> + return 0;
> +}
> +
> #ifndef TEST_ETHTOOL
> int send_ioctl(struct cmd_context *ctx, void *cmd)
> {
> @@ -3611,6 +3701,12 @@ static const struct option {
> " [ hex on|off ]\n"
> " [ offset N ]\n"
> " [ length N ]\n" },
> + { "--show-eee", 1, do_geee, "Show EEE settings"},
> + { "--set-eee", 1, do_seee, "Set EEE settings",
> + " [ eee on|off ]\n"
> + " [ advertise %x ]\n"
> + " [ tx-lpi on|off ]\n"
> + " [ tx-timer %d ]\n"},
> { "-h|--help", 0, show_usage, "Show this help" },
> { "--version", 0, do_version, "Show version number" },
> {}
> diff --git a/test-cmdline.c b/test-cmdline.c
> index 978c312..8fc2b48 100644
> --- a/test-cmdline.c
> +++ b/test-cmdline.c
> @@ -217,6 +217,17 @@ static struct test_case {
> { 0, "-m devname hex off" },
> { 1, "-m devname hex on raw on" },
> { 0, "-m devname offset 4 length 6" },
> + { 1, "--show-eee" },
> + { 0, "--show-eee devname" },
> + { 1, "--show-eee devname foo" },
> + { 1, "--set-eee" },
> + { 1, "--set-eee devname" },
> + { 0, "--set-eee devname eee on" },
> + { 0, "--set-eee devname eee off" },
> + { 0, "--set-eee devname tx-lpi on" },
> + { 0, "--set-eee devname tx-lpi off" },
> + { 1, "--set-eee devname tx-timer foo" },
> + { 1, "--set-eee devname advertise foo" },
> /* can't test --set-priv-flags yet */
> { 0, "-h" },
> { 0, "--help" },
>
^ permalink raw reply
* [net-next.git 2/4] stmmac: do not use strict_strtoul but kstrtoul
From: Giuseppe CAVALLARO @ 2012-06-12 12:45 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro
In-Reply-To: <1339505153-26731-1-git-send-email-peppe.cavallaro@st.com>
This patch replaces the obsolete strict_strtoul with kstrtoul.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 ++++++++-------------
1 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8899e10..e33abf5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2126,42 +2126,36 @@ static int __init stmmac_cmdline_opt(char *str)
return -EINVAL;
while ((opt = strsep(&str, ",")) != NULL) {
if (!strncmp(opt, "debug:", 6)) {
- if (strict_strtoul(opt + 6, 0, (unsigned long *)&debug))
+ if (kstrtoul(opt + 6, 0, (unsigned long *)&debug))
goto err;
} else if (!strncmp(opt, "phyaddr:", 8)) {
- if (strict_strtoul(opt + 8, 0,
- (unsigned long *)&phyaddr))
+ if (kstrtoul(opt + 8, 0, (unsigned long *)&phyaddr))
goto err;
} else if (!strncmp(opt, "dma_txsize:", 11)) {
- if (strict_strtoul(opt + 11, 0,
- (unsigned long *)&dma_txsize))
+ if (kstrtoul(opt + 11, 0, (unsigned long *)&dma_txsize))
goto err;
} else if (!strncmp(opt, "dma_rxsize:", 11)) {
- if (strict_strtoul(opt + 11, 0,
+ if (kstrtoul(opt + 11, 0,
(unsigned long *)&dma_rxsize))
goto err;
} else if (!strncmp(opt, "buf_sz:", 7)) {
- if (strict_strtoul(opt + 7, 0,
- (unsigned long *)&buf_sz))
+ if (kstrtoul(opt + 7, 0, (unsigned long *)&buf_sz))
goto err;
} else if (!strncmp(opt, "tc:", 3)) {
- if (strict_strtoul(opt + 3, 0, (unsigned long *)&tc))
+ if (kstrtoul(opt + 3, 0, (unsigned long *)&tc))
goto err;
} else if (!strncmp(opt, "watchdog:", 9)) {
- if (strict_strtoul(opt + 9, 0,
- (unsigned long *)&watchdog))
+ if (kstrtoul(opt + 9, 0, (unsigned long *)&watchdog))
goto err;
} else if (!strncmp(opt, "flow_ctrl:", 10)) {
- if (strict_strtoul(opt + 10, 0,
- (unsigned long *)&flow_ctrl))
+ if (kstrtoul(opt + 10, 0, (unsigned long *)&flow_ctrl))
goto err;
} else if (!strncmp(opt, "pause:", 6)) {
- if (strict_strtoul(opt + 6, 0, (unsigned long *)&pause))
+ if (kstrtoul(opt + 6, 0, (unsigned long *)&pause))
goto err;
#ifdef CONFIG_STMMAC_TIMER
} else if (!strncmp(opt, "tmrate:", 7)) {
- if (strict_strtoul(opt + 7, 0,
- (unsigned long *)&tmrate))
+ if (kstrtoul(opt + 7, 0, (unsigned long *)&tmrate))
goto err;
#endif
}
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 1/4 (v4)] phy: add the EEE support and the way to access to the MMD registers.
From: Giuseppe CAVALLARO @ 2012-06-12 12:45 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro
In-Reply-To: <1339505153-26731-1-git-send-email-peppe.cavallaro@st.com>
This patch adds the support for the Energy-Efficient Ethernet (EEE)
to the Physical Abstraction Layer.
To support the EEE we have to access to the MMD registers 3.20 and
7.60/61. So two new functions have been added to read/write the MMD
registers (clause 45).
An Ethernet driver (I tested the stmmac) can invoke the phy_init_eee to properly
check if the EEE is supported by the PHYs and it can also set the clock
stop enable bit in the 3.0 register.
The phy_get_eee_err can be used for reporting the number of time where
the PHY failed to complete its normal wake sequence.
In the end, this patch also adds the EEE ethtool support implementing:
o phy_ethtool_set_eee
o phy_ethtool_get_eee
v1: initial patch
v2: fixed some errors especially on naming convention
v3: renamed again the mmd read/write functions thank to Ben's feedback
v4: moved file to phy.c and added the ethtool support.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/phy/phy.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mdio.h | 21 +++-
include/linux/mii.h | 11 ++
include/linux/phy.h | 5 +
4 files changed, 295 insertions(+), 4 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2e1c237..39ae424 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -35,6 +35,7 @@
#include <linux/phy.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <linux/mdio.h>
#include <linux/atomic.h>
#include <asm/io.h>
@@ -967,3 +968,264 @@ void phy_state_machine(struct work_struct *work)
schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
}
+
+static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
+ int addr)
+{
+ /* Write the desired MMD Devad */
+ bus->write(bus, addr, MII_MMD_CTRL, devad);
+
+ /* Write the desired MMD register address */
+ bus->write(bus, addr, MII_MMD_DATA, prtad);
+
+ /* Select the Function : DATA with no post increment */
+ bus->write(bus, addr, MII_MMD_CTRL,
+ (devad | MII_MMD_CTRL_FUNC_DATA_NOINCR));
+}
+
+/**
+ * phy_read_mmd_indirect - reads data from the MMC register (clause 22 to
+ * access to clause 45)
+ * @bus: the target MII bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ *
+ * Description: Reads data from the MMD regisetrs of the
+ * phy addr. To read these register we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Read reg 14 // Read MMD data
+ */
+static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
+ int addr)
+{
+ u32 ret;
+
+ mmd_phy_indirect(bus, prtad, devad, addr);
+
+ /* Read the content of the MMD's selected register */
+ ret = bus->read(bus, addr, MII_MMD_DATA);
+
+ return ret;
+}
+
+/**
+ * phy_write_mmd_indirect - writes data to the MMC register (clause 22 to
+ * access to clause 45)
+ * @bus: the target MII bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ * @data: data to write in the MMD register
+ *
+ * Description: Reads data from the MMD regisetrs of the
+ * phy addr. To read these register we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Write reg 14 // Write MMD data
+ */
+static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
+ int addr, u32 data)
+{
+ mmd_phy_indirect(bus, prtad, devad, addr);
+
+ /* Write the data into MMD's selected register */
+ bus->write(bus, addr, MII_MMD_DATA, data);
+}
+
+/* phy_init_eee
+ * @phydev: target phy_device struct
+ * @clk_stop_enable: PHY may stop the clock during LPI
+ *
+ * Description: it checks if the Energy-Efficient Ethernet (EEE)
+ * is supported by looking at the MMD registers 3.20 and 7.60/61
+ * and it programs the MMD register 3.0 setting the "Clock stop enable"
+ * bit if required.
+ * In fact, the clk_stop_enable can be passed to:
+ * 1 = The PHY may stop the clock during LPI
+ * 0 = Clock not stoppable
+ */
+int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
+{
+ int ret = -EPROTONOSUPPORT;
+
+ /* According to 802.3az,the EEE is supported only in full duplex-mode.
+ * Also EEE feature is active when core is operating with MII, GMII
+ * or RGMII.
+ */
+ if ((phydev->duplex == DUPLEX_FULL) &&
+ ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
+ (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
+ int eee_cap, eee_link;
+
+ /* EEE ability must be supported in both local and remote
+ * PHY devices.
+ */
+ eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+ MDIO_MMD_AN, phydev->addr);
+ if (eee_cap < 0)
+ return eee_cap;
+
+ eee_link = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+ MDIO_MMD_PCS, phydev->addr);
+ if (eee_link < 0)
+ return eee_link;
+
+ if (eee_cap && eee_link) {
+ if (clk_stop_enable) {
+ /* Configure the PHY to stop receiving xMII
+ * clock while it is signaling LPI
+ */
+ int ctrl;
+ ctrl = phy_read_mmd_indirect(phydev->bus,
+ MDIO_CTRL1,
+ MDIO_MMD_PCS,
+ phydev->addr);
+ if (ctrl < 0)
+ return ctrl;
+
+ ctrl |= MDIO_PCS_CTRL1_CLKSTOP_EN;
+ phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
+ MDIO_MMD_PCS,
+ phydev->addr, ctrl);
+ }
+
+ ret = 0; /* EEE supported */
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(phy_init_eee);
+
+/* phy_get_eee_err
+ * @phydev: target phy_device struct
+ *
+ * Description: it is to report the number of time where the PHY
+ * failed to complete its normal wake sequence.
+ */
+int phy_get_eee_err(struct phy_device *phydev)
+{
+ return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
+ MDIO_MMD_PCS, phydev->addr);
+
+}
+EXPORT_SYMBOL(phy_get_eee_err);
+
+static int phy_eee_to_adv(int eee_adv)
+{
+ int adv = 0;
+
+ if (eee_adv & MDIO_EEE_100TX)
+ adv |= ADVERTISED_100baseT_Full;
+ if (eee_adv & MDIO_EEE_1000T)
+ adv |= ADVERTISED_1000baseT_Full;
+ if (eee_adv & MDIO_EEE_10GT)
+ adv |= ADVERTISED_10000baseT_Full;
+ if (eee_adv & MDIO_EEE_1000KX)
+ adv |= ADVERTISED_1000baseKX_Full;
+ if (eee_adv & MDIO_EEE_10GKX4)
+ adv |= ADVERTISED_10000baseKX4_Full;
+ if (eee_adv & MDIO_EEE_10GKR)
+ adv |= ADVERTISED_10000baseKR_Full;
+
+ return adv;
+}
+
+static int phy_eee_to_supported(int eee_supported)
+{
+ int supported = 0;
+
+ if (eee_supported & MDIO_EEE_100TX)
+ supported |= SUPPORTED_100baseT_Full;
+ if (eee_supported & MDIO_EEE_1000T)
+ supported |= SUPPORTED_1000baseT_Full;
+ if (eee_supported & MDIO_EEE_10GT)
+ supported |= SUPPORTED_10000baseT_Full;
+ if (eee_supported & MDIO_EEE_1000KX)
+ supported |= SUPPORTED_1000baseKX_Full;
+ if (eee_supported & MDIO_EEE_10GKX4)
+ supported |= SUPPORTED_10000baseKX4_Full;
+ if (eee_supported & MDIO_EEE_10GKR)
+ supported |= SUPPORTED_10000baseKR_Full;
+
+ return supported;
+}
+
+/* phy_ethtool_get_eee
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it reportes the Supported/Advertisement/LP Advertisement
+ * capabilities.
+ */
+int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+ int val;
+
+ /* Get Supported EEE */
+ val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+ MDIO_MMD_PCS, phydev->addr);
+ if (val < 0)
+ return val;
+ data->supported = phy_eee_to_supported(val);
+
+ /* Get advertisement EEE */
+ val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+ MDIO_MMD_AN, phydev->addr);
+ if (val < 0)
+ return val;
+ data->advertised = phy_eee_to_adv(val);
+
+ /* Get LP advertisement EEE */
+ val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+ MDIO_MMD_AN, phydev->addr);
+ if (val < 0)
+ return val;
+ data->lp_advertised = phy_eee_to_adv(val);
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_get_eee);
+
+static int phy_adv_to_eee(int adv)
+{
+ int reg = 0;
+
+ if (adv & ADVERTISED_100baseT_Full)
+ reg |= MDIO_EEE_100TX;
+ if (adv & ADVERTISED_1000baseT_Full)
+ reg |= MDIO_EEE_1000T;
+ if (adv & ADVERTISED_10000baseT_Full)
+ reg |= MDIO_EEE_10GT;
+ if (adv & ADVERTISED_1000baseKX_Full)
+ reg |= MDIO_EEE_1000KX;
+ if (adv & ADVERTISED_10000baseKX4_Full)
+ reg |= MDIO_EEE_10GKX4;
+ if (adv & ADVERTISED_10000baseKR_Full)
+ reg |= MDIO_EEE_10GKR;
+
+ return reg;
+}
+
+/* phy_ethtool_set_eee
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it is to program the Advertisement EEE register.
+ */
+int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+ int val;
+
+ val = phy_adv_to_eee(data->advertised);
+ phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
+ phydev->addr, val);
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_set_eee);
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index dfb9479..4ad8f0e 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -43,7 +43,11 @@
#define MDIO_PKGID2 15
#define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */
#define MDIO_AN_LPA 19 /* AN LP abilities (base page) */
+#define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */
+#define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */
#define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */
+#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
+#define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */
/* Media-dependent registers. */
#define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */
@@ -56,7 +60,6 @@
#define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */
#define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */
#define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */
-#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
/* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */
#define MDIO_PMA_LASI_RXCTRL 0x9000 /* RX_ALARM control */
@@ -82,6 +85,7 @@
#define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART
#define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE
#define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */
+#define MDIO_PCS_CTRL1_CLKSTOP_EN 0x400 /* Stop the clock during LPI */
/* 10 Gb/s */
#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00)
@@ -237,9 +241,18 @@
#define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */
#define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */
-/* AN EEE Advertisement register. */
-#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */
-#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */
+/* EEE Supported/Advertisement/LP Advertisement registers.
+ *
+ * EEE capability Register (3.20), Advertisement (7.60) and
+ * Link partner ability (7.61) registers have and can use the same identical
+ * bit masks.
+ */
+#define MDIO_EEE_100TX 0x0002 /* 100TX EEE cap */
+#define MDIO_EEE_1000T 0x0004 /* 1000T EEE cap */
+#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */
+#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */
+#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */
+#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */
/* LASI RX_ALARM control/status registers. */
#define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 2783eca..35ddda1 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -21,6 +21,8 @@
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
+#define MII_MMD_CTRL 0x0d /* MMD Access Control Register */
+#define MII_MMD_DATA 0x0e /* MMD Access Data Register */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
@@ -141,6 +143,15 @@
#define FLOW_CTRL_TX 0x01
#define FLOW_CTRL_RX 0x02
+/* MMD Access Control register fields */
+#define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/
+#define MII_MMD_CTRL_FUNC_ADDR 0x0000 /* Address */
+#define MII_MMD_CTRL_FUNC_DATA_NOINCR 0x4000 /* no post increment */
+#define MII_MMD_CTRL_FUNC_DATA_INCR_ON_RDWT 0x8000 /* post increment on
+ * reads & writes */
+#define MII_MMD_CTRL_FUNC_DATA_INCR_ON_WT 0xC000 /* post increment on
+ * writes only */
+
/* This structure is used in all SIOCxMIIxxx ioctl calls */
struct mii_ioctl_data {
__u16 phy_id;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c291cae..97fc4cf 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -532,6 +532,11 @@ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));
int phy_scan_fixups(struct phy_device *phydev);
+int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
+int phy_get_eee_err(struct phy_device *phydev);
+int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
+int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
+
int __init mdio_bus_init(void);
void mdio_bus_exit(void);
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 0/4] EEE for PAL and stmmac
From: Giuseppe CAVALLARO @ 2012-06-12 12:45 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro
These patches add the EEE support in the stmmac device driver
restoring an old work I had done some months ago and not
completed in time.
I've tested all on ST STB with the IC+ 101G PHY device that has
this feature.
The initial EEE support for the stmmac has been written by Rayagond
but I have reworked all his code adding new parts and especially
performing tests on a real hardware. Thx Rayagond!
In these patches, we can see that the stmmac supports the EEE
only if the DMA HW capability register says that this
feature is actually available. In that case, the driver can enter
in the Tx LPI mode by using a timer as recommended by Synopsys.
Note that EEE is supported in new chip generations; in particular
I used the 3.61a.
At any rate, further information about how the driver treats the EEE
can be found in the stmmac.txt file (there is a patch for that).
Another patch is for Physical Abstraction Layer now able to
manage the MMD registers (clause 45); it also provides the ethtool
support to manage supported/advertisement/lp adv features.
Giuseppe Cavallaro (4):
phy: add the EEE support and the way to access to the MMD registers.
stmmac: do not use strict_strtoul but kstrtoul
stmmac: update the driver Documentation and add EEE
stmmac: add the Energy Efficient Ethernet support
Documentation/networking/stmmac.txt | 36 +++-
drivers/net/ethernet/stmicro/stmmac/common.h | 31 +++-
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 20 ++
.../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 101 +++++++-
.../net/ethernet/stmicro/stmmac/dwmac100_core.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 8 +
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 55 ++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 192 +++++++++++++--
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +
drivers/net/phy/phy.c | 262 ++++++++++++++++++++
include/linux/mdio.h | 21 ++-
include/linux/mii.h | 11 +
include/linux/phy.h | 5 +
14 files changed, 705 insertions(+), 44 deletions(-)
--
1.7.4.4
^ permalink raw reply
* [net-next.git 4/4 (v4)] stmmac: add the Energy Efficient Ethernet support
From: Giuseppe CAVALLARO @ 2012-06-12 12:45 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro
In-Reply-To: <1339505153-26731-1-git-send-email-peppe.cavallaro@st.com>
This patch adds the Energy Efficient Ethernet support to the stmmac.
Please see the driver's documentation for further details about this support
in the driver.
Thanks also goes to Rayagond Kokatanur for his first implementation.
v1: initial patch
v2: fixed some sparse issues (typos)
v3: erroneously sent the v2 renamed as v3
v4:
o Fixed the return value of the stmmac_eee_init as suggested by D.Miller
o Totally reviewed the ethtool support for EEE
o Added a new internal parameter to tune the SW timer for TX LPI.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 31 ++++-
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 20 +++
.../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 101 +++++++++++-
.../net/ethernet/stmicro/stmmac/dwmac100_core.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 8 +
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 55 +++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 166 +++++++++++++++++++-
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +
9 files changed, 370 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index bcd54d6..e2d0832 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -95,6 +95,16 @@ struct stmmac_extra_stats {
unsigned long poll_n;
unsigned long sched_timer_n;
unsigned long normal_irq_n;
+ unsigned long mmc_tx_irq_n;
+ unsigned long mmc_rx_irq_n;
+ unsigned long mmc_rx_csum_offload_irq_n;
+ /* EEE */
+ unsigned long irq_receive_pmt_irq_n;
+ unsigned long irq_tx_path_in_lpi_mode_n;
+ unsigned long irq_tx_path_exit_lpi_mode_n;
+ unsigned long irq_rx_path_in_lpi_mode_n;
+ unsigned long irq_rx_path_exit_lpi_mode_n;
+ unsigned long phy_eee_wakeup_error_n;
};
/* CSR Frequency Access Defines*/
@@ -162,6 +172,17 @@ enum tx_dma_irq_status {
handle_tx_rx = 3,
};
+enum core_specific_irq_mask {
+ core_mmc_tx_irq = 1,
+ core_mmc_rx_irq = 2,
+ core_mmc_rx_csum_offload_irq = 4,
+ core_irq_receive_pmt_irq = 8,
+ core_irq_tx_path_in_lpi_mode = 16,
+ core_irq_tx_path_exit_lpi_mode = 32,
+ core_irq_rx_path_in_lpi_mode = 64,
+ core_irq_rx_path_exit_lpi_mode = 128,
+};
+
/* DMA HW capabilities */
struct dma_features {
unsigned int mbps_10_100;
@@ -208,6 +229,10 @@ struct dma_features {
#define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */
#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */
+/* Default LPI timers */
+#define STMMAC_DEFAULT_LIT_LS_TIMER 0x3E8
+#define STMMAC_DEFAULT_TWT_LS_TIMER 0x0
+
struct stmmac_desc_ops {
/* DMA RX descriptor ring initialization */
void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
@@ -278,7 +303,7 @@ struct stmmac_ops {
/* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */
- void (*host_irq_status) (void __iomem *ioaddr);
+ int (*host_irq_status) (void __iomem *ioaddr);
/* Multicast filter setting */
void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */
@@ -291,6 +316,10 @@ struct stmmac_ops {
unsigned int reg_n);
void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n);
+ void (*set_eee_mode) (void __iomem *ioaddr);
+ void (*reset_eee_mode) (void __iomem *ioaddr);
+ void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
+ void (*set_eee_pls) (void __iomem *ioaddr, int link);
};
struct mac_link {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 23478bf..f90fcb5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -36,6 +36,7 @@
#define GMAC_INT_STATUS 0x00000038 /* interrupt status register */
enum dwmac1000_irq_status {
+ lpiis_irq = 0x400,
time_stamp_irq = 0x0200,
mmc_rx_csum_offload_irq = 0x0080,
mmc_tx_irq = 0x0040,
@@ -60,6 +61,25 @@ enum power_event {
power_down = 0x00000001,
};
+/* Energy Efficient Ethernet (EEE)
+ *
+ * LPI status, timer and control register offset
+ */
+#define LPI_CTRL_STATUS 0x0030
+#define LPI_TIMER_CTRL 0x0034
+
+/* LPI control and status defines */
+#define LPI_CTRL_STATUS_LPITXA 0x00080000 /* Enable LPI TX Automate */
+#define LPI_CTRL_STATUS_PLSEN 0x00040000 /* Enable PHY Link Status */
+#define LPI_CTRL_STATUS_PLS 0x00020000 /* PHY Link Status */
+#define LPI_CTRL_STATUS_LPIEN 0x00010000 /* LPI Enable */
+#define LPI_CTRL_STATUS_RLPIST 0x00000200 /* Receive LPI state */
+#define LPI_CTRL_STATUS_TLPIST 0x00000100 /* Transmit LPI state */
+#define LPI_CTRL_STATUS_RLPIEX 0x00000008 /* Receive LPI Exit */
+#define LPI_CTRL_STATUS_RLPIEN 0x00000004 /* Receive LPI Entry */
+#define LPI_CTRL_STATUS_TLPIEX 0x00000002 /* Transmit LPI Exit */
+#define LPI_CTRL_STATUS_TLPIEN 0x00000001 /* Transmit LPI Entry */
+
/* GMAC HW ADDR regs */
#define GMAC_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \
(reg * 8))
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b5e4d02..bfe0226 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -194,26 +194,107 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
}
-static void dwmac1000_irq_status(void __iomem *ioaddr)
+static int dwmac1000_irq_status(void __iomem *ioaddr)
{
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+ int status = 0;
/* Not used events (e.g. MMC interrupts) are not handled. */
- if ((intr_status & mmc_tx_irq))
- CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
+ if ((intr_status & mmc_tx_irq)) {
+ CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_TX_INTR));
- if (unlikely(intr_status & mmc_rx_irq))
- CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
+ status |= core_mmc_tx_irq;
+ }
+ if (unlikely(intr_status & mmc_rx_irq)) {
+ CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_INTR));
- if (unlikely(intr_status & mmc_rx_csum_offload_irq))
- CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
+ status |= core_mmc_rx_irq;
+ }
+ if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
+ CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
+ status |= core_mmc_rx_csum_offload_irq;
+ }
if (unlikely(intr_status & pmt_irq)) {
- CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
+ CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
/* clear the PMT bits 5 and 6 by reading the PMT
* status register. */
readl(ioaddr + GMAC_PMT);
+ status |= core_irq_receive_pmt_irq;
}
+ /* MAC trx/rx EEE LPI entry/exit interrupts */
+ if (intr_status & lpiis_irq) {
+ /* Clean LPI interrupt by reading the Reg 12 */
+ u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);
+
+ if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
+ CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
+ status |= core_irq_tx_path_in_lpi_mode;
+ }
+ if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
+ CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
+ status |= core_irq_tx_path_exit_lpi_mode;
+ }
+ if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
+ CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
+ status |= core_irq_rx_path_in_lpi_mode;
+ }
+ if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
+ CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
+ status |= core_irq_rx_path_exit_lpi_mode;
+ }
+ }
+
+ return status;
+}
+
+static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
+{
+ u32 value;
+
+ /* Enable the link status receive on RGMII, SGMII ore SMII
+ * receive path and instruct the transmit to enter in LPI
+ * state. */
+ value = readl(ioaddr + LPI_CTRL_STATUS);
+ value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
+ writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+{
+ u32 value;
+
+ value = readl(ioaddr + LPI_CTRL_STATUS);
+ value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
+ writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+{
+ u32 value;
+
+ value = readl(ioaddr + LPI_CTRL_STATUS);
+
+ if (link)
+ value |= LPI_CTRL_STATUS_PLS;
+ else
+ value &= ~LPI_CTRL_STATUS_PLS;
+
+ writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+{
+ int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
+
+ /* Program the timers in the LPI timer control register:
+ * LS: minimum time (ms) for which the link
+ * status from PHY should be ok before transmitting
+ * the LPI pattern.
+ * TW: minimum time (us) for which the core waits
+ * after it has stopped transmitting the LPI pattern.
+ */
+ writel(value, ioaddr + LPI_TIMER_CTRL);
}
static const struct stmmac_ops dwmac1000_ops = {
@@ -226,6 +307,10 @@ static const struct stmmac_ops dwmac1000_ops = {
.pmt = dwmac1000_pmt,
.set_umac_addr = dwmac1000_set_umac_addr,
.get_umac_addr = dwmac1000_get_umac_addr,
+ .set_eee_mode = dwmac1000_set_eee_mode,
+ .reset_eee_mode = dwmac1000_reset_eee_mode,
+ .set_eee_timer = dwmac1000_set_eee_timer,
+ .set_eee_pls = dwmac1000_set_eee_pls,
};
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 19e0f4e..f83210e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,9 +72,9 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
return 0;
}
-static void dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(void __iomem *ioaddr)
{
- return;
+ return 0;
}
static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 6e0360f..e678ce3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -70,6 +70,7 @@
#define DMA_INTR_DEFAULT_MASK (DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
/* DMA Status register defines */
+#define DMA_STATUS_GLPII 0x40000000 /* GMAC LPI interrupt */
#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */
#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 6d07ba2..777771a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -86,6 +86,12 @@ struct stmmac_priv {
#endif
int clk_csr;
int synopsys_id;
+ struct timer_list eee_ctrl_timer;
+ bool tx_path_in_lpi_mode;
+ int lpi_irq;
+ int eee_enabled;
+ int eee_active;
+ int tx_lpi_timer;
};
extern int phyaddr;
@@ -105,6 +111,8 @@ int stmmac_dvr_remove(struct net_device *ndev);
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat,
void __iomem *addr);
+void stmmac_disable_eee_mode(struct stmmac_priv *priv);
+bool stmmac_eee_init(struct stmmac_priv *priv);
#ifdef CONFIG_HAVE_CLK
static inline int stmmac_clk_enable(struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index ce43184..d6014f5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -93,6 +93,16 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(poll_n),
STMMAC_STAT(sched_timer_n),
STMMAC_STAT(normal_irq_n),
+ STMMAC_STAT(normal_irq_n),
+ STMMAC_STAT(mmc_tx_irq_n),
+ STMMAC_STAT(mmc_rx_irq_n),
+ STMMAC_STAT(mmc_rx_csum_offload_irq_n),
+ STMMAC_STAT(irq_receive_pmt_irq_n),
+ STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
+ STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
+ STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
+ STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
+ STMMAC_STAT(phy_eee_wakeup_error_n),
};
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
@@ -366,6 +376,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
(*(u32 *)p);
}
}
+ if (priv->eee_enabled) {
+ int val = phy_get_eee_err(priv->phydev);
+ if (val)
+ priv->xstats.phy_eee_wakeup_error_n = val;
+ }
}
for (i = 0; i < STMMAC_STATS_LEN; i++) {
char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
@@ -464,6 +479,44 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
return 0;
}
+static int stmmac_ethtool_op_get_eee(struct net_device *dev,
+ struct ethtool_eee *edata)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ if (!priv->dma_cap.eee)
+ return -EOPNOTSUPP;
+
+ edata->eee_enabled = priv->eee_enabled;
+ edata->eee_active = priv->eee_active;
+ edata->tx_lpi_timer = priv->tx_lpi_timer;
+
+ return phy_ethtool_get_eee(priv->phydev, edata);
+}
+
+static int stmmac_ethtool_op_set_eee(struct net_device *dev,
+ struct ethtool_eee *edata)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ priv->eee_enabled = edata->eee_enabled;
+
+ if (!priv->eee_enabled)
+ stmmac_disable_eee_mode(priv);
+ else {
+ /* We are asking for enabling the EEE but it is safe
+ * to verify all by invoking the eee_init function.
+ * In case of failure it will return an error.
+ */
+ priv->tx_lpi_timer = edata->tx_lpi_timer;
+ priv->eee_enabled = stmmac_eee_init(priv);
+ if (!priv->eee_enabled)
+ return -EPERM;
+ }
+
+ return phy_ethtool_set_eee(priv->phydev, edata);
+}
+
static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -480,6 +533,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.get_strings = stmmac_get_strings,
.get_wol = stmmac_get_wol,
.set_wol = stmmac_set_wol,
+ .get_eee = stmmac_ethtool_op_get_eee,
+ .set_eee = stmmac_ethtool_op_set_eee,
.get_sset_count = stmmac_get_sset_count,
.get_ts_info = ethtool_op_get_ts_info,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e33abf5..05e1af7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -134,6 +134,12 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_IFUP |
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
+#define STMMAC_DEFAULT_LPI_TIMER 1000
+static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
+module_param(eee_timer, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
+#define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
+
static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
#ifdef CONFIG_STMMAC_DEBUG_FS
@@ -162,6 +168,8 @@ static void stmmac_verify_args(void)
flow_ctrl = FLOW_OFF;
if (unlikely((pause < 0) || (pause > 0xffff)))
pause = PAUSE_TIME;
+ if (eee_timer < 0)
+ eee_timer = STMMAC_DEFAULT_LPI_TIMER;
}
static void stmmac_clk_csr_set(struct stmmac_priv *priv)
@@ -230,6 +238,85 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
phydev->speed);
}
+static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
+{
+ /* Check and enter in LPI mode */
+ if ((priv->dirty_tx == priv->cur_tx) &&
+ (priv->tx_path_in_lpi_mode == false))
+ priv->hw->mac->set_eee_mode(priv->ioaddr);
+}
+
+void stmmac_disable_eee_mode(struct stmmac_priv *priv)
+{
+ /* Exit and disable EEE in case of we are are in LPI state. */
+ priv->hw->mac->reset_eee_mode(priv->ioaddr);
+ del_timer_sync(&priv->eee_ctrl_timer);
+ priv->tx_path_in_lpi_mode = false;
+}
+
+/**
+ * stmmac_eee_ctrl_timer
+ * @arg : data hook
+ * Description:
+ * If there is no data transfer and if we are not in LPI state,
+ * then MAC Transmitter can be moved to LPI state.
+ */
+static void stmmac_eee_ctrl_timer(unsigned long arg)
+{
+ struct stmmac_priv *priv = (struct stmmac_priv *)arg;
+
+ stmmac_enable_eee_mode(priv);
+ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+}
+
+/**
+ * stmmac_eee_init
+ * @priv: private device pointer
+ * Description:
+ * If the EEE support has been enabled while configuring the driver,
+ * if the GMAC actually supports the EEE (from the HW cap reg) and the
+ * phy can also manage EEE, so enable the LPI state and start the timer
+ * to verify if the tx path can enter in LPI state.
+ */
+bool stmmac_eee_init(struct stmmac_priv *priv)
+{
+ bool ret = false;
+
+ /* MAC core supports the EEE feature. */
+ if (priv->dma_cap.eee) {
+ /* Check if the PHY supports EEE */
+ if (phy_init_eee(priv->phydev, 1))
+ goto out;
+
+ priv->eee_active = 1;
+ init_timer(&priv->eee_ctrl_timer);
+ priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
+ priv->eee_ctrl_timer.data = (unsigned long)priv;
+ priv->eee_ctrl_timer.expires = STMMAC_LPI_TIMER(eee_timer);
+ add_timer(&priv->eee_ctrl_timer);
+
+ priv->hw->mac->set_eee_timer(priv->ioaddr,
+ STMMAC_DEFAULT_LIT_LS_TIMER,
+ priv->tx_lpi_timer);
+
+ pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
+
+ ret = true;
+ }
+out:
+ return ret;
+}
+
+static void stmmac_eee_adjust(struct stmmac_priv *priv)
+{
+ /* When the EEE has been already initialised we have to
+ * modify the PLS bit in the LPI ctrl & status reg according
+ * to the PHY link status. For this reason.
+ */
+ if (priv->eee_enabled)
+ priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
+}
+
/**
* stmmac_adjust_link
* @dev: net device structure
@@ -250,6 +337,7 @@ static void stmmac_adjust_link(struct net_device *dev)
phydev->addr, phydev->link);
spin_lock_irqsave(&priv->lock, flags);
+
if (phydev->link) {
u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
@@ -316,6 +404,8 @@ static void stmmac_adjust_link(struct net_device *dev)
if (new_state && netif_msg_link(priv))
phy_print_status(phydev);
+ stmmac_eee_adjust(priv);
+
spin_unlock_irqrestore(&priv->lock, flags);
DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
@@ -333,7 +423,7 @@ static int stmmac_init_phy(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct phy_device *phydev;
- char phy_id[MII_BUS_ID_SIZE + 3];
+ char phy_id_fmt[MII_BUS_ID_SIZE + 3];
char bus_id[MII_BUS_ID_SIZE];
int interface = priv->plat->interface;
priv->oldlink = 0;
@@ -347,11 +437,12 @@ static int stmmac_init_phy(struct net_device *dev)
snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
priv->plat->bus_id);
- snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+ snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
priv->plat->phy_addr);
- pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id);
+ pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt);
- phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface);
+ phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 0,
+ interface);
if (IS_ERR(phydev)) {
pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -690,6 +781,11 @@ static void stmmac_tx(struct stmmac_priv *priv)
}
netif_tx_unlock(priv->dev);
}
+
+ if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
+ stmmac_enable_eee_mode(priv);
+ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+ }
spin_unlock(&priv->tx_lock);
}
@@ -1028,6 +1124,17 @@ static int stmmac_open(struct net_device *dev)
}
}
+ /* Request the IRQ lines */
+ if (priv->lpi_irq != -ENXIO) {
+ ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (unlikely(ret < 0)) {
+ pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
+ __func__, priv->lpi_irq, ret);
+ goto open_error_lpiirq;
+ }
+ }
+
/* Enable the MAC Rx/Tx */
stmmac_set_mac(priv->ioaddr, true);
@@ -1063,12 +1170,19 @@ static int stmmac_open(struct net_device *dev)
if (priv->phydev)
phy_start(priv->phydev);
+ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
+ priv->eee_enabled = stmmac_eee_init(priv);
+
napi_enable(&priv->napi);
skb_queue_head_init(&priv->rx_recycle);
netif_start_queue(dev);
return 0;
+open_error_lpiirq:
+ if (priv->wol_irq != dev->irq)
+ free_irq(priv->wol_irq, dev);
+
open_error_wolirq:
free_irq(dev->irq, dev);
@@ -1094,6 +1208,9 @@ static int stmmac_release(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ if (priv->eee_enabled)
+ del_timer_sync(&priv->eee_ctrl_timer);
+
/* Stop and disconnect the PHY */
if (priv->phydev) {
phy_stop(priv->phydev);
@@ -1116,6 +1233,8 @@ static int stmmac_release(struct net_device *dev)
free_irq(dev->irq, dev);
if (priv->wol_irq != dev->irq)
free_irq(priv->wol_irq, dev);
+ if (priv->lpi_irq != -ENXIO)
+ free_irq(priv->lpi_irq, dev);
/* Stop TX/RX DMA and clear the descriptors */
priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1165,6 +1284,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock(&priv->tx_lock);
+ if (priv->tx_path_in_lpi_mode)
+ stmmac_disable_eee_mode(priv);
+
entry = priv->cur_tx % txsize;
#ifdef STMMAC_XMIT_DEBUG
@@ -1541,10 +1663,37 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
- if (priv->plat->has_gmac)
- /* To handle GMAC own interrupts */
- priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
+ /* To handle GMAC own interrupts */
+ if (priv->plat->has_gmac) {
+ int status = priv->hw->mac->host_irq_status((void __iomem *)
+ dev->base_addr);
+ if (unlikely(status)) {
+ if (status & core_mmc_tx_irq)
+ priv->xstats.mmc_tx_irq_n++;
+ if (status & core_mmc_rx_irq)
+ priv->xstats.mmc_rx_irq_n++;
+ if (status & core_mmc_rx_csum_offload_irq)
+ priv->xstats.mmc_rx_csum_offload_irq_n++;
+ if (status & core_irq_receive_pmt_irq)
+ priv->xstats.irq_receive_pmt_irq_n++;
+
+ /* For LPI we need to save the tx status */
+ if (status & core_irq_tx_path_in_lpi_mode) {
+ priv->xstats.irq_tx_path_in_lpi_mode_n++;
+ priv->tx_path_in_lpi_mode = true;
+ }
+ if (status & core_irq_tx_path_exit_lpi_mode) {
+ priv->xstats.irq_tx_path_exit_lpi_mode_n++;
+ priv->tx_path_in_lpi_mode = false;
+ }
+ if (status & core_irq_rx_path_in_lpi_mode)
+ priv->xstats.irq_rx_path_in_lpi_mode_n++;
+ if (status & core_irq_rx_path_exit_lpi_mode)
+ priv->xstats.irq_rx_path_exit_lpi_mode_n++;
+ }
+ }
+ /* To handle DMA interrupts */
stmmac_dma_interrupt(priv);
return IRQ_HANDLED;
@@ -2153,6 +2302,9 @@ static int __init stmmac_cmdline_opt(char *str)
} else if (!strncmp(opt, "pause:", 6)) {
if (kstrtoul(opt + 6, 0, (unsigned long *)&pause))
goto err;
+ } else if (!strncmp(opt, "eee_timer:", 6)) {
+ if (kstrtoul(opt + 10, 0, (unsigned long *)&eee_timer))
+ goto err;
#ifdef CONFIG_STMMAC_TIMER
} else if (!strncmp(opt, "tmrate:", 7)) {
if (kstrtoul(opt + 7, 0, (unsigned long *)&tmrate))
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 20eb502..7d36163 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -156,6 +156,8 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
if (priv->wol_irq == -ENXIO)
priv->wol_irq = priv->dev->irq;
+ priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
+
platform_set_drvdata(pdev, priv->dev);
pr_debug("STMMAC platform driver registration completed");
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 3/4] stmmac: update the driver Documentation and add EEE
From: Giuseppe CAVALLARO @ 2012-06-12 12:45 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, rayagond, davem, yuvalmin, Giuseppe Cavallaro
In-Reply-To: <1339505153-26731-1-git-send-email-peppe.cavallaro@st.com>
This patch updates the stmmac's documentation adding
some missing files in the section used to describe the
internal driver's structure.
Also the patch adds a new section to describe the EEE support.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
Documentation/networking/stmmac.txt | 36 +++++++++++++++++++++++++++++-----
1 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 5cb9a19..c676b9c 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -257,9 +257,11 @@ reset procedure etc).
o Makefile
o stmmac_main.c: main network device driver;
o stmmac_mdio.c: mdio functions;
+ o stmmac_pci: PCI driver;
+ o stmmac_platform.c: platform driver
o stmmac_ethtool.c: ethtool support;
o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
- Only tested on ST40 platforms based.
+ (only tested on ST40 platforms based);
o stmmac.h: private driver structure;
o common.h: common definitions and VFTs;
o descs.h: descriptor structure definitions;
@@ -269,9 +271,11 @@ reset procedure etc).
o dwmac100_core: MAC 100 core and dma code;
o dwmac100_dma.c: dma funtions for the MAC chip;
o dwmac1000.h: specific header file for the MAC;
- o dwmac_lib.c: generic DMA functions shared among chips
- o enh_desc.c: functions for handling enhanced descriptors
- o norm_desc.c: functions for handling normal descriptors
+ o dwmac_lib.c: generic DMA functions shared among chips;
+ o enh_desc.c: functions for handling enhanced descriptors;
+ o norm_desc.c: functions for handling normal descriptors;
+ o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes;
+ o mmc_core.c/mmc.h: Management MAC Counters;
5) Debug Information
@@ -304,7 +308,27 @@ All these are only useful during the developing stage
and should never enabled inside the code for general usage.
In fact, these can generate an huge amount of debug messages.
-6) TODO:
+6) Energy Efficient Ethernet
+
+Energy Efficient Ethernet(EEE) enables IEEE 802.3 MAC sublayer along
+with a family of Physical layer to operate in the Low power Idle(LPI)
+mode. The EEE mode supports the IEEE 802.3 MAC operation at 100Mbps,
+1000Mbps & 10Gbps.
+
+The LPI mode allows power saving by switching off parts of the
+communication device functionality when there is no data to be
+transmitted & received. The system on both the side of the link can
+disable some functionalities & save power during the period of low-link
+utilization. The MAC controls whether the system should enter or exit
+the LPI mode & communicate this to PHY.
+
+As soon as the interface is opened, the driver verifies if the EEE can
+be supported. This is done by looking at both the DMA HW capability
+register and the PHY devices MCD registers.
+To enter in Tx LPI mode the driver needs to have a software timer
+that enable and disable the LPI mode when there is nothing to be
+transmitted.
+
+7) TODO:
o XGMAC is not supported.
- o Add the EEE - Energy Efficient Ethernet
o Add the PTP - precision time protocol
--
1.7.4.4
^ permalink raw reply related
* Re: [PATCH] netpoll: Add support for hardware checksumming on egress
From: Eric Dumazet @ 2012-06-12 12:43 UTC (permalink / raw)
To: Bogdan Hamciuc; +Cc: davem, netdev
In-Reply-To: <1339496765-3093-2-git-send-email-bogdan.hamciuc@freescale.com>
On Tue, 2012-06-12 at 13:26 +0300, Bogdan Hamciuc wrote:
> Netpoll used to compute its own csum; but if the device supports, we
> should let it do the checksum itself.
>
> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
> ---
> net/core/netpoll.c | 14 ++++++++++----
> 1 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> index 9a08068..f5d00b4 100644
> --- a/net/core/netpoll.c
> +++ b/net/core/netpoll.c
> @@ -385,13 +385,19 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
> udph->source = htons(np->local_port);
> udph->dest = htons(np->remote_port);
> udph->len = htons(udp_len);
> - udph->check = 0;
> - udph->check = csum_tcpudp_magic(np->local_ip,
> +
> + /* Only querying the IPv4 csumming capabilities */
> + if (np->dev->features & NETIF_F_IP_CSUM)
> + skb->ip_summed = CHECKSUM_PARTIAL;
> + else {
> + skb->ip_summed = CHECKSUM_NONE;
> + udph->check = csum_tcpudp_magic(np->local_ip,
> np->remote_ip,
> udp_len, IPPROTO_UDP,
> csum_partial(udph, udp_len, 0));
> - if (udph->check == 0)
> - udph->check = CSUM_MANGLED_0;
> + if (udph->check == 0)
> + udph->check = CSUM_MANGLED_0;
> + }
>
> skb_push(skb, sizeof(*iph));
> skb_reset_network_header(skb);
Hi Bogdan
I cant see how this can possibly work ?
Which NIC was able to send a good UDP frame after this patch ?
^ permalink raw reply
* Re: [RFC PATCH net-next] hp100: delete VG/AnyLAN hp100
From: Pavel Machek @ 2012-06-12 12:36 UTC (permalink / raw)
To: Joe Perches
Cc: Paul Gortmaker, linux-kernel, JBottomley, David S. Miller, netdev
In-Reply-To: <1337292547.8872.20.camel@joe2Laptop>
Hi!
On Thu 2012-05-17 15:09:07, Joe Perches wrote:
> On Thu, 2012-05-17 at 17:20 -0400, Paul Gortmaker wrote:
> > [Re: [PATCH 2/5] drivers/net: delete all code/drivers depending on CONFIG_MCA
>
> If we're removing really old and unused stuff,
> how about the VG/AnyLAN driver too?
hp100... I believe it has PCI variants and I have that
somewhere. Please don't kill it.
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: [PATCHv2 net-next] ipv4: Add interface option to enable routing of 127.0.0.0/8
From: Neil Horman @ 2012-06-12 12:32 UTC (permalink / raw)
To: David Miller, netdev
In-Reply-To: <20120612113115.GI28598@canuck.infradead.org>
On Tue, Jun 12, 2012 at 07:31:15AM -0400, Thomas Graf wrote:
> On Tue, Jun 12, 2012 at 07:14:44AM -0400, Neil Horman wrote:
> > Just out of curiosity, would it be more efficient to implement this by
> > optionally adding a prohibit route to the local table for 127.0.0.0/8 to every
> > interface that was brought up, based on weather or not that interfaces
> > route_localnet bool was true or not? It would save the additional checks in the
> > routing path I think. Not sure how much a savings that is, but I thought I
> > would ask.
>
> It's not that simple because we also use the local table for source
> address selection and local address verification. So we would have to
> exclude/include such routes conditionally based on some route lookup
> purpose indicator. Such a prohibit route would have to be valid only
> in the output context.
ah, understood, so that doesn't really save us anything, it just moves the point
at which we do the check.
Acked-by: Neil Horman <nhorman@tuxdriver.com>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH] netpoll: Fix skb tail pointer in netpoll_send_udp()
From: Eric Dumazet @ 2012-06-12 12:22 UTC (permalink / raw)
To: Bogdan Hamciuc; +Cc: davem, netdev
In-Reply-To: <1339496765-3093-1-git-send-email-bogdan.hamciuc@freescale.com>
On Tue, 2012-06-12 at 13:26 +0300, Bogdan Hamciuc wrote:
> As skb->tail wasn't updated after skb_copy_to_linear_data(), subsequent
> calls to skb_realloc_headroom() (as made by an ethernet driver's
> ndo_start_xmit routine) would only effectively copy the packet headers,
> leaving garbage in the payload.
>
> In the process, removed some unnecessary code.
>
> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
> ---
> net/core/netpoll.c | 8 ++++----
> 1 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> index 3d84fb9..9a08068 100644
> --- a/net/core/netpoll.c
> +++ b/net/core/netpoll.c
> @@ -362,22 +362,22 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
>
> void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
> {
> - int total_len, eth_len, ip_len, udp_len;
> + int total_len, ip_len, udp_len;
> struct sk_buff *skb;
> struct udphdr *udph;
> struct iphdr *iph;
> struct ethhdr *eth;
>
> udp_len = len + sizeof(*udph);
> - ip_len = eth_len = udp_len + sizeof(*iph);
> - total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
> + ip_len = udp_len + sizeof(*iph);
> + total_len = ip_len + ETH_HLEN + NET_IP_ALIGN;
>
> skb = find_skb(np, total_len, total_len - len);
> if (!skb)
> return;
>
> skb_copy_to_linear_data(skb, msg, len);
> - skb->len += len;
> + skb_put(skb, len);
>
> skb_push(skb, sizeof(*udph));
> skb_reset_transport_header(skb);
Hmm, real question is why skb_realloc_headroom() is even necessary...
I suspect we need to reserve more bytes.
total_len = ip_len + ETH_HLEN + NET_IP_ALIGN + NET_SKB_PAD;
or something like that ?
Which driver triggers the bug ?
^ permalink raw reply
* Hello
From: Mrs Anna Kennedy @ 2012-06-12 11:39 UTC (permalink / raw)
I have an urgent proposal for you kindly get to me asap.
^ 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