Re: [PATCH 0/3]: net: dsa: mt7530: support MT7530 in the MT7621 SoC

2018-12-03 Thread John Crispin



On 03/12/2018 15:00, René van Dorst wrote:

Quoting Bjørn Mork :

Greg Ungerer  writes:


The following change helped alot, but I still get some problems under
sustained load and some types of port setups. Still trying to figure
out what exactly is going on.

--- a/linux/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/linux/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1750,8 +1750,8 @@ static irqreturn_t mtk_handle_irq_rx(int irq, 
void *_eth)

   if (likely(napi_schedule_prep(>rx_napi))) {
    __napi_schedule(>rx_napi);
-   mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
    }
+   mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
   return IRQ_HANDLED;
 }
@@ -1762,11 +1762,53 @@ static irqreturn_t mtk_handle_irq_tx(int 
irq, void *_eth)

   if (likely(napi_schedule_prep(>tx_napi))) {
    __napi_schedule(>tx_napi);
-   mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
    }
+   mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
   return IRQ_HANDLED;
 }


Yes, sorry I didn't point to that as well.  Just to be clear:  I have no
clue how this thing is actually wired up, or if you could use three
interrupts on the MT7621 too. I just messed with it until I got
something to work, based on Renés original idea and code.


My idea is a just a copy of mtk_handle_irq_{rx,tx} see [1]
You probably want to look at the staging driver or Ubiquity source 
with a 3.10.x kernel [2] or padavan with 3.4.x kernel [3].

AFAIK mt7621 only has 1 IRQ for ethernet part.


correct there is only 1 single IRQ on mt7621

    John





Greats,

René

[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/net/ethernet/mediatek/mtk_eth_soc.c#n1739
[2] 
https://www.ubnt.com/download/edgemax/edgerouter-x-sfp/default/edgerouter-er-xer-x-sfpep-r6-firmware-v1107
[3] 
https://bitbucket.org/padavan/rt-n56u/src/e6f45337528f668651e251057a1a0fec735f6df1/trunk/linux-3.4.x/drivers/net/raeth/raether.c?at=master=file-view-default#raether.c-658





Re: [PATCH 4/4] net: dsa: Add Lantiq / Intel DSA driver for vrx200

2018-07-25 Thread John Crispin




On 21/07/18 21:13, Hauke Mehrtens wrote:

+#define MC_ENTRY(val, msk, ns, out, len, type, flags, ipv4_len) \
+   { val, msk, (ns << 10 | out << 4 | len >> 1),\
+   (len & 1) << 15 | type << 13 | flags << 9 | ipv4_len << 8 }
+static const struct gswip_pce_microcode gswip_pce_microcode[] = {
+   /*  valuemaskns  fields  L  type flags   
ipv4_len */
+   MC_ENTRY(0x88c3, 0x,  1, OUT_ITAG0,  4, INSTR,   FLAG_ITAG,  0),
+   MC_ENTRY(0x8100, 0x,  2, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
+   MC_ENTRY(0x88A8, 0x,  1, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
+   MC_ENTRY(0x8100, 0x,  1, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
+   MC_ENTRY(0x8864, 0x, 17, OUT_ETHTYP, 1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x0800, 0x, 21, OUT_ETHTYP, 1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x86DD, 0x, 22, OUT_ETHTYP, 1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x8863, 0x, 16, OUT_ETHTYP, 1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0xF800, 10, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 40, OUT_ETHTYP, 1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x0600, 0x0600, 40, OUT_ETHTYP, 1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 12, OUT_NONE,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 14, OUT_NONE,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x0300, 0xFF00, 41, OUT_NONE,   0, INSTR,   FLAG_SNAP,  0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 41, OUT_DIP7,   3, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 18, OUT_DIP7,   3, INSTR,   FLAG_PPPOE, 0),
+   MC_ENTRY(0x0021, 0x, 21, OUT_NONE,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x0057, 0x, 22, OUT_NONE,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 40, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x4000, 0xF000, 24, OUT_IP0,4, INSTR,   FLAG_IPV4,  1),
+   MC_ENTRY(0x6000, 0xF000, 27, OUT_IP0,3, INSTR,   FLAG_IPV6,  0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 25, OUT_IP3,2, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 26, OUT_SIP0,   4, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 40, OUT_NONE,   0, LENACCU, FLAG_NO,0),
+   MC_ENTRY(0x1100, 0xFF00, 39, OUT_PROT,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x0600, 0xFF00, 39, OUT_PROT,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_HOP,   0),
+   MC_ENTRY(0x2B00, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_NN1,   0),
+   MC_ENTRY(0x3C00, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_NN2,   0),
+   MC_ENTRY(0x, 0x, 39, OUT_PROT,   1, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x00E0, 35, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 40, OUT_NONE,   0, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0xFF00, 33, OUT_NONE,   0, IPV6,FLAG_HOP,   0),
+   MC_ENTRY(0x2B00, 0xFF00, 33, OUT_NONE,   0, IPV6,FLAG_NN1,   0),
+   MC_ENTRY(0x3C00, 0xFF00, 33, OUT_NONE,   0, IPV6,FLAG_NN2,   0),
+   MC_ENTRY(0x, 0x, 40, OUT_PROT,   1, IPV6,FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 40, OUT_SIP0,  16, INSTR,   FLAG_NO,0),
+   MC_ENTRY(0x, 0x, 41, OUT_APP0,   4, INSTR,   FLAG_IGMP,  0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR,   FLAG_END,   0),
+   MC_ENTRY(0x, 0x, 41, OUT_NONE,   0, INSTR, 

Re: [PATCH 3/4] net: lantiq: Add Lantiq / Intel vrx200 Ethernet driver

2018-07-21 Thread John Crispin




On 21/07/18 21:13, Hauke Mehrtens wrote:

+ * Copyright (C) 2012 John Crispin

that is not my mail addr :-)
    John


Re: [PATCH v2 rfc 0/8] IGMP snooping for local traffic

2017-09-06 Thread John Crispin



On 06/09/17 02:47, Andrew Lunn wrote:

Should this be done at the DSA level, or at the driver level?  Do any
chips do broadcast flooding in hardware already? Hence they currently
see broadcast duplication? If i add a broadcast mdb at the DSA level,
and the chip is already hard wired to flooding broadcast, is it going
to double flood?


Hi Andrew,

MT7530 and QCA8K only have a  "unknown mac fwd to port X" feature. both 
use the same HW table for FDB and MDB tables. so this should ideally be 
fixed on DSA level rather than fixing up those 2 drivers.


John


Re: [PATCH 0/4] net-next: dsa: fix flow dissection

2017-08-10 Thread John Crispin



On 10/08/17 08:42, Eric Dumazet wrote:

On Wed, 2017-08-09 at 22:52 -0700, David Miller wrote:

From: John Crispin <j...@phrozen.org>
Date: Wed,  9 Aug 2017 14:41:15 +0200


RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this is that skb_hash will call the
flow_dissector. At this point the skb still contains the magic switch
header and the skb->protocol field is not set up to the correct 802.3
value yet. By the time the tag specific code is called, removing the header
and properly setting the protocol an invalid hash is already set. In the
case of the mt7530 this will result in all flows always having the same
hash.

Changes since RFC:
* use a callback instead of static values
* add cover letter

Series applied, thanks.

Is this related ?

net/core/flow_dissector.c: In function '__skb_flow_dissect':
net/core/flow_dissector.c:448:18: error: 'struct net_device' has no member 
named 'dsa_ptr'
 ops = skb->dev->dsa_ptr->tag_ops;
   ^
make[3]: *** [net/core/flow_dissector.o] Error 1



Hi Eric,

I have just sent the fix for this compile error

John


[PATCH net-next] net: core: fix compile error inside flow_dissector due to new dsa callback

2017-08-10 Thread John Crispin
The following error was introduced by
commit 43e665287f93 ("net-next: dsa: fix flow dissection")
due to a missing #if guard

net/core/flow_dissector.c: In function '__skb_flow_dissect':
net/core/flow_dissector.c:448:18: error: 'struct net_device' has no member 
named 'dsa_ptr'
ops = skb->dev->dsa_ptr->tag_ops;
^
make[3]: *** [net/core/flow_dissector.o] Error 1

Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/core/flow_dissector.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 5b5be9577257..79b9c06c83ad 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -441,6 +441,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 skb->vlan_proto : skb->protocol;
nhoff = skb_network_offset(skb);
hlen = skb_headlen(skb);
+#if IS_ENABLED(CONFIG_NET_DSA)
if (unlikely(netdev_uses_dsa(skb->dev))) {
const struct dsa_device_ops *ops;
int offset;
@@ -452,6 +453,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
nhoff += offset;
}
}
+#endif
}
 
/* It is ensured by skb_flow_dissector_init() that control key will
-- 
2.11.0



Re: [PATCH 0/4] net-next: dsa: fix flow dissection

2017-08-10 Thread John Crispin



On 10/08/17 08:42, Eric Dumazet wrote:

On Wed, 2017-08-09 at 22:52 -0700, David Miller wrote:

From: John Crispin <j...@phrozen.org>
Date: Wed,  9 Aug 2017 14:41:15 +0200


RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this is that skb_hash will call the
flow_dissector. At this point the skb still contains the magic switch
header and the skb->protocol field is not set up to the correct 802.3
value yet. By the time the tag specific code is called, removing the header
and properly setting the protocol an invalid hash is already set. In the
case of the mt7530 this will result in all flows always having the same
hash.

Changes since RFC:
* use a callback instead of static values
* add cover letter

Series applied, thanks.

Is this related ?

net/core/flow_dissector.c: In function '__skb_flow_dissect':
net/core/flow_dissector.c:448:18: error: 'struct net_device' has no member 
named 'dsa_ptr'
 ops = skb->dev->dsa_ptr->tag_ops;
   ^
make[3]: *** [net/core/flow_dissector.o] Error 1




looks like it, I did test the patches against net-next from 24 hours 
ago, let me do a test build just now.

John



___
Linux-mediatek mailing list
linux-media...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek




[PATCH 1/4] net-next: dsa: move struct dsa_device_ops to the global header file

2017-08-09 Thread John Crispin
We need to access this struct from within the flow_dissector to fix
dissection for packets coming in on DSA devices.

Signed-off-by: Muciri Gatimu <muc...@openmesh.com>
Signed-off-by: Shashidhar Lakkavalli <shashidhar.lakkava...@openmesh.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h  | 7 +++
 net/dsa/dsa_priv.h | 7 ---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index a4f66dbb4b7c..65d7804c6f69 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -101,6 +101,13 @@ struct dsa_platform_data {
 
 struct packet_type;
 
+struct dsa_device_ops {
+   struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
+   struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt,
+  struct net_device *orig_dev);
+};
+
 struct dsa_switch_tree {
struct list_headlist;
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 68c63d4b989c..9fff7f4c8689 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -65,13 +65,6 @@ struct dsa_notifier_vlan_info {
int port;
 };
 
-struct dsa_device_ops {
-   struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
-   struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
-  struct packet_type *pt,
-  struct net_device *orig_dev);
-};
-
 struct dsa_slave_priv {
/* Copy of dp->ds->dst->tag_ops->xmit for faster access in hot path */
struct sk_buff *(*xmit)(struct sk_buff *skb,
-- 
2.11.0



[PATCH 0/4] net-next: dsa: fix flow dissection

2017-08-09 Thread John Crispin
RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this is that skb_hash will call the
flow_dissector. At this point the skb still contains the magic switch
header and the skb->protocol field is not set up to the correct 802.3
value yet. By the time the tag specific code is called, removing the header
and properly setting the protocol an invalid hash is already set. In the
case of the mt7530 this will result in all flows always having the same
hash.

Changes since RFC:
* use a callback instead of static values
* add cover letter

John Crispin (4):
  net-next: dsa: move struct dsa_device_ops to the global header file
  net-next: dsa: add flow_dissect callback to struct dsa_device_ops
  net-next: tag_mtk: add flow_dissect callback to the ops struct
  net-next: dsa: fix flow dissection

 include/net/dsa.h |  9 +
 net/core/flow_dissector.c | 12 
 net/dsa/dsa_priv.h|  7 ---
 net/dsa/tag_mtk.c | 14 --
 4 files changed, 33 insertions(+), 9 deletions(-)

-- 
2.11.0



[PATCH 4/4] net-next: dsa: fix flow dissection

2017-08-09 Thread John Crispin
RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this is that skb_hash will call the
flow_dissector. At this point the skb still contains the magic switch
header and the skb->protocol field is not set up to the correct 802.3
value yet. By the time the tag specific code is called, removing the header
and properly setting the protocol an invalid hash is already set. In the
case of the mt7530 this will result in all flows always having the same
hash.

Signed-off-by: Muciri Gatimu <muc...@openmesh.com>
Signed-off-by: Shashidhar Lakkavalli <shashidhar.lakkava...@openmesh.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/core/flow_dissector.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 0cc672aba1f0..5b5be9577257 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -440,6 +441,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 skb->vlan_proto : skb->protocol;
nhoff = skb_network_offset(skb);
hlen = skb_headlen(skb);
+   if (unlikely(netdev_uses_dsa(skb->dev))) {
+   const struct dsa_device_ops *ops;
+   int offset;
+
+   ops = skb->dev->dsa_ptr->tag_ops;
+   if (ops->flow_dissect &&
+   !ops->flow_dissect(skb, , )) {
+   hlen -= offset;
+   nhoff += offset;
+   }
+   }
}
 
/* It is ensured by skb_flow_dissector_init() that control key will
-- 
2.11.0



[PATCH 2/4] net-next: dsa: add flow_dissect callback to struct dsa_device_ops

2017-08-09 Thread John Crispin
When the flow dissector first sees packets coming in on a DSA devices the
802.3 header wont be located where the code expects it to be as the tag
is still present. Adding this new callback allows a DSA device to provide a
new function that the flow_dissector can use to get the correct protocol
and offset of the network header.

Signed-off-by: Muciri Gatimu <muc...@openmesh.com>
Signed-off-by: Shashidhar Lakkavalli <shashidhar.lakkava...@openmesh.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 65d7804c6f69..7f46b521313e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -106,6 +106,8 @@ struct dsa_device_ops {
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
   struct packet_type *pt,
   struct net_device *orig_dev);
+   int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
+   int *offset);
 };
 
 struct dsa_switch_tree {
-- 
2.11.0



[PATCH 3/4] net-next: tag_mtk: add flow_dissect callback to the ops struct

2017-08-09 Thread John Crispin
The MT7530 inserts the 4 magic header in between the 802.3 address and
protocol field. The patch implements the callback that can be called by
the flow dissector to figure out the real protocol and offset of the
network header. With this patch applied we can properly parse the packet
and thus make hashing function properly.

Signed-off-by: Muciri Gatimu <muc...@openmesh.com>
Signed-off-by: Shashidhar Lakkavalli <shashidhar.lakkava...@openmesh.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/dsa/tag_mtk.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 2f32b7ea3365..02163c045a96 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -87,7 +87,17 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, 
struct net_device *dev,
return skb;
 }
 
+static int mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+   int *offset)
+{
+   *offset = 4;
+   *proto = ((__be16 *)skb->data)[1];
+
+   return 0;
+}
+
 const struct dsa_device_ops mtk_netdev_ops = {
-   .xmit   = mtk_tag_xmit,
-   .rcv= mtk_tag_rcv,
+   .xmit   = mtk_tag_xmit,
+   .rcv= mtk_tag_rcv,
+   .flow_dissect   = mtk_tag_flow_dissect,
 };
-- 
2.11.0



[PATCH 0/2] net-next: mediatek: bring up QDMA RX ring 0

2017-08-09 Thread John Crispin
The MT7623 has several DMA rings. Inside the SW path, the core will use
the PDMA when receiving traffic. While bringing up the HW path we noticed
that the PPE requires the QDMA RX to also be brought up as it uses this
ring internally for its flow scheduling.

John Crispin (2):
  net-next: mediatek: fix typos inside the header file
  net-next: mediatek: bring up QDMA RX ring 0

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  7 --
 2 files changed, 31 insertions(+), 12 deletions(-)

-- 
2.11.0



[PATCH 1/2] net-next: mediatek: fix typos inside the header file

2017-08-09 Thread John Crispin
Trivial patch fixing 2 typos.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 4594862e5a9b..940517af8039 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -599,8 +599,8 @@ struct mtk_soc_data {
  * @pctl:  The register map pointing at the range used to setup
  * GMAC port drive/slew values
  * @dma_refcnt:track how many netdevs are using the DMA engine
- * @tx_ring:   Pointer to the memore holding info about the TX ring
- * @rx_ring:   Pointer to the memore holding info about the RX ring
+ * @tx_ring:   Pointer to the memory holding info about the TX ring
+ * @rx_ring:   Pointer to the memory holding info about the RX ring
  * @tx_napi:   The TX NAPI struct
  * @rx_napi:   The RX NAPI struct
  * @scratch_ring:  Newer SoCs need memory for a second HW managed TX ring
-- 
2.11.0



[PATCH 2/2] net-next: mediatek: bring up QDMA RX ring 0

2017-08-09 Thread John Crispin
This patch is in preparation for adding HW flow and QoS offloading. For
those features to work, the driver needs to bring up the first QDMA RX
ring. This ring is used by the PPE offloading HW.

Signed-off-by: John Crisp in 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 +++
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ff97f2939209..4c85b4713c0d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1285,9 +1285,19 @@ static void mtk_tx_clean(struct mtk_eth *eth)
 
 static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
 {
-   struct mtk_rx_ring *ring = >rx_ring[ring_no];
+   struct mtk_rx_ring *ring;
int rx_data_len, rx_dma_size;
int i;
+   u32 offset = 0;
+
+   if (rx_flag == MTK_RX_FLAGS_QDMA) {
+   if (ring_no)
+   return -EINVAL;
+   ring = >rx_ring_qdma;
+   offset = 0x1000;
+   } else {
+   ring = >rx_ring[ring_no];
+   }
 
if (rx_flag == MTK_RX_FLAGS_HWLRO) {
rx_data_len = MTK_MAX_LRO_RX_LENGTH;
@@ -1337,17 +1347,16 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int 
ring_no, int rx_flag)
 */
wmb();
 
-   mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no));
-   mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no));
-   mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
-   mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX);
+   mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no) + offset);
+   mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no) + offset);
+   mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg + offset);
+   mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX + offset);
 
return 0;
 }
 
-static void mtk_rx_clean(struct mtk_eth *eth, int ring_no)
+static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring)
 {
-   struct mtk_rx_ring *ring = >rx_ring[ring_no];
int i;
 
if (ring->data && ring->dma) {
@@ -1673,6 +1682,10 @@ static int mtk_dma_init(struct mtk_eth *eth)
if (err)
return err;
 
+   err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_QDMA);
+   if (err)
+   return err;
+
err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_NORMAL);
if (err)
return err;
@@ -1712,12 +1725,13 @@ static void mtk_dma_free(struct mtk_eth *eth)
eth->phy_scratch_ring = 0;
}
mtk_tx_clean(eth);
-   mtk_rx_clean(eth, 0);
+   mtk_rx_clean(eth, >rx_ring[0]);
+   mtk_rx_clean(eth, >rx_ring_qdma);
 
if (eth->hwlro) {
mtk_hwlro_rx_uninit(eth);
for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
-   mtk_rx_clean(eth, i);
+   mtk_rx_clean(eth, >rx_ring[i]);
}
 
kfree(eth->scratch_head);
@@ -1784,7 +1798,9 @@ static int mtk_start_dma(struct mtk_eth *eth)
 
mtk_w32(eth,
MTK_TX_WB_DDONE | MTK_TX_DMA_EN |
-   MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO,
+   MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO |
+   MTK_RX_DMA_EN | MTK_RX_2B_OFFSET |
+   MTK_RX_BT_32DWORDS,
MTK_QDMA_GLO_CFG);
 
mtk_w32(eth,
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 940517af8039..3d3c24a28112 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -532,6 +532,7 @@ struct mtk_tx_ring {
 enum mtk_rx_flags {
MTK_RX_FLAGS_NORMAL = 0,
MTK_RX_FLAGS_HWLRO,
+   MTK_RX_FLAGS_QDMA,
 };
 
 /* struct mtk_rx_ring -This struct holds info describing a RX ring
@@ -601,6 +602,7 @@ struct mtk_soc_data {
  * @dma_refcnt:track how many netdevs are using the DMA engine
  * @tx_ring:   Pointer to the memory holding info about the TX ring
  * @rx_ring:   Pointer to the memory holding info about the RX ring
+ * @rx_ring_qdma:  Pointer to the memory holding info about the QDMA RX 
ring
  * @tx_napi:   The TX NAPI struct
  * @rx_napi:   The RX NAPI struct
  * @scratch_ring:  Newer SoCs need memory for a second HW managed TX ring
@@ -633,6 +635,7 @@ struct mtk_eth {
atomic_tdma_refcnt;
struct mtk_tx_ring  tx_ring;
struct mtk_rx_ring  rx_ring[MTK_MAX_RX_RING_NUM];
+   struct mtk_rx_ring  rx_ring_qdma;
struct napi_struct  tx_napi;
struct napi_struct  rx_napi;
struct mtk_tx_dma   *scratch_ring;
-- 
2.11.0



[PATCH] net: dsa: mediatek: add adjust link support for user ports

2017-08-07 Thread John Crispin
Manually adjust the port settings of user ports once PHY polling has
completed. This patch extends the adjust_link callback to configure the
per port PMCR register, applying the proper values polled from the PHY.
Without this patch flow control was not always getting setup properly.

Signed-off-by: Shashidhar Lakkavalli <shashidhar.lakkava...@openmesh.com>
Signed-off-by: Muciri Gatimu <muc...@openmesh.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/mt7530.c | 38 ++
 drivers/net/dsa/mt7530.h |  1 +
 2 files changed, 39 insertions(+)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 1e46418a3b74..264b281eb86b 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -625,6 +625,44 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int 
port,
 * all finished.
 */
mt7623_pad_clk_setup(ds);
+   } else {
+   u16 lcl_adv = 0, rmt_adv = 0;
+   u8 flowctrl;
+   u32 mcr = PMCR_USERP_LINK | PMCR_FORCE_MODE;
+
+   switch (phydev->speed) {
+   case SPEED_1000:
+   mcr |= PMCR_FORCE_SPEED_1000;
+   break;
+   case SPEED_100:
+   mcr |= PMCR_FORCE_SPEED_100;
+   break;
+   };
+
+   if (phydev->link)
+   mcr |= PMCR_FORCE_LNK;
+
+   if (phydev->duplex) {
+   mcr |= PMCR_FORCE_FDX;
+
+   if (phydev->pause)
+   rmt_adv = LPA_PAUSE_CAP;
+   if (phydev->asym_pause)
+   rmt_adv |= LPA_PAUSE_ASYM;
+
+   if (phydev->advertising & ADVERTISED_Pause)
+   lcl_adv |= ADVERTISE_PAUSE_CAP;
+   if (phydev->advertising & ADVERTISED_Asym_Pause)
+   lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+   flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+
+   if (flowctrl & FLOW_CTRL_TX)
+   mcr |= PMCR_TX_FC_EN;
+   if (flowctrl & FLOW_CTRL_RX)
+   mcr |= PMCR_RX_FC_EN;
+   }
+   mt7530_write(priv, MT7530_PMCR_P(port), mcr);
}
 }
 
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index b83d76b99802..74db9822eb40 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -151,6 +151,7 @@ enum mt7530_stp_state {
 #define  PMCR_TX_FC_EN BIT(5)
 #define  PMCR_RX_FC_EN BIT(4)
 #define  PMCR_FORCE_SPEED_1000 BIT(3)
+#define  PMCR_FORCE_SPEED_100  BIT(2)
 #define  PMCR_FORCE_FDXBIT(1)
 #define  PMCR_FORCE_LNKBIT(0)
 #define  PMCR_COMMON_LINK  (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
-- 
2.11.0



Re: [PATCH net-next v3 4/4] MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

2017-07-31 Thread John Crispin



On 31/07/17 12:05, sean.w...@mediatek.com wrote:

From: Sean Wang <sean.w...@mediatek.com>

Sean and Nelson work for MediaTek on maintaining the MediaTek ethernet
driver for the existing SoCs and adding support for the following SoCs.
In the past, Sean has been active at making most of the qualifications
, stress test and submitting a lot of patches for the driver while
Nelson was looking into the aspects more on hardware additions and details
such as introducing PDMA with Hardware LRO to the driver. Also update
John's up-to-date mail address in the patch.

Cc: John Crispin <j...@phrozen.org>
Signed-off-by: Sean Wang <sean.w...@mediatek.com>
Signed-off-by: Nelson Chang <nelson.ch...@mediatek.com>


Acked-by: John Crispin <j...@phrozen.org>


---
  MAINTAINERS | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index bd22d07..22faf704 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8431,7 +8431,9 @@ F:include/uapi/linux/uvcvideo.h
  
  MEDIATEK ETHERNET DRIVER

  M:Felix Fietkau <n...@openwrt.org>
-M: John Crispin <blo...@openwrt.org>
+M: John Crispin <j...@phrozen.org>
+M: Sean Wang <sean.w...@mediatek.com>
+M: Nelson Chang <nelson.ch...@mediatek.com>
  L:netdev@vger.kernel.org
  S:Maintained
  F:drivers/net/ethernet/mediatek/




Re: [PATCH V2 3/4] net-next: dsa: fix flow dissection

2017-07-28 Thread John Crispin



On 26/07/17 17:10, Andrew Lunn wrote:

On Fri, Jul 21, 2017 at 10:58:12AM +0200, John Crispin wrote:

RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this is that skb_hash will call the
flow_dissector. At this point the skb still contains the magic switch header
and the skb->protocol field is not set up to the correct 802.3 value yet.
By the time the tag specific code is called, removing the header and
properly setting the protocol an invalid hash is already set. In the case
of the mt7530 this will result in all flows always having the same hash.

This patch makes the flow dissector honour the nh and protocol offset
defined by the dsa tag driver thus fixing dissection, hashing and RPS.

Signed-off-by: John Crispin <j...@phrozen.org>
---
  net/core/flow_dissector.c | 12 
  1 file changed, 12 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index fc5fc4594c90..1268ae75c3b3 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -4,6 +4,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -440,6 +441,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 skb->vlan_proto : skb->protocol;
nhoff = skb_network_offset(skb);
hlen = skb_headlen(skb);
+
+   if (unlikely(netdev_uses_dsa(skb->dev))) {
+   const struct dsa_device_ops *ops;
+   u8 *p = (u8 *)data;
+
+   ops = skb->dev->dsa_ptr->tag_ops;
+   if (ops->hash_proto_off)
+   proto = (u16)p[ops->hash_proto_off];

Hi John

Unfortunately, this is not generic enough to work for DSA and EDSA
tagging. With these tagging protocols, the size of the tag depends on
the presence or not of a VLAN header.

To make this work for all tagging protocols, we are going to need to
add an a new op to tag_ops.

 Andrew

Hi Andrew,

thanks for the feedback. should I add 2 callbacks for each of the 2 
parameters ?


John


Re: [PATCH-next] net: ethernet: mediatek: fix implicit irq include causing build fails

2017-07-23 Thread John Crispin

Hi Paul

mark sent the same patch a couple of days ago [1]

John

[1] https://patchwork.ozlabs.org/patch/791550/


On 23/07/17 16:56, Paul Gortmaker wrote:

To fix:

drivers/net/ethernet/mediatek/mtk_eth_soc.c:1685:1: error: unknown type name 
'irqreturn_t'
drivers/net/ethernet/mediatek/mtk_eth_soc.c: In function 'mtk_handle_irq_rx':
drivers/net/ethernet/mediatek/mtk_eth_soc.c:1694:9: error: 'IRQ_HANDLED' 
undeclared (first use in this function)
drivers/net/ethernet/mediatek/mtk_eth_soc.c:1694:9: note: each undeclared 
identifier is reported only once for each function it appears in

and similar follow-on errors as seen in arm allmodconfig builds.

Cc: Sean Wang <sean.w...@mediatek.com>
Cc: Felix Fietkau <n...@openwrt.org>
Cc: John Crispin <blo...@openwrt.org>
Cc: Matthias Brugger <matthias@gmail.com>
Cc: linux-media...@lists.infradead.org
Signed-off-by: Paul Gortmaker <paul.gortma...@windriver.com>
---

[Seen on current linux-next, where similar implicit irq includes
  were recently revealed by some header shuffle somewhere.]

  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 7e95cf547ff1..ea15eb095d83 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -16,6 +16,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 




Re: [RFC 1/2] net-next: add a dma_desc element to struct skb_shared_info

2017-07-21 Thread John Crispin



On 21/07/17 17:56, Paolo Abeni wrote:

Hi,

On Fri, 2017-07-21 at 17:20 +0200, John Crispin wrote:

In order to make HW flow offloading work in latest MediaTek silicon we need
to propagate part of the RX DMS descriptor to the upper layers populating
the flow offload engines HW tables. This patch adds an extra element to
struct skb_shared_info allowing the ethernet drivers RX napi code to store
the required information and make it persistent for the lifecycle of the
skb and its clones.

Signed-off-by: John Crispin <j...@phrozen.org>
---
  include/linux/skbuff.h | 1 +
  1 file changed, 1 insertion(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4093552be1de..db9576cd946b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -426,6 +426,7 @@ struct skb_shared_info {
unsigned intgso_type;
u32 tskey;
__be32  ip6_frag_id;
+   u32 dma_desc;
  
  	/*

 * Warning : all fields before dataref are cleared in __alloc_skb()

This will increase the skb_shared_info struct size, which is already
quite large, and can have several kind of performance drawback.
AFAIK this is discouraged.

I don't understand the use case; the driver will set this field, but
who is going to consume it?

Thanks,

Paolo

Hi Paolo,

When the flow offloading engine forwards a packet to the DMA it will 
send additional info to the sw path. this includes

* physical switch port
* internal flow hash - this is required to populate the correct flow 
table entry
* ppe state - this indicates what state the PPEs internal table is in 
for the flow
* the reason why the packet was forwarde - these are things like bind, 
unbind, timed out, ...


once the flow table offloading patches are ready and upstream, the 
netfilter layer will see the SKB and pass it o to the flow table 
offloading code, at which point it will finally end up inside the 
offloading driver. this will need to have access to this info sent to 
the sw path inside the rx descriptor to properly work out what state the 
flow is in and which table entry to populate in the HW table for 
offloading to work.


Hope that is a little clearer. current hackish driver is here [1], the 
patch to the ethernet driver is here [2]


John

[1] 
https://git.lede-project.org/?p=lede/blogic/staging.git;a=tree;f=target/linux/mediatek/files/drivers/net/ethernet/mediatek/mtk_hnat;hb=bc0518b9d928b43d965d8a1f8860281f0ae6a31c
[2] 
https://git.lede-project.org/?p=lede/blogic/staging.git;a=blob;f=target/linux/mediatek/patches-4.9/0310-hwnat.patch;h=57bd0c07b39d2169f3ba08e1aa83b92dffcee025;hb=bc0518b9d928b43d965d8a1f8860281f0ae6a31c




[RFC 1/2] net-next: add a dma_desc element to struct skb_shared_info

2017-07-21 Thread John Crispin
In order to make HW flow offloading work in latest MediaTek silicon we need
to propagate part of the RX DMS descriptor to the upper layers populating
the flow offload engines HW tables. This patch adds an extra element to
struct skb_shared_info allowing the ethernet drivers RX napi code to store
the required information and make it persistent for the lifecycle of the
skb and its clones.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/linux/skbuff.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4093552be1de..db9576cd946b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -426,6 +426,7 @@ struct skb_shared_info {
unsigned intgso_type;
u32 tskey;
__be32  ip6_frag_id;
+   u32 dma_desc;
 
/*
 * Warning : all fields before dataref are cleared in __alloc_skb()
-- 
2.11.0



[RFC 2/2] net-next: mediatek: populate the shared

2017-07-21 Thread John Crispin
When enabling HW flow offloading, the traffic coming in on either of the
GMACs is first sent to the PPE for processing. Any traffic not offloaded
at this point will then be forwarded to the normal RX DMA ring for SW path
processing. In this case the PPE will send additional data inside RXD4
that is later required by the upper layers to populate the flow offloading
engines HW tables properly. This patch sets the skb_shared_info's dma_desc
field so that we can use the value later on.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a455d1b4f1d8..42d162cd6363 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -918,6 +918,7 @@ static void mtk_update_rx_cpu_idx(struct mtk_eth *eth)
 static int mtk_poll_rx(struct napi_struct *napi, int budget,
   struct mtk_eth *eth)
 {
+   struct skb_shared_info *sh;
struct mtk_rx_ring *ring;
int idx;
struct sk_buff *skb;
@@ -1000,6 +1001,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int 
budget,
else
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
+   sh = skb_shinfo(skb);
+
+   sh->dma_desc = trxd.rxd4;
 
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX &&
RX_DMA_VID(trxd.rxd3))
-- 
2.11.0



[RFC 0/2] net-next: hw flow offloading

2017-07-21 Thread John Crispin
Hi,

I managed to bring up the flow offloading on latest MedieTek silicon.

When enabling HW flow offloading, the traffic coming in on either of the
GMACs is first sent to the PPE for processing. Any traffic not offloaded
at this point will then be forwarded to the normal RX DMA ring for SW path
processing. In this case the PPE will send additional data inside RXD4
that is later required by the upper layers to populate the flow offloading
engines HW tables properly.

This series is a RFC as i am not sure how to best propagate the additional
info from the RX DMA descriptor. The driver is still using NF hooks and
I plan to rebase it and send it upstream once the flow table offloading
patches that folks are working on are upstream.

I am right now trying to get rid of the remaning hacks in the code and
wanted to know if this series would be a feasible solution.

John

John Crispin (2):
  net-next: add a dma_desc element to struct skb_shared_info
  net-next: mediatek: populate the shared

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 
 include/linux/skbuff.h  | 1 +
 2 files changed, 5 insertions(+)

-- 
2.11.0



[PATCH V2 1/4] net-next: dsa: move struct dsa_device_ops to the global header file

2017-07-21 Thread John Crispin
We need to access this struct from within the flow_dissector to fix
dissection for packets coming in on DSA devices.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h  | 7 +++
 net/dsa/dsa_priv.h | 7 ---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 88da272d20d0..a4c0d52abc80 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -101,6 +101,13 @@ struct dsa_platform_data {
 
 struct packet_type;
 
+struct dsa_device_ops {
+   struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
+   struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt,
+  struct net_device *orig_dev);
+};
+
 struct dsa_switch_tree {
struct list_headlist;
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 55982cc39b24..62ea3663c2c6 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -65,13 +65,6 @@ struct dsa_notifier_vlan_info {
int port;
 };
 
-struct dsa_device_ops {
-   struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
-   struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
-  struct packet_type *pt,
-  struct net_device *orig_dev);
-};
-
 struct dsa_slave_priv {
/* Copy of dp->ds->dst->tag_ops->xmit for faster access in hot path */
struct sk_buff *(*xmit)(struct sk_buff *skb,
-- 
2.11.0



[PATCH V2 4/4] net-next: tag_mtk: add nh and proto offsets to the ops struct

2017-07-21 Thread John Crispin
The MT7530 inserts the 4 magic header in between the 802.3 address and
protocol field. The patch defines these header such that the flow_disector
can properly parse the packet and thus allows hashing to function properly.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/dsa/tag_mtk.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 2f32b7ea3365..142322988202 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -88,6 +88,8 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, 
struct net_device *dev,
 }
 
 const struct dsa_device_ops mtk_netdev_ops = {
-   .xmit   = mtk_tag_xmit,
-   .rcv= mtk_tag_rcv,
+   .xmit   = mtk_tag_xmit,
+   .rcv= mtk_tag_rcv,
+   .hash_nh_off= 4,
+   .hash_proto_off = 2,
 };
-- 
2.11.0



[PATCH V2 3/4] net-next: dsa: fix flow dissection

2017-07-21 Thread John Crispin
RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this is that skb_hash will call the
flow_dissector. At this point the skb still contains the magic switch header
and the skb->protocol field is not set up to the correct 802.3 value yet.
By the time the tag specific code is called, removing the header and
properly setting the protocol an invalid hash is already set. In the case
of the mt7530 this will result in all flows always having the same hash.

This patch makes the flow dissector honour the nh and protocol offset
defined by the dsa tag driver thus fixing dissection, hashing and RPS.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/core/flow_dissector.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index fc5fc4594c90..1268ae75c3b3 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -440,6 +441,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 skb->vlan_proto : skb->protocol;
nhoff = skb_network_offset(skb);
hlen = skb_headlen(skb);
+
+   if (unlikely(netdev_uses_dsa(skb->dev))) {
+   const struct dsa_device_ops *ops;
+   u8 *p = (u8 *)data;
+
+   ops = skb->dev->dsa_ptr->tag_ops;
+   if (ops->hash_proto_off)
+   proto = (u16)p[ops->hash_proto_off];
+   hlen -= ops->hash_nh_off;
+   nhoff += ops->hash_nh_off;
+   }
}
 
/* It is ensured by skb_flow_dissector_init() that control key will
-- 
2.11.0



[PATCH V2 2/4] net-next: dsa: add 802.3 protocol offset to struct dsa_device_ops

2017-07-21 Thread John Crispin
Adding these 2 new fields allows a DSA device to indicate the offsets of
the 802.3 header caused by the insertion of the switches tag.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index a4c0d52abc80..b98bc3621905 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -106,6 +106,11 @@ struct dsa_device_ops {
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
   struct packet_type *pt,
   struct net_device *orig_dev);
+   /*
+* Network header and 802.3 protocol offsets
+*/
+   int hash_nh_off;
+   int hash_proto_off;
 };
 
 struct dsa_switch_tree {
-- 
2.11.0



Re: [PATCH net] net: ethernet: mediatek: avoid potential invalid memory access

2017-07-20 Thread John Crispin



On 20/07/17 08:52, sean.w...@mediatek.com wrote:

From: Sean Wang <sean.w...@mediatek.com>

Potential dangerous invalid memory might be accessed if invalid mac value
reflected from the forward port field in rxd4 caused by possible potential
hardware defects. So added a simple sanity checker to avoid the kind of
situation happening.

Signed-off-by: Sean Wang <sean.w...@mediatek.com>


Thanks, i ran into the same problem last week and was going to send a 
fix shortly.


Acked-by: John Crispin <j...@phrozen.org>


---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++
  1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c1dc08c..8175433 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -999,6 +999,12 @@ static int mtk_poll_rx(struct napi_struct *napi, int 
budget,
  RX_DMA_FPORT_MASK;
mac--;
  
+		if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||

+!eth->netdev[mac])) {
+   netdev->stats.rx_dropped++;
+   goto release_desc;
+   }
+
netdev = eth->netdev[mac];
  
  		if (unlikely(test_bit(MTK_RESETTING, >state)))




Re: [RFC 1/2] net-next: fix DSA flow_disection

2017-06-20 Thread John Crispin



On 20/06/17 23:52, Andrew Lunn wrote:

On Tue, Jun 20, 2017 at 07:37:35PM +0200, John Crispin wrote:


On 20/06/17 16:01, Andrew Lunn wrote:

On Tue, Jun 20, 2017 at 10:06:54AM +0200, John Crispin wrote:

RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this that skb_hash will call the
flow_disector.

Hi John

What is the call path when the flow_disector is called? I'm wondering
if we can defer this, and call it later, after the tag code has
removed the header.

Andrew

Hi John

I follow your logic of doing the hash early

Is there any value in including the DSA header in the hash? That might
allow frames from different ingress ports to be spread over CPUs?

   Andrew

Hi Andrew,

adding the DSA header wont make any difference and would still require a 
patch to the flow dissector.


John




Re: [RFC 1/2] net-next: fix DSA flow_disection

2017-06-20 Thread John Crispin



On 20/06/17 19:30, Florian Fainelli wrote:

On 06/20/2017 07:01 AM, Andrew Lunn wrote:

On Tue, Jun 20, 2017 at 10:06:54AM +0200, John Crispin wrote:

RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this that skb_hash will call the
flow_disector.

Hi John

What is the call path when the flow_disector is called? I'm wondering
if we can defer this, and call it later, after the tag code has
removed the header.

Would not you usually want to configure RPS at the DSA network device
level where the switch tag has already been popped and you are
processing a regular Ethernet frame at that point?

Hi Florian,

is explained in my mail to Andrew, you really want to be able to setup 
RPS for all devices in the chain to free up the core handling IRQs


John



Re: [RFC 1/2] net-next: fix DSA flow_disection

2017-06-20 Thread John Crispin



On 20/06/17 16:01, Andrew Lunn wrote:

On Tue, Jun 20, 2017 at 10:06:54AM +0200, John Crispin wrote:

RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this that skb_hash will call the
flow_disector.

Hi John

What is the call path when the flow_disector is called? I'm wondering
if we can defer this, and call it later, after the tag code has
removed the header.

Andrew


Hi Andrew,

the ethernet driver receives the frame and passes it down the line. 
Eventually it ends up inside netif_receive_skb_internal() where it gets 
added to the backlog. At this point get_rps_cpu() is called. Inside 
get_rps_cpu() the skb_get_hash() is called which utilizes the 
flow_dissector() ... which is broken for DSA devices. get_rps_cpu() will 
always return the same hash for all flows and the frame is always added 
to the backlog on the same core. Once inside the backlog it will 
traverse through the dsa layer and end up inside the tag driver and be 
passed to the slave device for further processing and keep its bad flow 
hash for its whole life cycle.


In theory we could reset the hash inside the tag driver but ideally the 
whole life cycle of the frame should happen on the same core to avoid 
possible reordering issues. In addition RPS is broken until the frame 
reaches the tag driver. In the case of the mediatek mt7623 we only have 
1 RX IRQ and in the worst case the RPS of the frame while still inside 
ethX will happen on the same core as where we handle IRQs. This will 
increase the IRQ latency and reduce the free cpu time, thus reducing 
maximum throughput. I did test resetting the hash inside the tag driver. 
Calculating the correct hash from the start did yield a huge performance 
difference however, at least on mt7623. We are talking about 30% extra 
max throughput. This might not be such a big problem if the SoC has a 
multi queue ethernet core but on mt7623 it does make a huge difference 
if we can use RPS to delegate all frame processing away from the core 
handling the IRQs.


John


Re: [RFC 2/2] net-next: mt7530: add nh and proto offsets to the ops struct

2017-06-20 Thread John Crispin



On 20/06/17 15:54, Andrew Lunn wrote:

On Tue, Jun 20, 2017 at 10:06:55AM +0200, John Crispin wrote:

The MT7530 inserts the 4 magic header in between the 802.3 address and
protocol field. The patch defines these header such that the flow_disector
can properly parse the packet and thus allows hashing to function properly.

This is to do with tagging, not the switch driver. The Marvell switch
driver can be used with two different tagging protocols.

So i would put these fields in the dsa_device_ops.

Andrew

Hi Andrew,

i originally did so but struct dsa_device_ops is defined inside 
net/dsa/dsa_priv.h so flow_dissector.c would need a


#include "../dsa/dsa_priv.h"

I was not sure if this is ok or if we would need to move the struct 
definition to include/net/dsa.h in that case


John


[RFC 1/2] net-next: fix DSA flow_disection

2017-06-20 Thread John Crispin
RPS and probably other kernel features are currently broken on some if not
all DSA devices. The root cause of this that skb_hash will call the
flow_disector. At this point the skb still contains the magic switch header
and the skb->protocol field is not set up to the correct 802.3 value yet.
by the time the tag specific code is called, removing the header and
properly setting the protocol an invalid hash is already set. In the case
of the mt7530 this will result in all flows always having the same hash.

The patch adds 2 new fields to the dsa_switch_ops allowing the
flow_disector to use them in order to be able to create the real hash of
the connection.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h |  6 ++
 net/core/flow_dissector.c | 12 
 2 files changed, 18 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 58969b9a090c..8b0e8eca3c28 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -442,6 +442,12 @@ struct dsa_switch_ops {
 int port, struct net_device *br);
void(*crosschip_bridge_leave)(struct dsa_switch *ds, int sw_index,
  int port, struct net_device *br);
+
+   /*
+* Network header and 802.3 protocol offsets
+*/
+   int hash_nh_off;
+   int hash_proto_off;
 };
 
 struct dsa_switch_driver {
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index fc5fc4594c90..da45bdf57408 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -440,6 +441,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 skb->vlan_proto : skb->protocol;
nhoff = skb_network_offset(skb);
hlen = skb_headlen(skb);
+
+   if (unlikely(netdev_uses_dsa(skb->dev))) {
+   const struct dsa_switch_ops *ops;
+   u8 *p = (u8 *) data;
+
+   ops = skb->dev->dsa_ptr->ds[0]->ops;
+   if (ops->hash_proto_off)
+   proto = (u16) p[ops->hash_proto_off];
+   hlen -= ops->hash_nh_off;
+   nhoff += ops->hash_nh_off;
+   }
}
 
/* It is ensured by skb_flow_dissector_init() that control key will
-- 
2.11.0



[RFC 2/2] net-next: mt7530: add nh and proto offsets to the ops struct

2017-06-20 Thread John Crispin
The MT7530 inserts the 4 magic header in between the 802.3 address and
protocol field. The patch defines these header such that the flow_disector
can properly parse the packet and thus allows hashing to function properly.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/mt7530.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 1e46418a3b74..b5385e554601 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1019,6 +1019,8 @@ static struct dsa_switch_ops mt7530_switch_ops = {
.port_fdb_add   = mt7530_port_fdb_add,
.port_fdb_del   = mt7530_port_fdb_del,
.port_fdb_dump  = mt7530_port_fdb_dump,
+   .hash_nh_off= 4,
+   .hash_nh_proto  = 2,
 };
 
 static int
-- 
2.11.0



[PATCH 3/4] net-next: mediatek: split IRQ register locking into TX and RX

2017-06-19 Thread John Crispin
Originally the driver only utilised the new QDMA engine. The current code
still assumes this is the case when locking the IRQ mask register. Since
RX now runs on the old style PDMA engine we can add a second lock. This
patch reduces the IRQ latency as the TX and RX path no longer need to wait
on each other under heavy load.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 79 ++---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  5 +-
 2 files changed, 54 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 92be59a1e4e7..462d1e83e254 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -372,28 +372,48 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth)
mdiobus_unregister(eth->mii_bus);
 }
 
-static inline void mtk_irq_disable(struct mtk_eth *eth,
-  unsigned reg, u32 mask)
+static inline void mtk_tx_irq_disable(struct mtk_eth *eth, u32 mask)
 {
unsigned long flags;
u32 val;
 
-   spin_lock_irqsave(>irq_lock, flags);
-   val = mtk_r32(eth, reg);
-   mtk_w32(eth, val & ~mask, reg);
-   spin_unlock_irqrestore(>irq_lock, flags);
+   spin_lock_irqsave(>tx_irq_lock, flags);
+   val = mtk_r32(eth, MTK_QDMA_INT_MASK);
+   mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK);
+   spin_unlock_irqrestore(>tx_irq_lock, flags);
 }
 
-static inline void mtk_irq_enable(struct mtk_eth *eth,
- unsigned reg, u32 mask)
+static inline void mtk_tx_irq_enable(struct mtk_eth *eth, u32 mask)
 {
unsigned long flags;
u32 val;
 
-   spin_lock_irqsave(>irq_lock, flags);
-   val = mtk_r32(eth, reg);
-   mtk_w32(eth, val | mask, reg);
-   spin_unlock_irqrestore(>irq_lock, flags);
+   spin_lock_irqsave(>tx_irq_lock, flags);
+   val = mtk_r32(eth, MTK_QDMA_INT_MASK);
+   mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK);
+   spin_unlock_irqrestore(>tx_irq_lock, flags);
+}
+
+static inline void mtk_rx_irq_disable(struct mtk_eth *eth, u32 mask)
+{
+   unsigned long flags;
+   u32 val;
+
+   spin_lock_irqsave(>rx_irq_lock, flags);
+   val = mtk_r32(eth, MTK_PDMA_INT_MASK);
+   mtk_w32(eth, val & ~mask, MTK_PDMA_INT_MASK);
+   spin_unlock_irqrestore(>rx_irq_lock, flags);
+}
+
+static inline void mtk_rx_irq_enable(struct mtk_eth *eth, u32 mask)
+{
+   unsigned long flags;
+   u32 val;
+
+   spin_lock_irqsave(>rx_irq_lock, flags);
+   val = mtk_r32(eth, MTK_PDMA_INT_MASK);
+   mtk_w32(eth, val | mask, MTK_PDMA_INT_MASK);
+   spin_unlock_irqrestore(>rx_irq_lock, flags);
 }
 
 static int mtk_set_mac_address(struct net_device *dev, void *p)
@@ -1101,7 +1121,7 @@ static int mtk_napi_tx(struct napi_struct *napi, int 
budget)
return budget;
 
napi_complete(napi);
-   mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
+   mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
 
return tx_done;
 }
@@ -1135,7 +1155,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int 
budget)
goto poll_again;
}
napi_complete(napi);
-   mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
+   mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
 
return rx_done + budget - remain_budget;
 }
@@ -1670,7 +1690,7 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
 
if (likely(napi_schedule_prep(>rx_napi))) {
__napi_schedule(>rx_napi);
-   mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
+   mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
}
 
return IRQ_HANDLED;
@@ -1682,7 +1702,7 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
 
if (likely(napi_schedule_prep(>tx_napi))) {
__napi_schedule(>tx_napi);
-   mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
+   mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
}
 
return IRQ_HANDLED;
@@ -1694,11 +1714,11 @@ static void mtk_poll_controller(struct net_device *dev)
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
 
-   mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
-   mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
+   mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+   mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
mtk_handle_irq_rx(eth->irq[2], dev);
-   mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
-   mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
+   mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+   mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
 }
 #endif
 
@@ -1739,8 +1759,8 @@ static int mtk_open(struct net_device

[PATCH 4/4] net-next: mediatek: set the rx_queue to 0

2017-06-19 Thread John Crispin
The get_rps_cpu() function will not do any RPS on the data flow when no
queue is setup and always use the current cpu where the IRQ was handled
to also handle the backlog. As we only have one physical queue we always
set this to 0 unconditionally.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 462d1e83e254..adaaafc20532 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -992,6 +992,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
RX_DMA_VID(trxd.rxd3))
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
   RX_DMA_VID(trxd.rxd3));
+   skb_record_rx_queue(skb, 0);
napi_gro_receive(napi, skb);
 
ring->data[idx] = new_data;
-- 
2.11.0



[PATCH 2/4] net-next: mediatek: add RX IRQ delay support

2017-06-19 Thread John Crispin
The PDMA engine used for RX allows IRQ aggregation. The patch sets up the
corresponding registers to aggregate 4 IRQs into one. Using aggregation
reduces the load on the core handling to a quarter thus reducing IRQ
latency and increasing RX performance by around 10%.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c |  4 +++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 13 ++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 24d5f1cad7f4..92be59a1e4e7 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1861,9 +1861,11 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
+   /* enable interrupt delay for RX */
+   mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT);
+
/* disable delay and normal interrupt */
mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
-   mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 3c46a3b613b9..e130c3b24c4c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -125,7 +125,14 @@
 #define MTK_PST_DRX_IDX_CFG(x) (MTK_PST_DRX_IDX0 << (x))
 
 /* PDMA Delay Interrupt Register */
-#define MTK_PDMA_DELAY_INT 0xa0c
+#define MTK_PDMA_DELAY_INT 0xa0c
+#define MTK_PDMA_DELAY_RX_EN   BIT(15)
+#define MTK_PDMA_DELAY_RX_PINT 4
+#define MTK_PDMA_DELAY_RX_PINT_SHIFT   8
+#define MTK_PDMA_DELAY_RX_PTIME4
+#define MTK_PDMA_DELAY_RX_DELAY\
+   (MTK_PDMA_DELAY_RX_EN | MTK_PDMA_DELAY_RX_PTIME | \
+   (MTK_PDMA_DELAY_RX_PINT << MTK_PDMA_DELAY_RX_PINT_SHIFT))
 
 /* PDMA Interrupt Status Register */
 #define MTK_PDMA_INT_STATUS0xa20
@@ -206,6 +213,7 @@
 
 /* QDMA Interrupt Status Register */
 #define MTK_QMTK_INT_STATUS0x1A18
+#define MTK_RX_DONE_DLYBIT(30)
 #define MTK_RX_DONE_INT3   BIT(19)
 #define MTK_RX_DONE_INT2   BIT(18)
 #define MTK_RX_DONE_INT1   BIT(17)
@@ -214,8 +222,7 @@
 #define MTK_TX_DONE_INT2   BIT(2)
 #define MTK_TX_DONE_INT1   BIT(1)
 #define MTK_TX_DONE_INT0   BIT(0)
-#define MTK_RX_DONE_INT(MTK_RX_DONE_INT0 | MTK_RX_DONE_INT1 | \
-MTK_RX_DONE_INT2 | MTK_RX_DONE_INT3)
+#define MTK_RX_DONE_INTMTK_RX_DONE_DLY
 #define MTK_TX_DONE_INT(MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \
 MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3)
 
-- 
2.11.0



[PATCH 0/4] net-next: mediatek: various performance improvements

2017-06-19 Thread John Crispin
During development we mainly ran testing using iperf doing 1500 byte
tcp frames. It was pointed out recently, that the driver does not perform
very well when using 512 byte udp frames. The biggest problem was that
RPS was not working as no rx queue was being set. fixing this more than
doubled the throughput. Additionally the IRQ mask register is now locked
independently for RX and TX. RX IRQ aggregation is also added. With all
these patches applied we can almost triple the throughput.

While at it we also add PHY status change reporting for GMACs connecting
directly to a PHY.

John Crispin (4):
  net-next: mediatek: print phy status changes for non DSA GMACs
  net-next: mediatek: add RX IRQ delay support
  net-next: mediatek: split IRQ register locking into TX and RX
  net-next: mediatek: set the rx_queue to 0

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 87 +++--
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 18 --
 2 files changed, 71 insertions(+), 34 deletions(-)

-- 
2.11.0



[PATCH 1/4] net-next: mediatek: print phy status changes for non DSA GMACs

2017-06-19 Thread John Crispin
Currently PHY status changes are only printed for DSA ports. This patch
adds code to also print status changes for non-fixed links.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 962975d192d1..24d5f1cad7f4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -221,6 +221,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
netif_carrier_on(dev);
else
netif_carrier_off(dev);
+
+   if (!of_phy_is_fixed_link(mac->of_node))
+   phy_print_status(dev->phydev);
 }
 
 static int mtk_phy_connect_node(struct mtk_eth *eth, struct mtk_mac *mac,
-- 
2.11.0



Re: [PATCH V2 2/3] net-next: dsa: add multi cpu port support

2017-05-30 Thread John Crispin

Hi,

the patch series is based on net-next from 12 hours ago and works fine 
on that tree. I compile and runtime tested it quite intensively on 
various boards


John


On 30/05/17 17:38, kbuild test robot wrote:

Hi John,

[auto build test ERROR on net-next/master]
[also build test ERROR on next-20170530]
[cannot apply to v4.12-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/John-Crispin/Documentation-devicetree-add-multiple-cpu-port-DSA-binding/20170530-224954
config: x86_64-randconfig-x014-201722 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
 # save the attached .config to linux build tree
 make ARCH=x86_64

All error/warnings (new ones prefixed by >>):

In file included from include/linux/ioport.h:12:0,
 from include/linux/device.h:16,
 from net//dsa/dsa2.c:13:
net//dsa/dsa2.c: In function 'dsa_ds_parse':

net//dsa/dsa2.c:574:31: error: passing argument 1 of 'dsa_is_normal_port' from 
incompatible pointer type [-Werror=incompatible-pointer-types]

   else if (dsa_is_normal_port(port))
   ^
include/linux/compiler.h:160:30: note: in definition of macro '__trace_if'
  if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
  ^~~~

net//dsa/dsa2.c:574:8: note: in expansion of macro 'if'

   else if (dsa_is_normal_port(port))
^~
In file included from net//dsa/dsa_priv.h:17:0,
 from net//dsa/dsa2.c:22:
include/net/dsa.h:264:20: note: expected 'struct dsa_switch *' but argument 
is of type 'struct dsa_port *'
 static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
^~
In file included from include/linux/ioport.h:12:0,
 from include/linux/device.h:16,
 from net//dsa/dsa2.c:13:

net//dsa/dsa2.c:574:12: error: too few arguments to function 
'dsa_is_normal_port'

   else if (dsa_is_normal_port(port))
^
include/linux/compiler.h:160:30: note: in definition of macro '__trace_if'
  if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
  ^~~~

net//dsa/dsa2.c:574:8: note: in expansion of macro 'if'

   else if (dsa_is_normal_port(port))
^~
In file included from net//dsa/dsa_priv.h:17:0,
 from net//dsa/dsa2.c:22:
include/net/dsa.h:264:20: note: declared here
 static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
^~
In file included from include/linux/ioport.h:12:0,
 from include/linux/device.h:16,
 from net//dsa/dsa2.c:13:

net//dsa/dsa2.c:574:31: error: passing argument 1 of 'dsa_is_normal_port' from 
incompatible pointer type [-Werror=incompatible-pointer-types]

   else if (dsa_is_normal_port(port))
   ^
include/linux/compiler.h:160:42: note: in definition of macro '__trace_if'
  if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
  ^~~~

net//dsa/dsa2.c:574:8: note: in expansion of macro 'if'

   else if (dsa_is_normal_port(port))
^~
In file included from net//dsa/dsa_priv.h:17:0,
 from net//dsa/dsa2.c:22:
include/net/dsa.h:264:20: note: expected 'struct dsa_switch *' but argument 
is of type 'struct dsa_port *'
 static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
^~
In file included from include/linux/ioport.h:12:0,
 from include/linux/device.h:16,
 from net//dsa/dsa2.c:13:

net//dsa/dsa2.c:574:12: error: too few arguments to function 
'dsa_is_normal_port'

   else if (dsa_is_normal_port(port))
^
include/linux/compiler.h:160:42: note: in definition of macro '__trace_if'
  if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
  ^~~~

net//dsa/dsa2.c:574:8: note: in expansion of macro 'if'

   else if (dsa_is_normal_port(port))
^~
In file included from net//dsa/dsa_priv.h:17:0,
 from net//dsa/dsa2.c:22:
include/net/dsa.h:264:20: note: declared here
 static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
^~
In file included from include/linux/ioport.h:12:0,
 from include/linux/device.h:16,
 from net//dsa/dsa2.c:13:

net//dsa/dsa2.c:574:31: error: passing argument 1 of 'dsa_is_normal_port' from 
incompatible pointer type [-Werror=incompatible-pointer-types]

   else if (dsa_is_normal_port(port))
   ^
include

[PATCH V2 3/3] net-next: dsa: mt7530: add multi cpu port support

2017-05-30 Thread John Crispin
MT7530 switches have 2 CPU ports. Inside an MT7623a these are connected
to GMAC1 and GMAC2. The code currently has the CPU hard coded to 6. Change
this to using the new dsa_port_upstream_port() api. In case port 5 is not
setup as a cpu port, we configure the RGMII passthrough mode allowing GMAC2
to connect to an external PHY.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/mt7530.c | 45 +
 drivers/net/dsa/mt7530.h |  1 -
 2 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 4d2f45153ede..370e0833474b 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -632,6 +632,9 @@ static int
 mt7530_cpu_port_enable(struct mt7530_priv *priv,
   int port)
 {
+   u8 port_mask = 0;
+   int i;
+
/* Enable Mediatek header mode on the cpu port */
mt7530_write(priv, MT7530_PVC_P(port),
 PORT_SPEC_TAG);
@@ -648,8 +651,12 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
/* CPU port gets connected to all user ports of
 * the switch
 */
+   for (i = 0; i < MT7530_NUM_PORTS; i++)
+   if ((priv->ds->enabled_port_mask & BIT(i)) &&
+   (dsa_port_upstream_port(priv->ds, i) == port))
+   port_mask |= BIT(i);
mt7530_write(priv, MT7530_PCR_P(port),
-PCR_MATRIX(priv->ds->enabled_port_mask));
+PCR_MATRIX(port_mask));
 
return 0;
 }
@@ -659,6 +666,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
   struct phy_device *phy)
 {
struct mt7530_priv *priv = ds->priv;
+   u8 upstream = dsa_port_upstream_port(ds, port);
 
mutex_lock(>reg_mutex);
 
@@ -669,7 +677,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
 * restore the port matrix if the port is the member of a certain
 * bridge.
 */
-   priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT));
+   priv->ports[port].pm |= PCR_MATRIX(BIT(upstream));
priv->ports[port].enable = true;
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
   priv->ports[port].pm);
@@ -732,7 +740,8 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *bridge)
 {
struct mt7530_priv *priv = ds->priv;
-   u32 port_bitmap = BIT(MT7530_CPU_PORT);
+   u8 upstream = dsa_port_upstream_port(ds, port);
+   u32 port_bitmap = BIT(upstream);
int i;
 
mutex_lock(>reg_mutex);
@@ -770,6 +779,7 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
 struct net_device *bridge)
 {
struct mt7530_priv *priv = ds->priv;
+   u8 upstream = dsa_port_upstream_port(ds, port);
int i;
 
mutex_lock(>reg_mutex);
@@ -794,8 +804,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
 */
if (priv->ports[port].enable)
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
-  PCR_MATRIX(BIT(MT7530_CPU_PORT)));
-   priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
+  PCR_MATRIX(BIT(upstream)));
+   priv->ports[port].pm = PCR_MATRIX(BIT(upstream));
 
mutex_unlock(>reg_mutex);
 }
@@ -892,15 +902,7 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
 static enum dsa_tag_protocol
 mtk_get_tag_protocol(struct dsa_switch *ds)
 {
-   struct mt7530_priv *priv = ds->priv;
-
-   if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) {
-   dev_warn(priv->dev,
-"port not matched with tagging CPU port\n");
-   return DSA_TAG_PROTO_NONE;
-   } else {
-   return DSA_TAG_PROTO_MTK;
-   }
+   return DSA_TAG_PROTO_MTK;
 }
 
 static int
@@ -971,10 +973,21 @@ mt7530_setup(struct dsa_switch *ds)
 SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
 SYS_CTRL_REG_RST);
 
-   /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */
+   /* Enable Port 6. Port 5 is setup in passthrough mode if it is not a CPU
+* port
+*/
val = mt7530_read(priv, MT7530_MHWTRAP);
-   val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
+   val &= ~MHWTRAP_P5_DIS & ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
val |= MHWTRAP_MANUAL;
+   if (!dsa_is_cpu_port(ds, 5)) {
+   val |= MHWTRAP_P5_DIS;
+   val |= MHWTRAP_P5_MAC_SEL;
+   val |= MHWTRAP_P5_RGMII_MODE;
+   } else if (0) {
+   val &= ~MHWTRAP_P5_DIS;
+   val &= ~MHWTRAP_P5_MAC_SEL;
+   val &= ~MHWTRAP_P5_RGMII_MODE;
+   }
mt7530_write(priv, MT7530_MHWTRAP, val);
 
 

[PATCH V2 2/3] net-next: dsa: add multi cpu port support

2017-05-30 Thread John Crispin
Some boards have two CPU interfaces connected to the switch, e.g. WiFi
access points, with 1 port labeled WAN, 4 ports labeled lan1-lan4, and
two port connected to the SoC.

This patch extends DSA to allows both CPU ports to be used. The "cpu"
node in the DSA tree can now have a phandle to the host interface it
connects to. Each user port can have a phandle to a cpu port which
should be used for traffic between the port and the CPU. Thus simple
load sharing over the two CPU ports can be achieved.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h  | 21 -
 net/dsa/dsa2.c | 35 +++
 net/dsa/dsa_priv.h |  1 +
 net/dsa/slave.c| 26 --
 4 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index c0e567c0c824..d2994bd2c507 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -186,6 +186,8 @@ struct dsa_port {
u8  stp_state;
struct net_device   *bridge_dev;
struct devlink_port devlink_port;
+   struct net_device   *ethernet;
+   int upstream;
 };
 
 struct dsa_switch {
@@ -251,7 +253,7 @@ struct dsa_switch {
 
 static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
 {
-   return ds->dst->cpu_dp == >ports[p];
+   return !!(ds->cpu_port_mask & (1 << p));
 }
 
 static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
@@ -269,6 +271,11 @@ static inline bool dsa_is_port_initialized(struct 
dsa_switch *ds, int p)
return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
 }
 
+static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p)
+{
+   return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p);
+}
+
 static inline u8 dsa_upstream_port(struct dsa_switch *ds)
 {
struct dsa_switch_tree *dst = ds->dst;
@@ -285,6 +292,18 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
return ds->rtable[dst->cpu_dp->ds->index];
 }
 
+static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port)
+{
+   /*
+* If this port has a specific upstream cpu port, use it,
+* otherwise use the switch default.
+*/
+   if (ds->ports[port].upstream)
+   return ds->ports[port].upstream;
+   else
+   return dsa_upstream_port(ds);
+}
+
 struct dsa_switch_ops {
/*
 * Legacy probing.
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4301f52e4f5a..8b13aa735c40 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -253,8 +253,6 @@ static int dsa_cpu_port_apply(struct dsa_port *port, u32 
index,
return err;
}
 
-   ds->cpu_port_mask |= BIT(index);
-
memset(>ports[index].devlink_port, 0,
   sizeof(ds->ports[index].devlink_port));
err = devlink_port_register(ds->devlink, >ports[index].devlink_port,
@@ -269,6 +267,10 @@ static void dsa_cpu_port_unapply(struct dsa_port *port, 
u32 index,
dsa_cpu_dsa_destroy(port);
ds->cpu_port_mask &= ~BIT(index);
 
+   if (ds->ports[index].ethernet) {
+   dev_put(ds->ports[index].ethernet);
+   ds->ports[index].ethernet = NULL;
+   }
 }
 
 static int dsa_user_port_apply(struct dsa_port *port, u32 index,
@@ -530,6 +532,29 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
 
dst->rcv = dst->tag_ops->rcv;
 
+   dev_hold(ethernet_dev);
+   ds->ports[index].ethernet = ethernet_dev;
+   ds->cpu_port_mask |= BIT(index);
+
+   return 0;
+}
+
+static int dsa_user_parse(struct device_node *port, u32 index,
+ struct dsa_switch *ds)
+{
+   struct device_node *cpu_port;
+   const unsigned int *cpu_port_reg;
+   int cpu_port_index;
+
+   cpu_port = of_parse_phandle(port, "cpu", 0);
+   if (cpu_port) {
+   cpu_port_reg = of_get_property(cpu_port, "reg", NULL);
+   if (!cpu_port_reg)
+   return -EINVAL;
+   cpu_port_index = be32_to_cpup(cpu_port_reg);
+   ds->ports[index].upstream = cpu_port_index;
+   }
+
return 0;
 }
 
@@ -544,11 +569,13 @@ static int dsa_ds_parse(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
if (!dsa_port_is_valid(port))
continue;
 
-   if (dsa_port_is_cpu(port)) {
+   if (dsa_port_is_cpu(port))
err = dsa_cpu_parse(port, index, dst, ds);
+   else if (dsa_is_normal_port(port))
+   err = dsa_user_parse(port->dn, index,  ds);
+
if (err)
return err;
-   }
}
 
pr_info("DSA: switch %d %d parse

[PATCH V2 1/3] Documentation: devicetree: add multiple cpu port DSA binding

2017-05-30 Thread John Crispin
Extend the DSA binding documentation, adding the new property required
when there is more than one CPU port attached to the switch.

Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Signed-off-by: John Crispin <j...@phrozen.org>
---
 Documentation/devicetree/bindings/net/dsa/dsa.txt | 61 ++-
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt 
b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index cfe8f64eca4f..c164eb38ccc5 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -55,6 +55,11 @@ A user port has the following optional property:
 - label: Describes the label associated with this 
port, which
   will become the netdev name.
 
+- cpu  : Option for non "cpu"/"dsa" ports. A phandle to a
+ "cpu" port, which will be used for passing packets
+ from this port to the host. If not present, the first
+ "cpu" port will be used.
+
 Port child nodes may also contain the following optional standardised
 properties, described in binding documents:
 
@@ -71,7 +76,7 @@ properties, described in binding documents:
  Documentation/devicetree/bindings/net/fixed-link.txt
  for details.
 
-Example
+Examples
 
 The following example shows three switches on three MDIO busses,
 linked into one DSA cluster.
@@ -264,6 +269,60 @@ linked into one DSA cluster.
};
 };
 
+The following example shows a switch that has two cpu ports each connecting
+to a different MAC.
+
+ {
+   switch@0 {
+   compatible = "mediatek,mt7530";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   port@0 {
+   reg = <0>;
+   label = "lan0";
+   cpu = <_port1>;
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   cpu = <_port1>;
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   cpu = <_port1>;
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "wan";
+   cpu = <_port2>;
+   };
+
+   cpu_port2: port@5 {
+   reg = <5>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "trgmii";
+   };
+
+   cpu_port1: port@6 {
+   reg = <6>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "trgmii";
+   };
+   };
+   };
+};
+
 Deprecated Binding
 --
 
-- 
2.11.0



Re: [PATCH net-next v2 5/5] net-next: dsa: add dsa support for Mediatek MT7530 switch

2017-03-23 Thread John Crispin



On 23/03/17 15:09, Felix Fietkau wrote:

On 2017-03-23 09:06, Sean Wang wrote:

Hi Andrew,

The purpose for the regmap table registered is to

provide a way which helps us to look up a specific

register on the switch through regmap-debugfs.


And not all ranges of register is defined

so I only include the meaningful ones in a sparse way

for the table.

I think in that case it might be nice to make regmap support optional in
order to avoid pulling in bloat on platforms that don't need it.

- Felix

The 2 relevant platforms are mips/ralink and arm/mediatek. both require 
regmap for the eth_sysctl syscon if they want to utilize the mtk_soc_eth 
driver which is a prereq for mt7530. so regmap cannot be optional here.


John




___
Linux-mediatek mailing list
linux-media...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek




Re: [PATCH net-next 0/4] net-next: dsa: add Mediatek MT7530 support

2017-03-13 Thread John Crispin



On 13/03/17 17:11, sean.w...@mediatek.com wrote:

From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N which includes 7-port
Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY. Among these ports,
The port from 0 to 4 are the user ports connecting with the remote devices
while the port 5 and 6 are the CPU ports connecting into Mediatek Ethernet
GMAC.

The patch series integrated Mediatek MT7530 into DSA support which
includes the most of the essential callbacks such as tag insertion for
port distinguishing, port control, bridge offloading, STP setup and
ethtool operations to allow DSA to model each user port into independently
standalone netdevice as the other DSA driver had done.

Hi Sean,

very cool, i'll give this a spin this week and if it works out will 
import it into LEDE to get test coverage from our users.


John


Sean Wang (4):
   dt-bindings: net: dsa: add mt7530 binding
   net-next: dsa: add Mediatek tag RX/TX handler
   net-next: ethernet: mediatek: add CMD ingress recognize the special
 tag
   net-next: dsa: add dsa support for Mediatek MT7530 switch

  .../devicetree/bindings/net/dsa/mt7530.txt |   96 ++
  drivers/net/dsa/Kconfig|8 +
  drivers/net/dsa/Makefile   |2 +-
  drivers/net/dsa/mt7530.c   | 1195 
  drivers/net/dsa/mt7530.h   |  387 +++
  drivers/net/ethernet/mediatek/mtk_eth_soc.c|8 +
  drivers/net/ethernet/mediatek/mtk_eth_soc.h|5 +
  include/net/dsa.h  |1 +
  net/dsa/Kconfig|2 +
  net/dsa/Makefile   |1 +
  net/dsa/dsa.c  |3 +
  net/dsa/dsa_priv.h |3 +
  net/dsa/tag_mtk.c  |  121 ++
  13 files changed, 1831 insertions(+), 1 deletion(-)
  create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt
  create mode 100644 drivers/net/dsa/mt7530.c
  create mode 100644 drivers/net/dsa/mt7530.h
  create mode 100644 net/dsa/tag_mtk.c





[PATCH 1/2] Documentation: devicetree: change the mediatek ethernet compatible string

2017-01-25 Thread John Crispin
When the binding was defined, I was not aware that mt2701 was an earlier
version of the SoC. For sake of consistency, the ethernet driver should
use mt2701 inside the compat string as this is the earliest SoC with the
ethernet core.

The ethernet driver is currently of no real use until we finish and
upstream the DSA driver. There are no users of this binding yet. It should
be safe to fix this now before it is too late and we need to provide
backward compatibility for the mt7623-eth compat string.

Reported-by: Sean Wang <sean.w...@mediatek.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 Documentation/devicetree/bindings/net/mediatek-net.txt |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index c010faf..c7194e8 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -7,7 +7,7 @@ have dual GMAC each represented by a child node..
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt7623-eth"
+- compatible: Should be "mediatek,mt2701-eth"
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
order. These are fe_int0, fe_int1 and fe_int2.
-- 
1.7.10.4



[PATCH 2/2] net-next: ethernet: mediatek: change the compatible string

2017-01-25 Thread John Crispin
When the binding was defined, I was not aware that mt2701 was an earlier
version of the SoC. For sake of consistency, the ethernet driver should
use mt2701 inside the compat string as this is the earliest SoC with the
ethernet core.

The ethernet driver is currently of no real use until we finish and
upstream the DSA driver. There are no users of this binding yet. It should
be safe to fix this now before it is too late and we need to provide
backward compatibility for the mt7623-eth compat string.

Reported-by: Sean Wang <sean.w...@mediatek.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 25ae0c5..9e75768 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2515,7 +2515,7 @@ static int mtk_remove(struct platform_device *pdev)
 }
 
 const struct of_device_id of_mtk_match[] = {
-   { .compatible = "mediatek,mt7623-eth" },
+   { .compatible = "mediatek,mt2701-eth" },
{},
 };
 MODULE_DEVICE_TABLE(of, of_mtk_match);
-- 
1.7.10.4



[PATCH] net-next: korina: Fix NAPI versus resources freeing

2017-01-04 Thread John Crispin
From: Florian Fainelli <f.faine...@gmail.com>

Commit beb0babfb77e ("korina: disable napi on close and restart")
introduced calls to napi_disable() that were missing before,
unfortunately this leaves a small window during which NAPI has a chance
to run, yet we just freed resources since korina_free_ring() has been
called:

Fix this by disabling NAPI first then freeing resource, and make sure
that we also cancel the restart taks before doing the resource freeing.

Fixes: beb0babfb77e ("korina: disable napi on close and restart")

Reported-by: Alexandros C. Couloumbis <a...@ozo.com>
Tested-by: John Crispin <j...@phrozen.org>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/ethernet/korina.c |8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 1799fe1..c051987 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -900,10 +900,10 @@ static void korina_restart_task(struct work_struct *work)
DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
>rx_dma_regs->dmasm);
 
-   korina_free_ring(dev);
-
napi_disable(>napi);
 
+   korina_free_ring(dev);
+
if (korina_init(dev) < 0) {
printk(KERN_ERR "%s: cannot restart device\n", dev->name);
return;
@@ -1064,12 +1064,12 @@ static int korina_close(struct net_device *dev)
tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
writel(tmp, >rx_dma_regs->dmasm);
 
-   korina_free_ring(dev);
-
napi_disable(>napi);
 
cancel_work_sync(>restart_task);
 
+   korina_free_ring(dev);
+
free_irq(lp->rx_irq, dev);
free_irq(lp->tx_irq, dev);
free_irq(lp->ovr_irq, dev);
-- 
1.7.10.4



[RFC 0/4] net-next: dsa: add support for multiple cpu ports

2017-01-03 Thread John Crispin
This series is based on work from Andrew. I have rebased his patches to
work on the latest kernel. The main problem is probably the fact that the
cpu port to user port mapping happens inside the devicetree.

Andrew Lunn (3):
  Documentation: devicetree: add multiple cpu port DSA binding
  net-next: dsa: Refactor DT probing of a switch port
  net-next: dsa: Add support for multiple cpu ports.

John Crispin (1):
  net-next: dsa: qca8k: add support for multiple cpu ports

 Documentation/devicetree/bindings/net/dsa/dsa.txt |   67 +-
 drivers/net/dsa/qca8k.c   |  135 +++-
 drivers/net/dsa/qca8k.h   |2 -
 include/net/dsa.h |   21 +++-
 net/dsa/dsa.c |  138 +++--
 net/dsa/dsa2.c|   36 +-
 net/dsa/dsa_priv.h|5 +
 net/dsa/slave.c   |   27 ++--
 8 files changed, 317 insertions(+), 114 deletions(-)

-- 
1.7.10.4



[RFC 3/4] net-next: dsa: Add support for multiple cpu ports.

2017-01-03 Thread John Crispin
From: Andrew Lunn <and...@lunn.ch>

Some boards have two CPU interfaces connected to the switch, e.g. WiFi
access points, with 1 port labeled WAN, 4 ports labeled lan1-lan4, and
two port connected to the SoC.

This patch extends DSA to allows both CPU ports to be used. The "cpu"
node in the DSA tree can now have a phandle to the host interface it
connects to. Each user port can have a phandle to a cpu port which
should be used for traffic between the port and the CPU. Thus simple
load sharing over the two CPU ports can be achieved.

Signed-off-by: John Crispin <j...@phrozen.org>
Signed-off-by: Andrew Lunn <and...@lunn.ch>
---
 include/net/dsa.h  |   21 -
 net/dsa/dsa2.c |   36 ++--
 net/dsa/dsa_priv.h |5 +
 net/dsa/slave.c|   27 ---
 4 files changed, 71 insertions(+), 18 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index b122196..f68180b 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -60,6 +60,8 @@ struct dsa_chip_data {
 */
char*port_names[DSA_MAX_PORTS];
struct device_node *port_dn[DSA_MAX_PORTS];
+   struct net_device *port_ethernet[DSA_MAX_PORTS];
+   int port_cpu[DSA_MAX_PORTS];
 
/*
 * An array of which element [a] indicates which port on this
@@ -204,7 +206,7 @@ struct dsa_switch {
 
 static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
 {
-   return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
+   return !!(ds->cpu_port_mask & (1 << p));
 }
 
 static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
@@ -217,6 +219,11 @@ static inline bool dsa_is_port_initialized(struct 
dsa_switch *ds, int p)
return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
 }
 
+static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p)
+{
+   return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p);
+}
+
 static inline u8 dsa_upstream_port(struct dsa_switch *ds)
 {
struct dsa_switch_tree *dst = ds->dst;
@@ -233,6 +240,18 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
return ds->rtable[dst->cpu_switch];
 }
 
+static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port)
+{
+   /*
+* If this port has a specific upstream cpu port, use it,
+* otherwise use the switch default.
+*/
+   if (ds->cd->port_cpu[port])
+   return ds->cd->port_cpu[port];
+   else
+   return dsa_upstream_port(ds);
+}
+
 struct switchdev_trans;
 struct switchdev_obj;
 struct switchdev_obj_port_fdb;
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 5fff951..1763cd4 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -258,7 +258,7 @@ static void dsa_cpu_port_unapply(struct device_node *port, 
u32 index,
 {
dsa_cpu_dsa_destroy(port);
ds->cpu_port_mask &= ~BIT(index);
-
+   dev_put(ds->cd->port_ethernet[index]);
 }
 
 static int dsa_user_port_apply(struct device_node *port, u32 index,
@@ -475,6 +475,28 @@ static int dsa_cpu_parse(struct device_node *port, u32 
index,
 
dst->rcv = dst->tag_ops->rcv;
 
+   dev_hold(ethernet_dev);
+   ds->cd->port_ethernet[index] = ethernet_dev;
+
+   return 0;
+}
+
+static int dsa_user_parse(struct device_node *port, u32 index,
+ struct dsa_switch *ds)
+{
+   struct device_node *cpu_port;
+   const unsigned int *cpu_port_reg;
+   int cpu_port_index;
+
+   cpu_port = of_parse_phandle(port, "cpu", 0);
+   if (cpu_port) {
+   cpu_port_reg = of_get_property(cpu_port, "reg", NULL);
+   if (!cpu_port_reg)
+   return -EINVAL;
+   cpu_port_index = be32_to_cpup(cpu_port_reg);
+   ds->cd->port_cpu[index] = cpu_port_index;
+   }
+
return 0;
 }
 
@@ -482,18 +504,20 @@ static int dsa_ds_parse(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
 {
struct device_node *port;
u32 index;
-   int err;
+   int err = 0;
 
for (index = 0; index < DSA_MAX_PORTS; index++) {
port = ds->ports[index].dn;
if (!port)
continue;
 
-   if (dsa_port_is_cpu(port)) {
+   if (dsa_port_is_cpu(port))
err = dsa_cpu_parse(port, index, dst, ds);
-   if (err)
-   return err;
-   }
+   else if (!dsa_port_is_dsa(port))
+   err = dsa_user_parse(port, index,  ds);
+
+   if (err)
+   return err;
}
 
pr_info("DSA: switch %d %d parsed\n", dst->tree, ds->index);
diff --git a/

[RFC 1/4] Documentation: devicetree: add multiple cpu port DSA binding

2017-01-03 Thread John Crispin
From: Andrew Lunn 

Extend the DSA binding documentation, adding the new properties required
when there is more than one CPU port attached to the switch.

Cc: Rob Herring 
Cc: devicet...@vger.kernel.org
Signed-off-by: Andrew Lunn 
---
 Documentation/devicetree/bindings/net/dsa/dsa.txt |   67 -
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt 
b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index a4a570f..fc901cf 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -337,13 +337,25 @@ Optional property:
  This mii-bus will be used in preference to the
  global dsa,mii-bus defined above, for this switch.
 
+- ethernet : Optional for "cpu" ports. A phandle to an ethernet
+  device which will be used by this CPU port for
+ passing packets to/from the host. If not present,
+ the port will use the "dsa,ethernet" property
+ defined above.
+
+- cpu  : Option for non "cpu"/"dsa" ports. A phandle to a
+ "cpu" port, which will be used for passing packets
+ from this port to the host. If not present, the first
+ "cpu" port will be used.
+
+
 Optional subnodes:
 - fixed-link   : Fixed-link subnode describing a link to a non-MDIO
  managed entity. See
  Documentation/devicetree/bindings/net/fixed-link.txt
  for details.
 
-Example:
+Examples:
 
dsa@0 {
compatible = "marvell,dsa";
@@ -416,3 +428,56 @@ Example:
};
};
};
+
+   dsa@1 {
+   compatible = "marvell,dsa";
+   #address-cells = <2>;
+   #size-cells = <0>;
+
+   dsa,ethernet = <>;
+   dsa,mii-bus = <>;
+
+   switch@0 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0 0>;/* MDIO address 0, switch 0 in tree */
+
+   port@0 {
+   reg = <0>;
+   label = "lan4";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan3";
+   cpu = <>;
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan1";
+   cpu = <>;
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "wan";
+   };
+
+   port@5 {
+   reg = <5>;
+   label = "cpu";
+   };
+
+   cpu1: port@6 {
+   reg = <6>;
+   label = "cpu";
+   ethernet = <>;
+   };
+   };
+   };
-- 
1.7.10.4



[RFC 4/4] net-next: dsa: qca8k: add support for multiple cpu ports

2017-01-03 Thread John Crispin
With the subsystem now supporting multiple cpu ports, we need to make some
changes to the driver as it currently has the cpu port hardcoded as port0.
The patch moves the setup logic for the cpu port into one loop which
iterates over all cpu ports and sets them up. Additionally the bridge
join/leave logic needs a small fix to work with having a cpu port other
than 0.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/qca8k.c |  135 +++
 drivers/net/dsa/qca8k.h |2 -
 2 files changed, 78 insertions(+), 59 deletions(-)

diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index b3df70d..1693388 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -486,11 +486,25 @@
qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
 }
 
+static void
+qca8k_setup_flooding(struct qca8k_priv *priv, int port_mask, int enable)
+{
+   u32 mask = (port_mask << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S) |
+  (port_mask << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S) |
+  (port_mask << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S) |
+  (port_mask << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
+
+   if (enable)
+   qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL1, mask);
+   else
+   qca8k_reg_clear(priv, QCA8K_REG_GLOBAL_FW_CTRL1, mask);
+}
+
 static int
 qca8k_setup(struct dsa_switch *ds)
 {
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
-   int ret, i, phy_mode = -1;
+   int ret, i;
 
/* Make sure that port 0 is the cpu port */
if (!dsa_is_cpu_port(ds, 0)) {
@@ -506,29 +520,49 @@
if (IS_ERR(priv->regmap))
pr_warn("regmap initialization failed");
 
-   /* Initialize CPU port pad mode (xMII type, delays...) */
-   phy_mode = of_get_phy_mode(ds->ports[ds->dst->cpu_port].dn);
-   if (phy_mode < 0) {
-   pr_err("Can't find phy-mode for master device\n");
-   return phy_mode;
-   }
-   ret = qca8k_set_pad_ctrl(priv, QCA8K_CPU_PORT, phy_mode);
-   if (ret < 0)
-   return ret;
-
-   /* Enable CPU Port */
+   /* Tell the switch that port0 is a cpu port */
qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
  QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
-   qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1);
-   priv->port_sts[QCA8K_CPU_PORT].enabled = 1;
 
/* Enable MIB counters */
qca8k_mib_init(priv);
 
-   /* Enable QCA header mode on the cpu port */
-   qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
-   QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
-   QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
+   /* Setup the cpu ports */
+   for (i = 0; i < DSA_MAX_PORTS; i++) {
+   struct net_device *netdev;
+   int phy_mode = -1;
+
+   if (!dsa_is_cpu_port(ds, i))
+   continue;
+
+   netdev = ds->dst->pd->chip->port_ethernet[i];
+   if (!netdev) {
+   pr_err("Can't find netdev for port%d\n", i);
+   return -ENODEV;
+   }
+
+   /* Initialize CPU port pad mode (xMII type, delays...) */
+   phy_mode = of_get_phy_mode(netdev->dev.parent->of_node);
+   if (phy_mode < 0) {
+   pr_err("Can't find phy-mode for port:%d\n", i);
+   return phy_mode;
+   }
+   ret = qca8k_set_pad_ctrl(priv, i, phy_mode);
+   if (ret < 0)
+   return ret;
+
+   /* Enable QCA header mode on the cpu port */
+   qca8k_write(priv,
+   QCA8K_REG_PORT_HDR_CTRL(i),
+   QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S 
|
+   QCA8K_PORT_HDR_CTRL_ALL << 
QCA8K_PORT_HDR_CTRL_RX_S);
+
+   qca8k_port_set_status(priv, i, 1);
+   priv->port_sts[i].enabled = 1;
+
+   /* Forward all unknown frames to CPU port for Linux processing 
*/
+   qca8k_setup_flooding(priv, BIT(i), 1);
+   }
 
/* Disable forwarding by default on all ports */
for (i = 0; i < QCA8K_NUM_PORTS; i++)
@@ -540,43 +574,30 @@
if (ds->enabled_port_mask & BIT(i))
qca8k_port_set_status(priv, i, 0);
 
-   /* Forward all unknown frames to CPU port for Linux processing */
-   qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
-   BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
-   BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
-   BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
-

[RFC 2/4] net-next: dsa: Refactor DT probing of a switch port

2017-01-03 Thread John Crispin
From: Andrew Lunn 

Move the DT probing of a switch port into a function of its own, since
it is about to get more complex. Add better error handling as well.

Signed-off-by: Andrew Lunn 
---
 net/dsa/dsa.c |  138 ++---
 1 file changed, 102 insertions(+), 36 deletions(-)

diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 7899919..0e0621c 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -326,14 +326,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, 
struct device *parent)
continue;
 
if (!strcmp(name, "cpu")) {
-   if (dst->cpu_switch != -1) {
-   netdev_err(dst->master_netdev,
-  "multiple cpu ports?!\n");
-   ret = -EINVAL;
-   goto out;
+   if (dst->cpu_switch == -1) {
+   dst->cpu_switch = index;
+   dst->cpu_port = i;
}
-   dst->cpu_switch = index;
-   dst->cpu_port = i;
ds->cpu_port_mask |= 1 << i;
} else if (!strcmp(name, "dsa")) {
ds->dsa_port_mask |= 1 << i;
@@ -709,11 +705,15 @@ static void dsa_of_free_platform_data(struct 
dsa_platform_data *pd)
 {
int i;
int port_index;
+   struct dsa_chip_data *cd;
 
for (i = 0; i < pd->nr_chips; i++) {
+   cd = >chip[i];
port_index = 0;
while (port_index < DSA_MAX_PORTS) {
-   kfree(pd->chip[i].port_names[port_index]);
+   kfree(cd->port_names[port_index]);
+   if (cd->port_ethernet[port_index])
+   dev_put(cd->port_ethernet[port_index]);
port_index++;
}
 
@@ -724,6 +724,94 @@ static void dsa_of_free_platform_data(struct 
dsa_platform_data *pd)
kfree(pd->chip);
 }
 
+static int dsa_of_probe_cpu_port(struct dsa_chip_data *cd,
+struct device_node *port,
+int port_index)
+{
+   struct net_device *ethernet_dev;
+   struct device_node *ethernet;
+
+   ethernet = of_parse_phandle(port, "ethernet", 0);
+   if (ethernet) {
+   ethernet_dev = of_find_net_device_by_node(ethernet);
+   if (!ethernet_dev)
+   return -EPROBE_DEFER;
+
+   dev_hold(ethernet_dev);
+   cd->port_ethernet[port_index] = ethernet_dev;
+   }
+
+   return 0;
+}
+
+static int dsa_of_probe_user_port(struct dsa_chip_data *cd,
+ struct device_node *port,
+ int port_index)
+{
+   struct device_node *cpu_port;
+   const unsigned int *cpu_port_reg;
+   int cpu_port_index;
+
+   cpu_port = of_parse_phandle(port, "cpu", 0);
+   if (cpu_port) {
+   cpu_port_reg = of_get_property(cpu_port, "reg", NULL);
+   if (!cpu_port_reg)
+   return -EINVAL;
+   cpu_port_index = be32_to_cpup(cpu_port_reg);
+   cd->port_cpu[port_index] = cpu_port_index;
+   }
+
+   return 0;
+}
+
+static int dsa_of_probe_port(struct dsa_platform_data *pd,
+struct dsa_chip_data *cd,
+int chip_index,
+struct device_node *port)
+{
+   bool is_cpu_port = false, is_dsa_port = false;
+   bool is_user_port = false;
+   const unsigned int *port_reg;
+   const char *port_name;
+   int port_index, ret = 0;
+
+   port_reg = of_get_property(port, "reg", NULL);
+   if (!port_reg)
+   return -EINVAL;
+
+   port_index = be32_to_cpup(port_reg);
+
+   port_name = of_get_property(port, "label", NULL);
+   if (!port_name)
+   return -EINVAL;
+
+   if (!strcmp(port_name, "cpu"))
+   is_cpu_port = true;
+   if (!strcmp(port_name, "dsa"))
+   is_dsa_port = true;
+   if (!is_cpu_port && !is_dsa_port)
+   is_user_port = true;
+
+   cd->port_dn[port_index] = port;
+
+   cd->port_names[port_index] = kstrdup(port_name,
+   GFP_KERNEL);
+   if (!cd->port_names[port_index])
+   return -ENOMEM;
+
+   if (is_dsa_port)
+   ret = dsa_of_probe_links(pd, cd, chip_index,
+port_index, port, port_name);
+   if (is_cpu_port)
+   ret = dsa_of_probe_cpu_port(cd, port, port_index);
+   if (is_user_port)
+   ret = dsa_of_probe_user_port(cd, port, port_index);
+   if (ret)
+   return ret;
+
+   return port_index;
+}
+
 static int dsa_of_probe(struct 

Re: [PATCH net-next 1/3] net:dsa:mv88e6xxx: use hashtable to store multicast entries

2016-12-16 Thread John Crispin


On 16/12/2016 10:24, Volodymyr Bendiuga wrote:
> Hi all,
> 
> Does this mean we all agree on implementing caching
> mechanism in net/dsa layer? If yes, then I can start
> working on it immediately.
> 
> Regards,
> Volodymyr

i think that the brcm approach is better as at least on QCA you can also
read auto learned values from the table which would get broken by a
caching mechanism. filtering inside the dump function or the code
calling the dump function seams a lot simpler and lightweight to me.

John

> 
> On Thu, Dec 15, 2016 at 6:50 PM, Vivien Didelot
>  > wrote:
> 
> Florian Fainelli  > writes:
> 
> >> In all cases *if caching is really needed*, I think it won't hurt to do
> >> it in DSA core even if a switch support FDB dump operations on a
> >> per-port basis, as Andrew mentioned.
> >
> > Agreed, and there does not appear to be any need to new dsa_switch_ops
> > operations to be introduced?
> 
> Nope.
> 
> 


Re: [PATCH net-next 1/3] net:dsa:mv88e6xxx: use hashtable to store multicast entries

2016-12-15 Thread John Crispin


On 15/12/2016 18:21, Vivien Didelot wrote:
> Hi Volodymyr,
> 
> Volodymyr Bendiuga  writes:
> 
>> Hi Andrew,
>>
>> I have tested the approach you wrote in previous mails, the one
>> with setting next.mac to address we are looking for -1. It seems
>> to be as slow as the original implementation, unfortunately.
> 
> Hum, that is what I was expecting... The ATU GetNext operation
> (alongside an ether_addr_equal() call) should be quite fast.
> 
>> We use 6097 and 6352 chips, and both of them can not do any port
>> filtering in hardware for fdb dump operation. Seems like they would
>> benefit from cache. But I am not sure about other switches.
>>
>> Does anyone know about such feature in other switches?
> 
> Marvell switches cannot filter ATU entries for a specific port, they
> contain a port vector.
> 
> I guess Florian might answer for Broadcom switches, and John might
> answer for Qualcomm switches.
> 
> In all cases *if caching is really needed*, I think it won't hurt to do
> it in DSA core even if a switch support FDB dump operations on a
> per-port basis, as Andrew mentioned.


QCA switches allow defining a port mask in a fdb search/iterate
operation. just had a look in the brcm driver and it filters in software

John


Re: dsa: handling more than 1 cpu port

2016-12-14 Thread John Crispin


On 14/12/2016 12:00, Andrew Lunn wrote:
> On Wed, Dec 14, 2016 at 11:35:30AM +0100, John Crispin wrote:
>>
>>
>> On 14/12/2016 11:31, Andrew Lunn wrote:
>>> On Wed, Dec 14, 2016 at 11:01:54AM +0100, John Crispin wrote:
>>>> Hi Andrew,
>>>>
>>>> switches supported by qca8k have 2 gmacs that we can wire an external
>>>> mii interface to. Usually this is used to wire 2 of the SoCs MACs to the
>>>> switch. Thw switch itself is aware of one of the MACs being the cpu port
>>>> and expects this to be port/mac0. Using the other will break the
>>>> hardware offloading features.
>>>
>>> Just to be sure here. There is no way to use the second port connected
>>> to the CPU as a CPU port?
>>
>> both macs are considered cpu ports and both allow for the tag to be
>> injected. for HW NAT/routing/... offloading to work, the lan ports neet
>> to trunk via port0 and not port6 however.
> 
> Maybe you can do a restricted version of the generic solution. LAN
> ports are mapped to cpu port0. WAN port to cpu port 6?
> 
>>> The Marvell chips do allow this. So i developed a proof of concept
>>> which had a mapping between cpu ports and slave ports. slave port X
>>> should you cpu port y for its traffic. This never got past proof of
>>> concept. 
>>>
>>> If this can be made to work for qca8k, i would prefer having this
>>> general concept, than specific hacks for pass through.
>>
>> oh cool, can you send those patches my way please ? how do you configure
>> this from userland ? does the cpu port get its on swdev which i just add
>> to my lan bridge and then add the 2nd cpu port to the wan bridge ?
> 
> https://github.com/lunn/linux/tree/v4.1-rc4-net-next-multiple-cpu
> 
> You don't configure anything from userland. Which was actually a
> criticism. It is in device tree. But my solution is generic. Having
> one WAN port and four bridges LAN ports is a pure marketing
> requirement. The hardware will happily do two WAN ports and 3 LAN
> ports, for example. And the switch is happy to take traffic for the
> WAN port and a LAN port over the same CPU port, and keep the traffic
> separate. So we can have some form of load balancing. We are not
> limited to 1->1, 1->4, we can do 1->2, 1->3 to increase the overall
> performance. And to the user it is all transparent.
> 
> This PoC is for the old DSA binding. The new binding makes it easier
> to express this. Which is one of the reasons for the new binding.
> 
>   Andrew
> 

Hi Andrew,

spent some time looking at this and thinking about possible solutions.
my initial idea was to detect which cpu port to based on the cpu port
being included inside the bridge. however that wont allow us to control
ports using the tag outside of a bridge. i think that your approach is
the only sane one. we could add a sysfs interface later, allowing us to
change the default cpu port <-> mappings, but the device tree needs to
include some sane defaults. i'll use your patches as a base for a series.

John



Re: dsa: handling more than 1 cpu port

2016-12-14 Thread John Crispin


On 14/12/2016 12:00, Andrew Lunn wrote:
> On Wed, Dec 14, 2016 at 11:35:30AM +0100, John Crispin wrote:
>>
>>
>> On 14/12/2016 11:31, Andrew Lunn wrote:
>>> On Wed, Dec 14, 2016 at 11:01:54AM +0100, John Crispin wrote:
>>>> Hi Andrew,
>>>>
>>>> switches supported by qca8k have 2 gmacs that we can wire an external
>>>> mii interface to. Usually this is used to wire 2 of the SoCs MACs to the
>>>> switch. Thw switch itself is aware of one of the MACs being the cpu port
>>>> and expects this to be port/mac0. Using the other will break the
>>>> hardware offloading features.
>>>
>>> Just to be sure here. There is no way to use the second port connected
>>> to the CPU as a CPU port?
>>
>> both macs are considered cpu ports and both allow for the tag to be
>> injected. for HW NAT/routing/... offloading to work, the lan ports neet
>> to trunk via port0 and not port6 however.
> 
> Maybe you can do a restricted version of the generic solution. LAN
> ports are mapped to cpu port0. WAN port to cpu port 6?

hardcoding it is exactly what i want to avoid, same as using magic name
matching. the dts should describe the HW and not the usage dictated by
what is printed on the casing of the switch. as you mention below this
is marketing chatter. imho ports should have any name and we should be
able to bridge them as we feel happy and attach the bridges to any cpu
port that we want.

> 
>>> The Marvell chips do allow this. So i developed a proof of concept
>>> which had a mapping between cpu ports and slave ports. slave port X
>>> should you cpu port y for its traffic. This never got past proof of
>>> concept. 
>>>
>>> If this can be made to work for qca8k, i would prefer having this
>>> general concept, than specific hacks for pass through.
>>
>> oh cool, can you send those patches my way please ? how do you configure
>> this from userland ? does the cpu port get its on swdev which i just add
>> to my lan bridge and then add the 2nd cpu port to the wan bridge ?
> 
> https://github.com/lunn/linux/tree/v4.1-rc4-net-next-multiple-cpu
> 
> You don't configure anything from userland. Which was actually a
> criticism. It is in device tree. But my solution is generic. Having
> one WAN port and four bridges LAN ports is a pure marketing
> requirement. The hardware will happily do two WAN ports and 3 LAN
> ports, for example. And the switch is happy to take traffic for the
> WAN port and a LAN port over the same CPU port, and keep the traffic
> separate. So we can have some form of load balancing. We are not
> limited to 1->1, 1->4, we can do 1->2, 1->3 to increase the overall
> performance. And to the user it is all transparent.
> 
> This PoC is for the old DSA binding. The new binding makes it easier
> to express this. Which is one of the reasons for the new binding.
> 
>   Andrew
> 

i'll have a look at the patches. thanks !

John



Re: dsa: handling more than 1 cpu port

2016-12-14 Thread John Crispin


On 14/12/2016 11:31, Andrew Lunn wrote:
> On Wed, Dec 14, 2016 at 11:01:54AM +0100, John Crispin wrote:
>> Hi Andrew,
>>
>> switches supported by qca8k have 2 gmacs that we can wire an external
>> mii interface to. Usually this is used to wire 2 of the SoCs MACs to the
>> switch. Thw switch itself is aware of one of the MACs being the cpu port
>> and expects this to be port/mac0. Using the other will break the
>> hardware offloading features.
> 
> Just to be sure here. There is no way to use the second port connected
> to the CPU as a CPU port?

both macs are considered cpu ports and both allow for the tag to be
injected. for HW NAT/routing/... offloading to work, the lan ports neet
to trunk via port0 and not port6 however.

> 
> The Marvell chips do allow this. So i developed a proof of concept
> which had a mapping between cpu ports and slave ports. slave port X
> should you cpu port y for its traffic. This never got past proof of
> concept. 
> 
> If this can be made to work for qca8k, i would prefer having this
> general concept, than specific hacks for pass through.

oh cool, can you send those patches my way please ? how do you configure
this from userland ? does the cpu port get its on swdev which i just add
to my lan bridge and then add the 2nd cpu port to the wan bridge ?

John


dsa: handling more than 1 cpu port

2016-12-14 Thread John Crispin
Hi Andrew,

switches supported by qca8k have 2 gmacs that we can wire an external
mii interface to. Usually this is used to wire 2 of the SoCs MACs to the
switch. Thw switch itself is aware of one of the MACs being the cpu port
and expects this to be port/mac0. Using the other will break the
hardware offloading features. The original series from Matthieu added a
feature to configure the switch in a pass-through mode [1]. This
resulted in us having to define the pass-through inside the dts which
means that we loose userland configurability. Assume the setup as
follows ...

port0 - cpu port wired to SoCs MAC0
port1-4 - the lan ports
port5 - the wan port
port6 - wired to the SoCs MAC1

What i have done now is bring up one bridge for port1-4 and a second one
for port5-6. Once setup I can pass traffic on the SoCs MAC1 and it will
flow via port6 and egress on port5. So far so good, however due to the
way the port based vlans are setup and how the bridge_join/leave() logic
works, port5/6 will also fwd traffic to the cpu port. the driver has now
to tell that we are trunking traffic on eth1 via port6. also the MII
mode is not known to the driver. Adding some hackish register writes
will make this work nicely. My proposed way of fixing this cleanly in an
upstream friendly way would be as follows

1) add an extra dsa,ethernet property to the 2nd MII port

dsa@0 {
compatible = "qca,ar8xxx";

dsa,ethernet = <>;

[...]

switch@0 {
[...]

port@5 {
reg = <5>;
label = "wan";
phy-handle = <_port5>;
};

port@6 {
reg = <6>;
label = "gmac2";

dsa,ethernet = <>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};

2) fix up the port_bridge_join/leave() logic such that if a port is
present in the bridge that has a reference to a ethernet interface it
will remove all ports in the bridge from the port based vlan of the
actual cpu port.

3) in case of this switch we also need to fiddle with the bcast/mcast
flooding registers

would this be ok and would it be better to probe the extra dsa_ethernet
inside the subsystem or the driver ? i was considering to do add a
dsa_is_trunk_port() or similar to achieve this.

John




[1] https://patchwork.ozlabs.org/patch/477525/


Re: [PATCH] net: dsa: properly disconnect the slave PHYs

2016-10-18 Thread John Crispin


On 18/10/2016 15:24, Andrew Lunn wrote:
>> Hi Andrew
>>
>> i am testing on v4.4 which did not have a phy_disconnect() call. this
>> seems to have been fixed by cda5c15b so please ignore this patch
> 
> Hi John
> 
> All patches must be against net-next, or net if it is a fix. Anything
> else is wrong
> 
>  Andrew
> 

Hi Andrew,

i know. i was testing on v4.4 and then rebased the patch against
net-next without noticing that a similar patch had already been merged.

regardless, using the latest net-next tree, the oops is gone without
adding any patches.

John


Re: [PATCH] net: dsa: properly disconnect the slave PHYs

2016-10-18 Thread John Crispin


On 18/10/2016 14:29, Andrew Lunn wrote:
> On Tue, Oct 18, 2016 at 02:12:40PM +0200, John Crispin wrote:
>> The shutdown code only stopped the PHYs but does not diconnect them
>> properly. This could lead to null pointer deref related kernel oopses
>> during reboot. Fix this by calling phy_disconnect() after the PHYs are
>> stopped.
> 
> Humm, i don't follow this.
> 
> The phy is disconnected in dsa_slave_destroy(). Why is that not
> sufficient?
> 
> Also, after calling dsa_slave_close(), dsa_slave_open() can be
> called. But with your change, the phy has gone, so we are going to
> have trouble.
> 
>   Andrew
> 

Hi Andrew

i am testing on v4.4 which did not have a phy_disconnect() call. this
seems to have been fixed by cda5c15b so please ignore this patch

John

>>
>> Signed-off-by: John Crispin <j...@phrozen.org>
>> ---
>>  net/dsa/slave.c |4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
>> index 68714a5..725d9f7 100644
>> --- a/net/dsa/slave.c
>> +++ b/net/dsa/slave.c
>> @@ -154,8 +154,10 @@ static int dsa_slave_close(struct net_device *dev)
>>  struct net_device *master = p->parent->dst->master_netdev;
>>  struct dsa_switch *ds = p->parent;
>>  
>> -if (p->phy)
>> +if (p->phy) {
>>  phy_stop(p->phy);
>> +phy_disconnect(p->phy);
>> +}
>>  
>>  dev_mc_unsync(master, dev);
>>  dev_uc_unsync(master, dev);
>> -- 
>> 1.7.10.4
>>


[PATCH] net: dsa: properly disconnect the slave PHYs

2016-10-18 Thread John Crispin
The shutdown code only stopped the PHYs but does not diconnect them
properly. This could lead to null pointer deref related kernel oopses
during reboot. Fix this by calling phy_disconnect() after the PHYs are
stopped.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/dsa/slave.c |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 68714a5..725d9f7 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -154,8 +154,10 @@ static int dsa_slave_close(struct net_device *dev)
struct net_device *master = p->parent->dst->master_netdev;
struct dsa_switch *ds = p->parent;
 
-   if (p->phy)
+   if (p->phy) {
phy_stop(p->phy);
+   phy_disconnect(p->phy);
+   }
 
dev_mc_unsync(master, dev);
dev_uc_unsync(master, dev);
-- 
1.7.10.4



Re: [PATCH net-next 1/3] net: ethernet: mediatek: get the chip id by ETHDMASYS registers

2016-10-04 Thread John Crispin


On 04/10/2016 14:12, Nelson Chang wrote:
> Hi John,
> 
> Thanks for your review!
> I will modify that as below. Would you think it is okay?
> 
> static int mtk_get_chip_id(struct mtk_eth *eth, u32 *chip_id)
> {
>   u32 val[2], id[4];
> 
>   regmap_read(eth->ethsys, ETHSYS_CHIPID0_3, [0]);
>   regmap_read(eth->ethsys, ETHSYS_CHIPID4_7, [1]);
> 
>   id[3] = ((val[0] >> 16) & 0xff) - '0';
>   id[2] = ((val[0] >> 24) & 0xff) - '0';
>   id[1] = (val[1] & 0xff) - '0';
>   id[0] = ((val[1] >> 8) & 0xff) - '0';
> 
>   *chip_id = (id[3] * 1000) + (id[2] * 100) +
>  (id[1] * 10) + id[0];
> 
>   if (!(*chip_id)) {
>   dev_err(eth->dev, "failed to get chip id\n");
>   return -ENODEV;
>   }
> 
>   dev_info(eth->dev, "chip id = %d\n", *chip_id);
> 
>   return 0;
> }
> ...
> static int mtk_probe(struct platform_device *pdev)
> {
>   ...
>   err = mtk_get_chip_id(eth, >chip_id);
>   if (err)
>   return err;
>   ...
> }
> 
> 
> Nelson


Hi Nelson,

I think that looks nicer, thanks !

John

> 
> -Original Message-
> From: John Crispin [mailto:j...@phrozen.org] 
> Sent: Tuesday, October 04, 2016 3:17 AM
> To: Nelson Chang (張家祥); da...@davemloft.net
> Cc: n...@openwrt.org; netdev@vger.kernel.org;
> linux-media...@lists.infradead.org; nelsonch...@gmail.com
> Subject: Re: [PATCH net-next 1/3] net: ethernet: mediatek: get the chip
> id by ETHDMASYS registers
> 
> Hi Nelson,
> 
> comments inline
> 
> On 03/10/2016 09:18, Nelson Chang wrote:
>> The driver gets the chip id by ETHSYS_CHIPID0_3/ETHSYS_CHIPID4_7 
>> registers in mtk_probe().
>>
>> Signed-off-by: Nelson Chang <nelson.ch...@mediatek.com>
>> ---
>>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 27 
>> +++  
>> drivers/net/ethernet/mediatek/mtk_eth_soc.h |  5 +
>>  2 files changed, 32 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
>> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
>> index ad4ab97..a3e4ae6 100644
>> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
>> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
>> @@ -2323,6 +2323,27 @@ free_netdev:
>>  return err;
>>  }
>>  
>> +static u32 mtk_get_chip_id(struct mtk_eth *eth) {
>> +u32 val[2], id[4];
>> +u32 chip_id;
>> +
>> +regmap_read(eth->ethsys, ETHSYS_CHIPID0_3, [0]);
>> +regmap_read(eth->ethsys, ETHSYS_CHIPID4_7, [1]);
>> +
>> +id[3] = ((val[0] >> 16) & 0xff) - '0';
>> +id[2] = ((val[0] >> 24) & 0xff) - '0';
>> +id[1] = (val[1] & 0xff) - '0';
>> +id[0] = ((val[1] >> 8) & 0xff) - '0';
>> +
>> +chip_id = (id[3] * 1000) + (id[2] * 100) +
>> +  (id[1] * 10) + id[0];
>> +
>> +dev_info(eth->dev, "chip id = %d\n", chip_id);
> 
> the chip id is printed here
> 
>> +return chip_id;
>> +}
>> +
>>  static int mtk_probe(struct platform_device *pdev)  {
>>  struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 
>> 0); @@ -2388,6 +2409,12 @@ static int mtk_probe(struct platform_device
> *pdev)
>>  if (err)
>>  return err;
>>  
>> +eth->chip_id = mtk_get_chip_id(eth);
>> +if (!eth->chip_id) {
>> +dev_err(>dev, "failed to get chip id\n");
>> +return -ENODEV;
>> +}
>> +
> 
> and the error check happens here. maybe you could move the dev_err to
> the above function.
> 
>   John
> 
>>  for_each_child_of_node(pdev->dev.of_node, mac_np) {
>>  if (!of_device_is_compatible(mac_np,
>>   "mediatek,eth-mac"))
>> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
>> b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
>> index 3003195..a5b422b 100644
>> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
>> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
>> @@ -342,6 +342,10 @@
>>  #define GPIO_BIAS_CTRL  0xed0
>>  #define GPIO_DRV_SEL10  0xf00
>>  
>> +/* ethernet subsystem chip id register */
>> +#define ETHSYS_CHIPID0_30x0
>> +#define ETHSYS_CHIPID4_70x4
>> +
>>  /* ethernet subsystem config register */
>>  #define ETHSYS_SYSCFG0  0x14
>>  #define SYSCFG0_GE_MASK 0x3
>> @@ -534,6 +538,7 @@ struct mtk_eth {
>>  unsigned long   sysclk;
>>  struct regmap   *ethsys;
>>  struct regmap   *pctl;
>> +u32 chip_id;
>>  boolhwlro;
>>  atomic_tdma_refcnt;
>>  struct mtk_tx_ring  tx_ring;
>>
> 
> 


Re: [PATCH net-next 2/3] net: ethernet: mediatek: get hw lro capability by the chip id instead of by the dtsi

2016-10-03 Thread John Crispin
Hi Nelson,

comment inline

On 03/10/2016 09:18, Nelson Chang wrote:
> Because hw lro started to be supported from MT7623, the proper way to check if
> the feature is capable is to judge by the chip id instead of by the dtsi.
> 
> Signed-off-by: Nelson Chang 
> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 12 ++--
>  drivers/net/ethernet/mediatek/mtk_eth_soc.h |  1 +
>  2 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index a3e4ae6..3d16a0c 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -2344,6 +2344,14 @@ static u32 mtk_get_chip_id(struct mtk_eth *eth)
>   return chip_id;
>  }
>  
> +static bool mtk_is_hwlro_supported(struct mtk_eth *eth)
> +{
> + if (eth->chip_id == MT7623_ETH)
> + return true;
> + else
> + return false;
> +}
> +
>  static int mtk_probe(struct platform_device *pdev)
>  {
>   struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -2383,8 +2391,6 @@ static int mtk_probe(struct platform_device *pdev)
>   return PTR_ERR(eth->pctl);
>   }
>  
> - eth->hwlro = of_property_read_bool(pdev->dev.of_node, "mediatek,hwlro");
> -
>   for (i = 0; i < 3; i++) {
>   eth->irq[i] = platform_get_irq(pdev, i);
>   if (eth->irq[i] < 0) {
> @@ -2415,6 +2421,8 @@ static int mtk_probe(struct platform_device *pdev)
>   return -ENODEV;
>   }
>  
> + eth->hwlro = mtk_is_hwlro_supported(eth);
> +

do you plan to add more chips to the mtk_is_hwlro_supporte() function ?
if not a simple

eth->hwlro = (eth->chip_id == MT7623_ETH);

might be enough

John


>   for_each_child_of_node(pdev->dev.of_node, mac_np) {
>   if (!of_device_is_compatible(mac_np,
>"mediatek,eth-mac"))
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> index a5b422b..58738fd 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> @@ -345,6 +345,7 @@
>  /* ethernet subsystem chip id register */
>  #define ETHSYS_CHIPID0_3 0x0
>  #define ETHSYS_CHIPID4_7 0x4
> +#define MT7623_ETH   (7623)
>  
>  /* ethernet subsystem config register */
>  #define ETHSYS_SYSCFG0   0x14
> 


Re: [PATCH net-next 1/3] net: ethernet: mediatek: get the chip id by ETHDMASYS registers

2016-10-03 Thread John Crispin
Hi Nelson,

comments inline

On 03/10/2016 09:18, Nelson Chang wrote:
> The driver gets the chip id by ETHSYS_CHIPID0_3/ETHSYS_CHIPID4_7 registers
> in mtk_probe().
> 
> Signed-off-by: Nelson Chang 
> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 27 +++
>  drivers/net/ethernet/mediatek/mtk_eth_soc.h |  5 +
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index ad4ab97..a3e4ae6 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -2323,6 +2323,27 @@ free_netdev:
>   return err;
>  }
>  
> +static u32 mtk_get_chip_id(struct mtk_eth *eth)
> +{
> + u32 val[2], id[4];
> + u32 chip_id;
> +
> + regmap_read(eth->ethsys, ETHSYS_CHIPID0_3, [0]);
> + regmap_read(eth->ethsys, ETHSYS_CHIPID4_7, [1]);
> +
> + id[3] = ((val[0] >> 16) & 0xff) - '0';
> + id[2] = ((val[0] >> 24) & 0xff) - '0';
> + id[1] = (val[1] & 0xff) - '0';
> + id[0] = ((val[1] >> 8) & 0xff) - '0';
> +
> + chip_id = (id[3] * 1000) + (id[2] * 100) +
> +   (id[1] * 10) + id[0];
> +
> + dev_info(eth->dev, "chip id = %d\n", chip_id);

the chip id is printed here

> + return chip_id;
> +}
> +
>  static int mtk_probe(struct platform_device *pdev)
>  {
>   struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -2388,6 +2409,12 @@ static int mtk_probe(struct platform_device *pdev)
>   if (err)
>   return err;
>  
> + eth->chip_id = mtk_get_chip_id(eth);
> + if (!eth->chip_id) {
> + dev_err(>dev, "failed to get chip id\n");
> + return -ENODEV;
> + }
> +

and the error check happens here. maybe you could move the dev_err to
the above function.

John

>   for_each_child_of_node(pdev->dev.of_node, mac_np) {
>   if (!of_device_is_compatible(mac_np,
>"mediatek,eth-mac"))
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> index 3003195..a5b422b 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> @@ -342,6 +342,10 @@
>  #define GPIO_BIAS_CTRL   0xed0
>  #define GPIO_DRV_SEL10   0xf00
>  
> +/* ethernet subsystem chip id register */
> +#define ETHSYS_CHIPID0_3 0x0
> +#define ETHSYS_CHIPID4_7 0x4
> +
>  /* ethernet subsystem config register */
>  #define ETHSYS_SYSCFG0   0x14
>  #define SYSCFG0_GE_MASK  0x3
> @@ -534,6 +538,7 @@ struct mtk_eth {
>   unsigned long   sysclk;
>   struct regmap   *ethsys;
>   struct regmap   *pctl;
> + u32 chip_id;
>   boolhwlro;
>   atomic_tdma_refcnt;
>   struct mtk_tx_ring  tx_ring;
> 


[PATCH 2/4] net-next: dsa: make the set_addr() operation optional

2016-09-19 Thread John Crispin
Only 1 of the 3 drivers currently has a set_addr() operation. Make the
set_addr() callback optional to reduce the amount of empty stubs inside
the drivers.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/dsa/dsa.c  |8 +---
 net/dsa/dsa2.c |8 +---
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 66e31ac..a6902c1 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -378,9 +378,11 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, 
struct device *parent)
if (ret < 0)
goto out;
 
-   ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
-   if (ret < 0)
-   goto out;
+   if (ops->set_addr) {
+   ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
+   if (ret < 0)
+   goto out;
+   }
 
if (!ds->slave_mii_bus && ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(parent);
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index cffc19e..f8a7d9a 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -304,9 +304,11 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
if (err < 0)
return err;
 
-   err = ds->ops->set_addr(ds, dst->master_netdev->dev_addr);
-   if (err < 0)
-   return err;
+   if (ds->ops->set_addr) {
+   err = ds->ops->set_addr(ds, dst->master_netdev->dev_addr);
+   if (err < 0)
+   return err;
+   }
 
if (!ds->slave_mii_bus && ds->ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
-- 
1.7.10.4



[PATCH 3/4] net-next: dsa: b53: remove empty set_addr() stub

2016-09-19 Thread John Crispin
The set_addr() callback is now optional. Remove the empty stub that b53
has.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/b53/b53_common.c |6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 0afc2e5..1a492c0 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -764,11 +764,6 @@ static int b53_get_sset_count(struct dsa_switch *ds)
return b53_get_mib_size(dev);
 }
 
-static int b53_set_addr(struct dsa_switch *ds, u8 *addr)
-{
-   return 0;
-}
-
 static int b53_setup(struct dsa_switch *ds)
 {
struct b53_device *dev = ds->priv;
@@ -1466,7 +1461,6 @@ static enum dsa_tag_protocol b53_get_tag_protocol(struct 
dsa_switch *ds)
 static struct dsa_switch_ops b53_switch_ops = {
.get_tag_protocol   = b53_get_tag_protocol,
.setup  = b53_setup,
-   .set_addr   = b53_set_addr,
.get_strings= b53_get_strings,
.get_ethtool_stats  = b53_get_ethtool_stats,
.get_sset_count = b53_get_sset_count,
-- 
1.7.10.4



[PATCH 1/4] net-next: dsa: fix duplicate invocation of set_addr()

2016-09-19 Thread John Crispin
commit 83c0afaec7b730b ("net: dsa: Add new binding implementation")
has a duplicate invocation of the set_addr() operation callback. Remove one
of them.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 net/dsa/dsa2.c |4 
 1 file changed, 4 deletions(-)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 8278385..cffc19e 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -308,10 +308,6 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
if (err < 0)
return err;
 
-   err = ds->ops->set_addr(ds, dst->master_netdev->dev_addr);
-   if (err < 0)
-   return err;
-
if (!ds->slave_mii_bus && ds->ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
if (!ds->slave_mii_bus)
-- 
1.7.10.4



[PATCH 0/4] net-next: dsa: set_addr should be optional

2016-09-19 Thread John Crispin
The Marvell driver is the only one that actually sets the switches HW
address. All other drivers have an empty stub. fix this by making the
callback optional.

John Crispin (4):
  net-next: dsa: fix duplicate invocation of set_addr()
  net-next: dsa: make the set_addr() operation optional
  net-next: dsa: b53: remove empty set_addr() stub
  net-next: dsa: qca8k: remove empty set_addr() stub

 drivers/net/dsa/b53/b53_common.c |6 --
 drivers/net/dsa/qca8k.c  |8 
 net/dsa/dsa.c|8 +---
 net/dsa/dsa2.c   |   12 +---
 4 files changed, 10 insertions(+), 24 deletions(-)

-- 
1.7.10.4



[PATCH 4/4] net-next: dsa: qca8k: remove empty set_addr() stub

2016-09-19 Thread John Crispin
The set_addr() callback is now optional. Remove the empty stub that qca8k
has.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/qca8k.c |8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 7f3f178..4788a89 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -586,13 +586,6 @@ qca8k_setup(struct dsa_switch *ds)
 }
 
 static int
-qca8k_set_addr(struct dsa_switch *ds, u8 *addr)
-{
-   /* The subsystem always calls this function so add an empty stub */
-   return 0;
-}
-
-static int
 qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum)
 {
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
@@ -921,7 +914,6 @@ qca8k_get_tag_protocol(struct dsa_switch *ds)
 static struct dsa_switch_ops qca8k_switch_ops = {
.get_tag_protocol   = qca8k_get_tag_protocol,
.setup  = qca8k_setup,
-   .set_addr   = qca8k_set_addr,
.get_strings= qca8k_get_strings,
.phy_read   = qca8k_phy_read,
.phy_write  = qca8k_phy_write,
-- 
1.7.10.4



Re: MDB offloading of local ipv4 multicast groups

2016-09-16 Thread John Crispin


On 15/09/2016 22:42, Ido Schimmel wrote:
> On Thu, Sep 15, 2016 at 08:58:50PM +0200, John Crispin wrote:
>> Hi,
>>
>> While adding MDB support to the qca8k dsa driver I found that ipv4 mcast
>> groups don't always get propagated to the dsa driver. In my setup there
>> are 2 clients connected to the switch, both running a mdns client. The
>> .port_mdb_add() callback is properly called for 33:33:00:00:00:FB but
>> 01:00:5E:00:00:FB never got propagated to the dsa driver.
>>
>> The reason is that the call to ipv4_is_local_multicast() here [1] will
>> return true and the notifier is never called. Is this intentional or is
>> there something missing in the code ?
> 
> I believe this is based on RFC 4541:
> 
> "Packets with a destination IP (DIP) address in the 224.0.0.X range
> which are not IGMP must be forwarded on all ports."
> https://tools.ietf.org/html/rfc4541
> 
> But, we are missing the offloading of router ports, which is needed for
> the device to correctly flood unregistered multicast packets. That's
> also according to the mentioned RFC:
> 
> "If a switch receives an unregistered packet, it must forward that
> packet on all ports to which an IGMP router is attached."
> 
> Implemented at br_flood_multicast()
> 
> However, the marking is done per-port and not per-{port, VID}. We need
> that in case vlan filtering is enabled. I think Nik is working on that,
> but he can correct me if I'm wrong :). The switchdev bits can be added
> soon after.
> 

thanks for the explanation. i was not aware the the local groups should
always be flooded to all ports.

John


MDB offloading of local ipv4 multicast groups

2016-09-15 Thread John Crispin
Hi,

While adding MDB support to the qca8k dsa driver I found that ipv4 mcast
groups don't always get propagated to the dsa driver. In my setup there
are 2 clients connected to the switch, both running a mdns client. The
.port_mdb_add() callback is properly called for 33:33:00:00:00:FB but
01:00:5E:00:00:FB never got propagated to the dsa driver.

The reason is that the call to ipv4_is_local_multicast() here [1] will
return true and the notifier is never called. Is this intentional or is
there something missing in the code ?

John

[1]
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/bridge/br_multicast.c?id=refs/tags/v4.8-rc6#n737


[PATCH V3 1/3] Documentation: devicetree: add qca8k binding

2016-09-15 Thread John Crispin
Add device-tree binding for ar8xxx switch families.

Cc: devicet...@vger.kernel.org
Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* fixup example to include phy nodes and corresponding phandles
* add a note explaining why we need to phy nodes

Changes in V3
* add note stating that the cpu port is always 0

 .../devicetree/bindings/net/dsa/qca8k.txt  |   89 
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt 
b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
new file mode 100644
index 000..9c67ee4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -0,0 +1,89 @@
+* Qualcomm Atheros QCA8xxx switch family
+
+Required properties:
+
+- compatible: should be "qca,qca8337"
+- #size-cells: must be 0
+- #address-cells: must be 1
+
+Subnodes:
+
+The integrated switch subnode should be specified according to the binding
+described in dsa/dsa.txt. As the QCA8K switches do not have a N:N mapping of
+port and PHY id, each subnode describing a port needs to have a valid phandle
+referencing the internal PHY connected to it. The CPU port of this switch is
+always port 0.
+
+Example:
+
+
+{
+   phy_port1: phy@0 {
+   reg = <0>;
+   };
+
+   phy_port2: phy@1 {
+   reg = <1>;
+   };
+
+   phy_port3: phy@2 {
+   reg = <2>;
+   };
+
+   phy_port4: phy@3 {
+   reg = <3>;
+   };
+
+   phy_port5: phy@4 {
+   reg = <4>;
+   };
+
+   switch0@0 {
+   compatible = "qca,qca8337";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   reg = <0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   port@0 {
+   reg = <0>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "rgmii";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   phy-handle = <_port1>;
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   phy-handle = <_port2>;
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan3";
+   phy-handle = <_port3>;
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "lan4";
+   phy-handle = <_port4>;
+   };
+
+   port@5 {
+   reg = <5>;
+   label = "wan";
+   phy-handle = <_port5>;
+   };
+   };
+   };
+   };
-- 
1.7.10.4



[PATCH V3 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-15 Thread John Crispin
This patch contains initial support for the QCA8337 switch. It
will detect a QCA8337 switch, if present and declared in the DT.

Each port will be represented through a standalone net_device interface,
as for other DSA switches. CPU can communicate with any of the ports by
setting an IP@ on ethN interface. Most of the extra callbacks of the DSA
subsystem are already supported, such as bridge offloading, stp, fdb.

Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* add proper locking for the FDB table
* remove udelay when changing the page. neither datasheet nore SDK code
  requires a sleep
* add a cond_resched to the busy wait loop
* use nested locking when accessing the mdio bus
* remove the phy_to_port() wrappers
* remove mmd access function and use existing phy helpers
* fix a copy/paste bug breaking the eee callbacks
* use default vid 1 when fdb entries are added fro vid 0
* remove the phy id check and add a switch id check instead
* add error handling to the mdio read/write functions
* remove inline usage

Changes in V3
* remove qca8k_to_priv() helper
* turn fdb mutex into a generic register mutex
* verify that port0 is the cpu port
* flush MIB counters on startup
* more PHY->port
* implement fdb_prepare properly
* power ports up/down on PM event and shutdown

 drivers/net/dsa/Kconfig  |9 +
 drivers/net/dsa/Makefile |1 +
 drivers/net/dsa/qca8k.c  | 1060 ++
 drivers/net/dsa/qca8k.h  |  185 
 4 files changed, 1255 insertions(+)
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index de6d044..0659846 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -25,4 +25,13 @@ source "drivers/net/dsa/b53/Kconfig"
 
 source "drivers/net/dsa/mv88e6xxx/Kconfig"
 
+config NET_DSA_QCA8K
+   tristate "Qualcomm Atheros QCA8K Ethernet switch family support"
+   depends on NET_DSA
+   select NET_DSA_TAG_QCA
+   select REGMAP
+   ---help---
+ This enables support for the Qualcomm Atheros QCA8K Ethernet
+ switch chips.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index ca1e71b..8346e4f 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm_sf2.o
+obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
 
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
new file mode 100644
index 000..7f3f178
--- /dev/null
+++ b/drivers/net/dsa/qca8k.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (C) 2009 Felix Fietkau <n...@nbd.name>
+ * Copyright (C) 2011-2012 Gabor Juhos <juh...@openwrt.org>
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016 John Crispin <j...@phrozen.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "qca8k.h"
+
+#define MIB_DESC(_s, _o, _n)   \
+   {   \
+   .size = (_s),   \
+   .offset = (_o), \
+   .name = (_n),   \
+   }
+
+static const struct qca8k_mib_desc ar8327_mib[] = {
+   MIB_DESC(1, 0x00, "RxBroad"),
+   MIB_DESC(1, 0x04, "RxPause"),
+   MIB_DESC(1, 0x08, "RxMulti"),
+   MIB_DESC(1, 0x0c, "RxFcsErr"),
+   MIB_DESC(1, 0x10, "RxAlignErr"),
+   MIB_DESC(1, 0x14, "RxRunt"),
+   MIB_DESC(1, 0x18, "RxFragment"),
+   MIB_DESC(1, 0x1c, "Rx64Byte"),
+   MIB_DESC(1, 0x20, "Rx128Byte"),
+   MIB_DESC(1, 0x24, "Rx256Byte"),
+   MIB_DESC(1, 0x28, "Rx512Byte"),
+   MIB_DESC(1, 0x2c, "Rx1024Byte"),
+   MIB_DESC(1, 0x30, "Rx1518Byte"),
+   MIB_DESC(1, 0x34, "RxMaxByte"),
+   MIB_DESC(1, 0x38, "RxTooLong"),
+   MIB_DESC(2, 0x3c, "RxGoodByte"),
+   MIB_DESC(2, 0x44, "RxBadByte"),
+   MIB_DESC(1, 0x4c, "RxOverFlow"),
+   MIB_DESC(1, 0x50, "Filtered"),
+   MIB_DESC(1, 0x54, "TxBroad"),
+   MIB_DESC(1, 0x58, "TxPause"),
+   MIB_DESC(1, 0x5c, "TxMulti"),
+   MIB_D

[PATCH V3 0/3] net-next: dsa: add QCA8K support

2016-09-15 Thread John Crispin
This series is based on the AR8xxx series posted by Matthieu Olivari in may
2015. The following changes were made since then

* fixed the nitpicks from the previous review
* updated to latest API
* turned it into an mdio device
* added callbacks for fdb, bridge offloading, stp, eee, port status
* fixed several minor issues to the port setup and arp learning
* changed the namespacing as this driver to qca8k

The driver has so far only been tested on qca8337/N. It should work on other QCA
switches such as the qca8327 with minor changes.

John Crispin (3):
  Documentation: devicetree: add qca8k binding
  net-next: dsa: add Qualcomm tag RX/TX handler
  net-next: dsa: add new driver for qca8xxx family

 .../devicetree/bindings/net/dsa/qca8k.txt  |   89 ++
 drivers/net/dsa/Kconfig|9 +
 drivers/net/dsa/Makefile   |1 +
 drivers/net/dsa/qca8k.c| 1060 
 drivers/net/dsa/qca8k.h|  185 
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|3 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |2 +
 net/dsa/tag_qca.c  |  138 +++
 11 files changed, 1492 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h
 create mode 100644 net/dsa/tag_qca.c

-- 
1.7.10.4



[PATCH V3 2/3] net-next: dsa: add Qualcomm tag RX/TX handler

2016-09-15 Thread John Crispin
Add support for the 2-bytes Qualcomm tag that gigabit switches such as
the QCA8337/N might insert when receiving packets, or that we need
to insert while targeting specific switch ports. The tag is inserted
directly behind the ethernet header.

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* fix some comments
* remove dead code
* rename variable from phy->reg

 include/net/dsa.h  |1 +
 net/dsa/Kconfig|3 ++
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 ++
 net/dsa/dsa_priv.h |2 +
 net/dsa/tag_qca.c  |  138 
 6 files changed, 148 insertions(+)
 create mode 100644 net/dsa/tag_qca.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 24ee961..7fdd63e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -26,6 +26,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
+   DSA_TAG_PROTO_QCA,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index ff7736f..96e47c5 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -38,4 +38,7 @@ config NET_DSA_TAG_EDSA
 config NET_DSA_TAG_TRAILER
bool
 
+config NET_DSA_TAG_QCA
+   bool
+
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 8af4ded..a3380ed 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -7,3 +7,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
 dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
+dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d8d267e..66e31ac 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -54,6 +54,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
 #ifdef CONFIG_NET_DSA_TAG_BRCM
[DSA_TAG_PROTO_BRCM] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_QCA
+   [DSA_TAG_PROTO_QCA] = _netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 00077a9..6cfd738 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -81,5 +81,7 @@ extern const struct dsa_device_ops trailer_netdev_ops;
 /* tag_brcm.c */
 extern const struct dsa_device_ops brcm_netdev_ops;
 
+/* tag_qca.c */
+extern const struct dsa_device_ops qca_netdev_ops;
 
 #endif
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
new file mode 100644
index 000..0c90cac
--- /dev/null
+++ b/net/dsa/tag_qca.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include 
+#include "dsa_priv.h"
+
+#define QCA_HDR_LEN2
+#define QCA_HDR_VERSION0x2
+
+#define QCA_HDR_RECV_VERSION_MASK  GENMASK(15, 14)
+#define QCA_HDR_RECV_VERSION_S 14
+#define QCA_HDR_RECV_PRIORITY_MASK GENMASK(13, 11)
+#define QCA_HDR_RECV_PRIORITY_S11
+#define QCA_HDR_RECV_TYPE_MASK GENMASK(10, 6)
+#define QCA_HDR_RECV_TYPE_S6
+#define QCA_HDR_RECV_FRAME_IS_TAGGED   BIT(3)
+#define QCA_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+
+#define QCA_HDR_XMIT_VERSION_MASK  GENMASK(15, 14)
+#define QCA_HDR_XMIT_VERSION_S 14
+#define QCA_HDR_XMIT_PRIORITY_MASK GENMASK(13, 11)
+#define QCA_HDR_XMIT_PRIORITY_S11
+#define QCA_HDR_XMIT_CONTROL_MASK  GENMASK(10, 8)
+#define QCA_HDR_XMIT_CONTROL_S 8
+#define QCA_HDR_XMIT_FROM_CPU  BIT(7)
+#define QCA_HDR_XMIT_DP_BIT_MASK   GENMASK(6, 0)
+
+static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u16 *phdr, hdr;
+
+   dev->stats.tx_packets++;
+   dev->stats.tx_bytes += skb->len;
+
+   if (skb_cow_head(skb, 0) < 0)
+   goto out_free;
+
+   skb_push(skb, QCA_HDR_LEN);
+
+   memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN);
+   phdr = (u16 *)(skb->data + 2 * ETH_ALEN);
+
+   /* Set the version field, and set destination port information */
+   hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
+   QCA_HDR_XMIT_FROM_CPU |
+   BIT(p->port);
+
+   *phdr = htons(hdr);
+
+   return skb;
+
+out_free:
+   kfree_skb(skb);
+   return NULL;
+}
+
+stati

Re: [PATCH V2 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-14 Thread John Crispin


On 14/09/2016 12:39, John Crispin wrote:
> +static void
> +qca8k_fdb_add(struct dsa_switch *ds, int port,
> +   const struct switchdev_obj_port_fdb *fdb,
> +   struct switchdev_trans *trans)
> +{
> + struct qca8k_priv *priv = qca8k_to_priv(ds);
> + u16 port_mask = BIT(port);
> + u16 vid = fdb->vid;
> +
> + if (!vid)
> + vid = 1;
> +
> + qca8k_fdb_write(priv, vid, port_mask, fdb->addr,
> + QCA8K_ATU_STATUS_STATIC);
> +
> + qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
> +}
> +
> +static int
> +qca8k_fdb_del(struct dsa_switch *ds, int port,
> +   const struct switchdev_obj_port_fdb *fdb)
> +{
> + struct qca8k_priv *priv = qca8k_to_priv(ds);
> + u16 port_mask = BIT(port);
> +
> + qca8k_fdb_write(priv, fdb->vid, port_mask, fdb->addr, 0);
> +
> + return qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
> +}
> +

while adding MDB support i noticed that

1) the code above is still not properly locked
2) i can unify the FDB and MDB code

i will send a V3 with those 2 changes tomorrow.

John


[PATCH V2 2/3] net-next: dsa: add Qualcomm tag RX/TX handler

2016-09-14 Thread John Crispin
Add support for the 2-bytes Qualcomm tag that gigabit switches such as
the QCA8337/N might insert when receiving packets, or that we need
to insert while targeting specific switch ports. The tag is inserted
directly behind the ethernet header.

Signed-off-by: John Crispin <j...@phrozen.org>
---
* fix some comments
* remove dead code
* rename variable from phy->reg

 include/net/dsa.h  |1 +
 net/dsa/Kconfig|3 ++
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 ++
 net/dsa/dsa_priv.h |2 +
 net/dsa/tag_qca.c  |  138 
 6 files changed, 148 insertions(+)
 create mode 100644 net/dsa/tag_qca.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 24ee961..7fdd63e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -26,6 +26,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
+   DSA_TAG_PROTO_QCA,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index ff7736f..96e47c5 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -38,4 +38,7 @@ config NET_DSA_TAG_EDSA
 config NET_DSA_TAG_TRAILER
bool
 
+config NET_DSA_TAG_QCA
+   bool
+
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 8af4ded..a3380ed 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -7,3 +7,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
 dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
+dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d8d267e..66e31ac 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -54,6 +54,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
 #ifdef CONFIG_NET_DSA_TAG_BRCM
[DSA_TAG_PROTO_BRCM] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_QCA
+   [DSA_TAG_PROTO_QCA] = _netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 00077a9..6cfd738 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -81,5 +81,7 @@ extern const struct dsa_device_ops trailer_netdev_ops;
 /* tag_brcm.c */
 extern const struct dsa_device_ops brcm_netdev_ops;
 
+/* tag_qca.c */
+extern const struct dsa_device_ops qca_netdev_ops;
 
 #endif
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
new file mode 100644
index 000..0c90cac
--- /dev/null
+++ b/net/dsa/tag_qca.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include 
+#include "dsa_priv.h"
+
+#define QCA_HDR_LEN2
+#define QCA_HDR_VERSION0x2
+
+#define QCA_HDR_RECV_VERSION_MASK  GENMASK(15, 14)
+#define QCA_HDR_RECV_VERSION_S 14
+#define QCA_HDR_RECV_PRIORITY_MASK GENMASK(13, 11)
+#define QCA_HDR_RECV_PRIORITY_S11
+#define QCA_HDR_RECV_TYPE_MASK GENMASK(10, 6)
+#define QCA_HDR_RECV_TYPE_S6
+#define QCA_HDR_RECV_FRAME_IS_TAGGED   BIT(3)
+#define QCA_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+
+#define QCA_HDR_XMIT_VERSION_MASK  GENMASK(15, 14)
+#define QCA_HDR_XMIT_VERSION_S 14
+#define QCA_HDR_XMIT_PRIORITY_MASK GENMASK(13, 11)
+#define QCA_HDR_XMIT_PRIORITY_S11
+#define QCA_HDR_XMIT_CONTROL_MASK  GENMASK(10, 8)
+#define QCA_HDR_XMIT_CONTROL_S 8
+#define QCA_HDR_XMIT_FROM_CPU  BIT(7)
+#define QCA_HDR_XMIT_DP_BIT_MASK   GENMASK(6, 0)
+
+static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u16 *phdr, hdr;
+
+   dev->stats.tx_packets++;
+   dev->stats.tx_bytes += skb->len;
+
+   if (skb_cow_head(skb, 0) < 0)
+   goto out_free;
+
+   skb_push(skb, QCA_HDR_LEN);
+
+   memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN);
+   phdr = (u16 *)(skb->data + 2 * ETH_ALEN);
+
+   /* Set the version field, and set destination port information */
+   hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
+   QCA_HDR_XMIT_FROM_CPU |
+   BIT(p->port);
+
+   *phdr = htons(hdr);
+
+   return skb;
+
+out_free:
+   kfree_skb(skb);
+   return NULL;
+}
+
+static int qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt, struct net_device 

[PATCH V2 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-14 Thread John Crispin
This patch contains initial support for the QCA8337 switch. It
will detect a QCA8337 switch, if present and declared in the DT.

Each port will be represented through a standalone net_device interface,
as for other DSA switches. CPU can communicate with any of the ports by
setting an IP@ on ethN interface. Most of the extra callbacks of the DSA
subsystem are already supported, such as bridge offloading, stp, fdb.

Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* add proper locking for the FDB table
* remove udelay when changing the page. neither datasheet nore SDK code
  requires a sleep
* add a cond_resched to the busy wait loop
* use nested locking when accessing the mdio bus
* remove the phy_to_port() wrappers
* remove mmd access function and use existing phy helpers
* fix a copy/paste bug breaking the eee callbacks
* use default vid 1 when fdb entries are added fro vid 0
* remove the phy id check and add a switch id check instead
* add error handling to the mdio read/write functions
* remove inline usage

 drivers/net/dsa/Kconfig  |9 +
 drivers/net/dsa/Makefile |1 +
 drivers/net/dsa/qca8k.c  |  968 ++
 drivers/net/dsa/qca8k.h  |  180 +
 4 files changed, 1158 insertions(+)
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index de6d044..0659846 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -25,4 +25,13 @@ source "drivers/net/dsa/b53/Kconfig"
 
 source "drivers/net/dsa/mv88e6xxx/Kconfig"
 
+config NET_DSA_QCA8K
+   tristate "Qualcomm Atheros QCA8K Ethernet switch family support"
+   depends on NET_DSA
+   select NET_DSA_TAG_QCA
+   select REGMAP
+   ---help---
+ This enables support for the Qualcomm Atheros QCA8K Ethernet
+ switch chips.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index ca1e71b..8346e4f 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm_sf2.o
+obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
 
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
new file mode 100644
index 000..76a550f
--- /dev/null
+++ b/drivers/net/dsa/qca8k.c
@@ -0,0 +1,968 @@
+/*
+ * Copyright (C) 2009 Felix Fietkau <n...@nbd.name>
+ * Copyright (C) 2011-2012 Gabor Juhos <juh...@openwrt.org>
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016 John Crispin <j...@phrozen.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "qca8k.h"
+
+#define MIB_DESC(_s, _o, _n)   \
+   {   \
+   .size = (_s),   \
+   .offset = (_o), \
+   .name = (_n),   \
+   }
+
+static const struct qca8k_mib_desc ar8327_mib[] = {
+   MIB_DESC(1, 0x00, "RxBroad"),
+   MIB_DESC(1, 0x04, "RxPause"),
+   MIB_DESC(1, 0x08, "RxMulti"),
+   MIB_DESC(1, 0x0c, "RxFcsErr"),
+   MIB_DESC(1, 0x10, "RxAlignErr"),
+   MIB_DESC(1, 0x14, "RxRunt"),
+   MIB_DESC(1, 0x18, "RxFragment"),
+   MIB_DESC(1, 0x1c, "Rx64Byte"),
+   MIB_DESC(1, 0x20, "Rx128Byte"),
+   MIB_DESC(1, 0x24, "Rx256Byte"),
+   MIB_DESC(1, 0x28, "Rx512Byte"),
+   MIB_DESC(1, 0x2c, "Rx1024Byte"),
+   MIB_DESC(1, 0x30, "Rx1518Byte"),
+   MIB_DESC(1, 0x34, "RxMaxByte"),
+   MIB_DESC(1, 0x38, "RxTooLong"),
+   MIB_DESC(2, 0x3c, "RxGoodByte"),
+   MIB_DESC(2, 0x44, "RxBadByte"),
+   MIB_DESC(1, 0x4c, "RxOverFlow"),
+   MIB_DESC(1, 0x50, "Filtered"),
+   MIB_DESC(1, 0x54, "TxBroad"),
+   MIB_DESC(1, 0x58, "TxPause"),
+   MIB_DESC(1, 0x5c, "TxMulti"),
+   MIB_DESC(1, 0x60, "TxUnderRun"),
+   MIB_DESC(1, 0x64, "Tx64Byte"),
+   MIB_DESC(1, 0x68, "Tx128Byte"),
+   MIB_DESC(1, 0x6c, "Tx256Byte"),
+   MIB_DESC(1, 0x70, "Tx512Byte"),
+   MIB_DESC(1, 0x74, &q

[PATCH V2 1/3] Documentation: devicetree: add qca8k binding

2016-09-14 Thread John Crispin
Add device-tree binding for ar8xxx switch families.

Cc: devicet...@vger.kernel.org
Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* fixup ecample to include phy nodes and corresponding phandles
* add a note explaining why we need to phy nodes

 .../devicetree/bindings/net/dsa/qca8k.txt  |   88 
 1 file changed, 88 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt 
b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
new file mode 100644
index 000..2c1582a
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -0,0 +1,88 @@
+* Qualcomm Atheros QCA8xxx switch family
+
+Required properties:
+
+- compatible: should be "qca,qca8337"
+- #size-cells: must be 0
+- #address-cells: must be 1
+
+Subnodes:
+
+The integrated switch subnode should be specified according to the binding
+described in dsa/dsa.txt. As the QCA8K switches do not have a N:N mapping of
+port and PHY id, each subnode describing a port needs to have a valid phandle
+referencing the internal PHY connected to it.
+
+Example:
+
+
+{
+   phy_port1: phy@0 {
+   reg = <0>;
+   };
+
+   phy_port2: phy@1 {
+   reg = <1>;
+   };
+
+   phy_port3: phy@2 {
+   reg = <2>;
+   };
+
+   phy_port4: phy@3 {
+   reg = <3>;
+   };
+
+   phy_port5: phy@4 {
+   reg = <4>;
+   };
+
+   switch0@0 {
+   compatible = "qca,qca8337";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   reg = <0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   port@0 {
+   reg = <0>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "rgmii";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   phy-handle = <_port1>;
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   phy-handle = <_port2>;
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan3";
+   phy-handle = <_port3>;
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "lan4";
+   phy-handle = <_port4>;
+   };
+
+   port@5 {
+   reg = <5>;
+   label = "wan";
+   phy-handle = <_port5>;
+   };
+   };
+   };
+   };
-- 
1.7.10.4



[PATCH V2 0/3] net-next: dsa: add QCA8K support

2016-09-14 Thread John Crispin
This series is based on the AR8xxx series posted by Matthieu Olivari in may
2015. The following changes were made since then

* fixed the nitpicks from the previous review
* updated to latest API
* turned it into an mdio device
* added callbacks for fdb, bridge offloading, stp, eee, port status
* fixed several minor issues to the port setup and arp learning
* changed the namespacing as this driver to qca8k

The driver has so far only been tested on qca8337/N. It should work on other QCA
switches such as the qca8327 with minor changes.

John Crispin (3):
  Documentation: devicetree: add qca8k binding
  net-next: dsa: add Qualcomm tag RX/TX handler
  net-next: dsa: add new driver for qca8xxx family

 .../devicetree/bindings/net/dsa/qca8k.txt  |   88 ++
 drivers/net/dsa/Kconfig|9 +
 drivers/net/dsa/Makefile   |1 +
 drivers/net/dsa/qca8k.c|  968 
 drivers/net/dsa/qca8k.h|  180 
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|3 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |2 +
 net/dsa/tag_qca.c  |  138 +++
 11 files changed, 1394 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h
 create mode 100644 net/dsa/tag_qca.c

-- 
1.7.10.4



Re: [PATCH 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-13 Thread John Crispin


On 13/09/2016 21:07, Andrew Lunn wrote:
>> Since the former alternative is prefered, we may want to remove the
>> latter soon from DSA. If this phy_port_map is needed for that case, it'd
>> be preferable not to add it.
> 
> O.K, so maybe we should solve it the device tree way:
> 
> 
> {
>   phy_port1: phy@0 {
>   reg = <0>;
>   };
> 
>   phy_port2: phy@1 {
>   reg = <1>;
>   };
> 
>   phy_port3: phy@2 {
>   reg = <2>;
>   };
> 
>   phy_port4: phy@3 {
>   reg = <3>;
>   };
> 
>   phy_port5: phy@4 {
>   reg = <4>;
>   };
> 
>   switch@0 {
>compatible = "qca,qca8337";
> 
>#address-cells = <1>;
>#size-cells = <0>;
>reg = <30>;
> 
>ports {
>port@11 {
>reg = <11>;
>label = "cpu";
>ethernet = <>;
>phy-mode = "rgmii";
>};
> 
>port@1 {
>reg = <1>;
>label = "lan1";
>  phy-handle = <_port1>;
>};
> 
>port@2 {
>reg = <2>;
>label = "lan2";
>  phy-handle = <_port2>;
>};
> 
>port@3 {
>reg = <3>;
>label = "lan3";
>  phy-handle = <_port3>;
>};
> 
>port@4 {
>reg = <4>;
>label = "lan4";
>  phy-handle = <_port4>;
>};
>};
>};
>};
> 
> and remove the phy_read() and phy_write() functions.
> 
> 
>Andrew
> 

Hi Andrew

ok, will give it a spin in the morning and add a note to the binding doc
explaining this. thanks for taking the time !

John


Re: [PATCH 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-13 Thread John Crispin


On 13/09/2016 19:09, Florian Fainelli wrote:
> On 09/13/2016 08:59 AM, Andrew Lunn wrote:
>>> Hi Andrew,
>>>
>>> this function does indeed duplicate the functionality of
>>> phy_ethtool_get_eee() with the small difference, that e->eee_active is
>>> also set which phy_ethtool_get_eee() does not set.
>>>
>>> dsa_slave_get_eee() will call phy_ethtool_get_eee() right after the
>>> get_eee() op has been called. would it be ok to move the code setting
>>> eee_active to  phy_ethtool_get_eee().
> 
> Humm, AFAIR, the reason why eee_active is set outside of
> phy_ethtool_set_eee() is because this is a MAC + PHY thing, both need to
> agree and support that, and so while the PHY may be configured to have
> EEE advertised and enabled, you also need to take care of the MAC
> portion and enable EEE in there as well. Is not there such a thing for
> the qca8k switch where the PHY needs to be configured through the
> standard phylib calls, but the switch's transmitter/receiver also needs
> to have EEE enabled?
>

Hi Florian,

the switch needs to enable the eee on a per mac absis, but there is no
way to tell if the autonegotiate worked and eee is enabled without
reading the phys registers.

setting the eee_active inside phy_ethtool_get_eee() would break those
dsa drivers that have a register telling if AN worked. if it is ok i
will just call phy_ethtool_get_eee() inside get_eee().

John


Re: [PATCH V3] net-next: dsa: add FIB support

2016-09-13 Thread John Crispin


On 13/09/2016 18:21, Vivien Didelot wrote:
> Hi John,
> 
> John Crispin <j...@phrozen.org> writes:
> 
>> @@ -237,6 +237,7 @@ struct switchdev_obj;
>>  struct switchdev_obj_port_fdb;
>>  struct switchdev_obj_port_mdb;
>>  struct switchdev_obj_port_vlan;
>> +struct switchdev_obj_ipv4_fib;
> 
> Can you keep it ordered please (put obj_ipv4 above port_fdb).
> 
>>  
>>  struct dsa_switch_ops {
>>  struct list_headlist;
>> @@ -386,6 +387,18 @@ struct dsa_switch_ops {
>>  int (*port_mdb_dump)(struct dsa_switch *ds, int port,
>>   struct switchdev_obj_port_mdb *mdb,
>>   int (*cb)(struct switchdev_obj *obj));
>> +
>> +/*
>> + * IPV4 routing
>> + */
>> +int (*ipv4_fib_prepare)(struct dsa_switch *ds, int port,
>> +const struct switchdev_obj_ipv4_fib *fib4,
>> +struct switchdev_trans *trans);
>> +int (*ipv4_fib_add)(struct dsa_switch *ds, int port,
>> +const struct switchdev_obj_ipv4_fib *fib4,
>> +struct switchdev_trans *trans);
> 
> DSA *_add ops should return void, since no error is supposed to occure in
> the commit phase.
> 
> If they are port-based operations, please prefix them with "port_",
> otherwise, the int port parameter is not necessary.
> 
>> +int (*ipv4_fib_del)(struct dsa_switch *ds, int port,
>> +const struct switchdev_obj_ipv4_fib *fib4);
>>  };
>>  
>>  void register_switch_driver(struct dsa_switch_ops *type);
>> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
>> index 9ecbe78..c974ac0 100644
>> --- a/net/dsa/slave.c
>> +++ b/net/dsa/slave.c
>> @@ -334,6 +334,38 @@ static int dsa_slave_port_mdb_dump(struct net_device 
>> *dev,
>>  return -EOPNOTSUPP;
>>  }
>>  
>> +static int dsa_slave_ipv4_fib_add(struct net_device *dev,
>> +  const struct switchdev_obj_ipv4_fib *fib4,
>> +  struct switchdev_trans *trans)
>> +{
>> +struct dsa_slave_priv *p = netdev_priv(dev);
>> +struct dsa_switch *ds = p->parent;
>> +int ret;
>> +
>> +if (!ds->ops->ipv4_fib_prepare || !ds->ops->ipv4_fib_add)
>> +return -EOPNOTSUPP;
>> +
>> +if (switchdev_trans_ph_prepare(trans))
>> +ret = ds->ops->ipv4_fib_prepare(ds, p->port, fib4, trans);
>> +else
>> +ret = ds->ops->ipv4_fib_add(ds, p->port, fib4, trans);
>> +
>> +return ret;
>> +}
> 
> Please see dsa_slave_port_vlan_add for a better logic with the prepare
> phase and void add routine.
> 
>> +
>> +static int dsa_slave_ipv4_fib_del(struct net_device *dev,
>> +  const struct switchdev_obj_ipv4_fib *fib4)
>> +{
>> +struct dsa_slave_priv *p = netdev_priv(dev);
>> +struct dsa_switch *ds = p->parent;
>> +int ret = -EOPNOTSUPP;
>> +
>> +if (ds->ops->ipv4_fib_del)
>> +ret = ds->ops->ipv4_fib_del(ds, p->port, fib4);
>> +
>> +return ret;
>> +}
> 
> Just curious, isn't there a dump operation for SWITCHDEV_OBJ_ID_IPV4_FIB?
> 
>> +
>>  static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int 
>> cmd)
>>  {
>>  struct dsa_slave_priv *p = netdev_priv(dev);
>> @@ -465,6 +497,11 @@ static int dsa_slave_port_obj_add(struct net_device 
>> *dev,
>>SWITCHDEV_OBJ_PORT_VLAN(obj),
>>trans);
>>  break;
>> +case SWITCHDEV_OBJ_ID_IPV4_FIB:
>> +err = dsa_slave_ipv4_fib_add(dev,
>> + SWITCHDEV_OBJ_IPV4_FIB(obj),
>> + trans);
>> +break;
>>  default:
>>  err = -EOPNOTSUPP;
>>  break;
>> @@ -490,6 +527,10 @@ static int dsa_slave_port_obj_del(struct net_device 
>> *dev,
>>  err = dsa_slave_port_vlan_del(dev,
>>SWITCHDEV_OBJ_PORT_VLAN(obj));
>>  break;
>> +case SWITCHDEV_OBJ_ID_IPV4_FIB:
>> +err = dsa_slave_ipv4_fib_del(dev,
>> + SWITCHDEV_OBJ_IPV4_FIB(obj));
>> +break;
>>  default:
>>  err = -EOPNOTSUPP;
>>  break;
> 
> Please keep the SWITCHDEV_OBJ_ID_IPV4_FIB case ordered with other cases
> as well.
> 
> I'm adding Jiri's in the loop, since he has started a thread on FIB
> notifications a few days ago, his feedback might be interesting. If I'm
> not mistaken, there is a plan to factorize FID routines (not sure).
> 
> Thanks,
> 
> Vivien

Hi Vivien,

i sent an email to Jiri earlier today and he asked me to drop this until
his notification series got merged.

John

> 


Re: [PATCH 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-13 Thread John Crispin


On 13/09/2016 03:23, Andrew Lunn wrote:
> So lets see if i have this right.
> 
> Port 0 has no internal phy.
> Port 1 has an internal PHY at MDIO address 0.
> Port 2 has an internal PHY at MDIO address 1.
> ...
> Port 5 has an internal PHY ad MDIO address 4.
> Port 6 has no internal PHY.

Hi Andrew

correct. port 0 is the cpu port. I initially thought that port6 can also
be used as te cpu port but there are various places in the datasheet
stating that the cpu port is 0. in some of the reference designs, port6
is wired to a 2nd gmac of the cpu and in those cases port 6 is then
hardwired to port 5 of the switch and called wan. right now the driver
does not support this feature. i have changed the code to always assume
that port is the cpu port and will send a patch later to allow the
port5/6 wan port setup once the series got accepted.

> 
> This is why you have funky port numbers, and phy_to_port.

this is legacy code from the series Matthieu posted. i agree though that
its a bit dirty. Sergey already told me that the devicetree is also bad
because of this as the unit address of the device tree node and reg
property are not aligned.

> 
> I think it would be a lot cleaner to handle this in qca8k_phy_read()
> and qca8k_phy_write(). 

ok, i will simply substract 1 from the phy_addr inside the mdio
callbacks. this would make the code more readable and make the DT
binding compliant with the ePAPR spec.

> 
> Also, the comment it a bit misleading. You are probing the PHY ID, not
> the switch ID. At least for the Marvell switches, different switches
> can have the same embedded PHY. It would be annoying to find there is
> another incompatible switch with the same PHY ID.

there is only an 8bit field inside the MASK_CTRL register (0x000) which
is 0x13. I've sent an email to QCA asking if this a unique identifier.

> Is the embedded PHY compatible with the at803x driver?

I've sent an email to QCA asking about this

John


Re: [PATCH 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-13 Thread John Crispin


On 13/09/2016 02:40, Andrew Lunn wrote:
>> > +static int
>> > +qca8k_get_eee(struct dsa_switch *ds, int port,
>> > +struct ethtool_eee *e)
>> > +{
>> > +  struct qca8k_priv *priv = qca8k_to_priv(ds);
>> > +  struct ethtool_eee *p = >port_sts[qca8k_phy_to_port(port)].eee;
>> > +  u32 lp, adv, supported;
>> > +  u16 val;
>> > +
>> > +  /* The switch has no way to tell the result of the AN so we need to
>> > +   * read the result directly from the PHYs MMD registers
>> > +   */
>> > +  val = qca8k_phy_mmd_read(priv, port, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
>> > +  supported = mmd_eee_cap_to_ethtool_sup_t(val);
>> > +
>> > +  val = qca8k_phy_mmd_read(priv, port, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
>> > +  adv = mmd_eee_adv_to_ethtool_adv_t(val);
>> > +
>> > +  val = qca8k_phy_mmd_read(priv, port, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
>> > +  lp = mmd_eee_adv_to_ethtool_adv_t(val);
>> > +
>> > +  e->eee_enabled = p->eee_enabled;
>> > +  e->eee_active = !!(supported & adv & lp);
>> > +
>> > +  return 0;
>> > +}
> Couldn't you just call phy_ethtool_get_eee(phydev)? Then you don't
> need qca8k_phy_mmd_read()?

Hi Andrew,

this function does indeed duplicate the functionality of
phy_ethtool_get_eee() with the small difference, that e->eee_active is
also set which phy_ethtool_get_eee() does not set.

dsa_slave_get_eee() will call phy_ethtool_get_eee() right after the
get_eee() op has been called. would it be ok to move the code setting
eee_active to  phy_ethtool_get_eee(). if thats possible then we could
just have a stub inside the dsa driver with a note saying that the dsa
layer will do the magic for us.

John


[PATCH V3] net-next: dsa: add FIB support

2016-09-13 Thread John Crispin
Add SWITCHDEV_OBJ_ID_IPV4_FIB support to the DSA layer.

Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* rebase on latest net-next to fix compile errors

Changes in V3
* fix subject prefix. this needs to go into the next tree

 Documentation/networking/dsa/dsa.txt |   18 +++
 include/net/dsa.h|   13 +++
 net/dsa/slave.c  |   41 ++
 3 files changed, 72 insertions(+)

diff --git a/Documentation/networking/dsa/dsa.txt 
b/Documentation/networking/dsa/dsa.txt
index 6d6c07c..6cd5831 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -607,6 +607,24 @@ of DSA, would be the its port-based VLAN, used by the 
associated bridge device.
   function that the driver has to call for each MAC address known to be behind
   the given port. A switchdev object is used to carry the VID and MDB info.
 
+Route offloading
+
+
+- ipv4_fib_prepare: routing layer function invoked to prepare the installation
+  of an ipv4 route into the switches routing database. If the operation is not
+  supported this function should return -EOPNOTSUPP. No hardware setup must be
+  done in this function. See ipv4_fib_add for this and details.
+
+- ipv4_fib_add: routing layer function invoked when a new ipv4 route should be
+  installed into the routing database of the switch, it should be programmed
+  with the route for the specified VLAN ID of the device that the route applies
+  to.
+
+- ipv4_fib_del: routing layer function invoked when an ipv4 route should be
+  removed from the routing database, the switch hardware should be programmed
+  to delete the specified MAC address of the nexthop from the specified VLAN ID
+  if it was mapped into the forwarding database.
+
 TODO
 
 
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7556646..7fdd63e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -237,6 +237,7 @@ struct switchdev_obj;
 struct switchdev_obj_port_fdb;
 struct switchdev_obj_port_mdb;
 struct switchdev_obj_port_vlan;
+struct switchdev_obj_ipv4_fib;
 
 struct dsa_switch_ops {
struct list_headlist;
@@ -386,6 +387,18 @@ struct dsa_switch_ops {
int (*port_mdb_dump)(struct dsa_switch *ds, int port,
 struct switchdev_obj_port_mdb *mdb,
 int (*cb)(struct switchdev_obj *obj));
+
+   /*
+* IPV4 routing
+*/
+   int (*ipv4_fib_prepare)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4,
+   struct switchdev_trans *trans);
+   int (*ipv4_fib_add)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4,
+   struct switchdev_trans *trans);
+   int (*ipv4_fib_del)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4);
 };
 
 void register_switch_driver(struct dsa_switch_ops *type);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 9ecbe78..c974ac0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -334,6 +334,38 @@ static int dsa_slave_port_mdb_dump(struct net_device *dev,
return -EOPNOTSUPP;
 }
 
+static int dsa_slave_ipv4_fib_add(struct net_device *dev,
+ const struct switchdev_obj_ipv4_fib *fib4,
+ struct switchdev_trans *trans)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->parent;
+   int ret;
+
+   if (!ds->ops->ipv4_fib_prepare || !ds->ops->ipv4_fib_add)
+   return -EOPNOTSUPP;
+
+   if (switchdev_trans_ph_prepare(trans))
+   ret = ds->ops->ipv4_fib_prepare(ds, p->port, fib4, trans);
+   else
+   ret = ds->ops->ipv4_fib_add(ds, p->port, fib4, trans);
+
+   return ret;
+}
+
+static int dsa_slave_ipv4_fib_del(struct net_device *dev,
+ const struct switchdev_obj_ipv4_fib *fib4)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->parent;
+   int ret = -EOPNOTSUPP;
+
+   if (ds->ops->ipv4_fib_del)
+   ret = ds->ops->ipv4_fib_del(ds, p->port, fib4);
+
+   return ret;
+}
+
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -465,6 +497,11 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
  SWITCHDEV_OBJ_PORT_VLAN(obj),
  trans);
break;
+   case SWITCHDEV_OBJ_ID_IPV4_FIB:
+   err = dsa_slave_ipv4_fib_add(dev,
+ 

[PATCH V2] net: dsa: add FIB support

2016-09-13 Thread John Crispin
Add SWITCHDEV_OBJ_ID_IPV4_FIB support to the DSA layer.

Signed-off-by: John Crispin <j...@phrozen.org>
---
Changes in V2
* rebase on latest net-next to fix compile errors

 Documentation/networking/dsa/dsa.txt |   18 +++
 include/net/dsa.h|   13 +++
 net/dsa/slave.c  |   41 ++
 3 files changed, 72 insertions(+)

diff --git a/Documentation/networking/dsa/dsa.txt 
b/Documentation/networking/dsa/dsa.txt
index 6d6c07c..6cd5831 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -607,6 +607,24 @@ of DSA, would be the its port-based VLAN, used by the 
associated bridge device.
   function that the driver has to call for each MAC address known to be behind
   the given port. A switchdev object is used to carry the VID and MDB info.
 
+Route offloading
+
+
+- ipv4_fib_prepare: routing layer function invoked to prepare the installation
+  of an ipv4 route into the switches routing database. If the operation is not
+  supported this function should return -EOPNOTSUPP. No hardware setup must be
+  done in this function. See ipv4_fib_add for this and details.
+
+- ipv4_fib_add: routing layer function invoked when a new ipv4 route should be
+  installed into the routing database of the switch, it should be programmed
+  with the route for the specified VLAN ID of the device that the route applies
+  to.
+
+- ipv4_fib_del: routing layer function invoked when an ipv4 route should be
+  removed from the routing database, the switch hardware should be programmed
+  to delete the specified MAC address of the nexthop from the specified VLAN ID
+  if it was mapped into the forwarding database.
+
 TODO
 
 
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7556646..7fdd63e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -237,6 +237,7 @@ struct switchdev_obj;
 struct switchdev_obj_port_fdb;
 struct switchdev_obj_port_mdb;
 struct switchdev_obj_port_vlan;
+struct switchdev_obj_ipv4_fib;
 
 struct dsa_switch_ops {
struct list_headlist;
@@ -386,6 +387,18 @@ struct dsa_switch_ops {
int (*port_mdb_dump)(struct dsa_switch *ds, int port,
 struct switchdev_obj_port_mdb *mdb,
 int (*cb)(struct switchdev_obj *obj));
+
+   /*
+* IPV4 routing
+*/
+   int (*ipv4_fib_prepare)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4,
+   struct switchdev_trans *trans);
+   int (*ipv4_fib_add)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4,
+   struct switchdev_trans *trans);
+   int (*ipv4_fib_del)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4);
 };
 
 void register_switch_driver(struct dsa_switch_ops *type);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 9ecbe78..c974ac0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -334,6 +334,38 @@ static int dsa_slave_port_mdb_dump(struct net_device *dev,
return -EOPNOTSUPP;
 }
 
+static int dsa_slave_ipv4_fib_add(struct net_device *dev,
+ const struct switchdev_obj_ipv4_fib *fib4,
+ struct switchdev_trans *trans)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->parent;
+   int ret;
+
+   if (!ds->ops->ipv4_fib_prepare || !ds->ops->ipv4_fib_add)
+   return -EOPNOTSUPP;
+
+   if (switchdev_trans_ph_prepare(trans))
+   ret = ds->ops->ipv4_fib_prepare(ds, p->port, fib4, trans);
+   else
+   ret = ds->ops->ipv4_fib_add(ds, p->port, fib4, trans);
+
+   return ret;
+}
+
+static int dsa_slave_ipv4_fib_del(struct net_device *dev,
+ const struct switchdev_obj_ipv4_fib *fib4)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->parent;
+   int ret = -EOPNOTSUPP;
+
+   if (ds->ops->ipv4_fib_del)
+   ret = ds->ops->ipv4_fib_del(ds, p->port, fib4);
+
+   return ret;
+}
+
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -465,6 +497,11 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
  SWITCHDEV_OBJ_PORT_VLAN(obj),
  trans);
break;
+   case SWITCHDEV_OBJ_ID_IPV4_FIB:
+   err = dsa_slave_ipv4_fib_add(dev,
+SWITCHDEV_OBJ_IPV4_FIB(obj),
+trans);
+ 

Re: [PATCH] net: dsa: add FIB support

2016-09-12 Thread John Crispin


On 12/09/2016 16:00, Andrew Lunn wrote:
> Hi John
> 
>> +if (!ds->drv->ipv4_fib_prepare || !ds->drv->ipv4_fib_add)
> 
> drv recently got renamed to ops, which is what 0-day is complaining
> about.
> 
>   Andrew
> 

i based this on a net-next from 5-6 days ago, will rebase/resend tomorrow.

John


[PATCH] net: dsa: add FIB support

2016-09-12 Thread John Crispin
Add SWITCHDEV_OBJ_ID_IPV4_FIB support to the DSA layer.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 Documentation/networking/dsa/dsa.txt |   18 +++
 include/net/dsa.h|   13 +++
 net/dsa/slave.c  |   41 ++
 3 files changed, 72 insertions(+)

diff --git a/Documentation/networking/dsa/dsa.txt 
b/Documentation/networking/dsa/dsa.txt
index 6d6c07c..6cd5831 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -607,6 +607,24 @@ of DSA, would be the its port-based VLAN, used by the 
associated bridge device.
   function that the driver has to call for each MAC address known to be behind
   the given port. A switchdev object is used to carry the VID and MDB info.
 
+Route offloading
+
+
+- ipv4_fib_prepare: routing layer function invoked to prepare the installation
+  of an ipv4 route into the switches routing database. If the operation is not
+  supported this function should return -EOPNOTSUPP. No hardware setup must be
+  done in this function. See ipv4_fib_add for this and details.
+
+- ipv4_fib_add: routing layer function invoked when a new ipv4 route should be
+  installed into the routing database of the switch, it should be programmed
+  with the route for the specified VLAN ID of the device that the route applies
+  to.
+
+- ipv4_fib_del: routing layer function invoked when an ipv4 route should be
+  removed from the routing database, the switch hardware should be programmed
+  to delete the specified MAC address of the nexthop from the specified VLAN ID
+  if it was mapped into the forwarding database.
+
 TODO
 
 
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7556646..7fdd63e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -237,6 +237,7 @@ struct switchdev_obj;
 struct switchdev_obj_port_fdb;
 struct switchdev_obj_port_mdb;
 struct switchdev_obj_port_vlan;
+struct switchdev_obj_ipv4_fib;
 
 struct dsa_switch_ops {
struct list_headlist;
@@ -386,6 +387,18 @@ struct dsa_switch_ops {
int (*port_mdb_dump)(struct dsa_switch *ds, int port,
 struct switchdev_obj_port_mdb *mdb,
 int (*cb)(struct switchdev_obj *obj));
+
+   /*
+* IPV4 routing
+*/
+   int (*ipv4_fib_prepare)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4,
+   struct switchdev_trans *trans);
+   int (*ipv4_fib_add)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4,
+   struct switchdev_trans *trans);
+   int (*ipv4_fib_del)(struct dsa_switch *ds, int port,
+   const struct switchdev_obj_ipv4_fib *fib4);
 };
 
 void register_switch_driver(struct dsa_switch_ops *type);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 9ecbe78..9e6ceb2 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -334,6 +334,38 @@ static int dsa_slave_port_mdb_dump(struct net_device *dev,
return -EOPNOTSUPP;
 }
 
+static int dsa_slave_ipv4_fib_add(struct net_device *dev,
+ const struct switchdev_obj_ipv4_fib *fib4,
+ struct switchdev_trans *trans)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->parent;
+   int ret;
+
+   if (!ds->drv->ipv4_fib_prepare || !ds->drv->ipv4_fib_add)
+   return -EOPNOTSUPP;
+
+   if (switchdev_trans_ph_prepare(trans))
+   ret = ds->drv->ipv4_fib_prepare(ds, p->port, fib4, trans);
+   else
+   ret = ds->drv->ipv4_fib_add(ds, p->port, fib4, trans);
+
+   return ret;
+}
+
+static int dsa_slave_ipv4_fib_del(struct net_device *dev,
+ const struct switchdev_obj_ipv4_fib *fib4)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->parent;
+   int ret = -EOPNOTSUPP;
+
+   if (ds->drv->ipv4_fib_del)
+   ret = ds->drv->ipv4_fib_del(ds, p->port, fib4);
+
+   return ret;
+}
+
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -465,6 +497,11 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
  SWITCHDEV_OBJ_PORT_VLAN(obj),
  trans);
break;
+   case SWITCHDEV_OBJ_ID_IPV4_FIB:
+   err = dsa_slave_ipv4_fib_add(dev,
+SWITCHDEV_OBJ_IPV4_FIB(obj),
+trans);
+   break;
default:
err = -EOPNOTSUP

[PATCH 3/3] net-next: dsa: add new driver for qca8xxx family

2016-09-12 Thread John Crispin
This patch contains initial support for the QCA8337 switch. It
will detect a QCA8337 switch, if present and declared in the DT.

Each port will be represented through a standalone net_device interface,
as for other DSA switches. CPU can communicate with any of the ports by
setting an IP@ on ethN interface. Most of the extra callbacks of the DSA
subsystem are already supported, such as bridge offloading, stp, fdb.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 drivers/net/dsa/Kconfig  |9 +
 drivers/net/dsa/Makefile |1 +
 drivers/net/dsa/qca8k.c  |  969 ++
 drivers/net/dsa/qca8k.h  |  201 ++
 4 files changed, 1180 insertions(+)
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index de6d044..0659846 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -25,4 +25,13 @@ source "drivers/net/dsa/b53/Kconfig"
 
 source "drivers/net/dsa/mv88e6xxx/Kconfig"
 
+config NET_DSA_QCA8K
+   tristate "Qualcomm Atheros QCA8K Ethernet switch family support"
+   depends on NET_DSA
+   select NET_DSA_TAG_QCA
+   select REGMAP
+   ---help---
+ This enables support for the Qualcomm Atheros QCA8K Ethernet
+ switch chips.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index ca1e71b..8346e4f 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm_sf2.o
+obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
 
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
new file mode 100644
index 000..4d0c138
--- /dev/null
+++ b/drivers/net/dsa/qca8k.c
@@ -0,0 +1,969 @@
+/*
+ * Copyright (C) 2009 Felix Fietkau <n...@nbd.name>
+ * Copyright (C) 2011-2012 Gabor Juhos <juh...@openwrt.org>
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016 John Crispin <j...@phrozen.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "qca8k.h"
+
+#define MIB_DESC(_s, _o, _n)   \
+   {   \
+   .size = (_s),   \
+   .offset = (_o), \
+   .name = (_n),   \
+   }
+
+static const struct qca8k_mib_desc ar8327_mib[] = {
+   MIB_DESC(1, 0x00, "RxBroad"),
+   MIB_DESC(1, 0x04, "RxPause"),
+   MIB_DESC(1, 0x08, "RxMulti"),
+   MIB_DESC(1, 0x0c, "RxFcsErr"),
+   MIB_DESC(1, 0x10, "RxAlignErr"),
+   MIB_DESC(1, 0x14, "RxRunt"),
+   MIB_DESC(1, 0x18, "RxFragment"),
+   MIB_DESC(1, 0x1c, "Rx64Byte"),
+   MIB_DESC(1, 0x20, "Rx128Byte"),
+   MIB_DESC(1, 0x24, "Rx256Byte"),
+   MIB_DESC(1, 0x28, "Rx512Byte"),
+   MIB_DESC(1, 0x2c, "Rx1024Byte"),
+   MIB_DESC(1, 0x30, "Rx1518Byte"),
+   MIB_DESC(1, 0x34, "RxMaxByte"),
+   MIB_DESC(1, 0x38, "RxTooLong"),
+   MIB_DESC(2, 0x3c, "RxGoodByte"),
+   MIB_DESC(2, 0x44, "RxBadByte"),
+   MIB_DESC(1, 0x4c, "RxOverFlow"),
+   MIB_DESC(1, 0x50, "Filtered"),
+   MIB_DESC(1, 0x54, "TxBroad"),
+   MIB_DESC(1, 0x58, "TxPause"),
+   MIB_DESC(1, 0x5c, "TxMulti"),
+   MIB_DESC(1, 0x60, "TxUnderRun"),
+   MIB_DESC(1, 0x64, "Tx64Byte"),
+   MIB_DESC(1, 0x68, "Tx128Byte"),
+   MIB_DESC(1, 0x6c, "Tx256Byte"),
+   MIB_DESC(1, 0x70, "Tx512Byte"),
+   MIB_DESC(1, 0x74, "Tx1024Byte"),
+   MIB_DESC(1, 0x78, "Tx1518Byte"),
+   MIB_DESC(1, 0x7c, "TxMaxByte"),
+   MIB_DESC(1, 0x80, "TxOverSize"),
+   MIB_DESC(2, 0x84, "TxByte"),
+   MIB_DESC(1, 0x8c, "TxCollision"),
+   MIB_DESC(1, 0x90, "TxAbortCol"),
+   MIB_DESC(1, 0x94, "TxMultiCol"),
+   MIB_DESC(1, 0x98, "TxSingleCol"),
+   MIB_DESC(1, 0x9c, "TxExcDefer"),
+   MIB_DESC(1, 0xa0, "TxDefer"),
+   MIB_DESC(

[PATCH 1/3] Documentation: devicetree: add qca8k binding

2016-09-12 Thread John Crispin
Add device-tree binding for ar8xxx switch families.

Cc: devicet...@vger.kernel.org
Signed-off-by: John Crispin <j...@phrozen.org>
---
 .../devicetree/bindings/net/dsa/qca8k.txt  |   53 
 1 file changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt 
b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
new file mode 100644
index 000..2a1ad06
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -0,0 +1,53 @@
+* Qualcomm Atheros QCA8xxx switch family
+
+Required properties:
+
+- compatible: should be "qca,qca8337"
+- #size-cells: must be 0
+- #address-cells: must be 1
+
+Subnodes:
+
+The integrated switch subnode should be specified according to the binding
+described in dsa/dsa.txt.
+
+Example:
+
+{
+   switch@0 {
+   compatible = "qca,qca8337";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <30>;
+
+   ports {
+   port@0 {
+   reg = <11>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "rgmii";
+   };
+
+   port@1 {
+   reg = <0>;
+   label = "lan1";
+   };
+
+   port@2 {
+   reg = <1>;
+   label = "lan2";
+   };
+
+   port@3 {
+   reg = <2>;
+   label = "lan3";
+   };
+
+   port@4 {
+   reg = <3>;
+   label = "lan4";
+   };
+   }
+   };
+   };
-- 
1.7.10.4



[PATCH 0/3] net-next: dsa: add QCA8K support

2016-09-12 Thread John Crispin
This series is based on the AR8xxx series posted by Matthieu Olivari in may
2015. The following changes were made since then

* fixed the nitpicks from the previous review
* updated to latest API
* turned it into an mdio device
* added callbacks for fdb, bridge offloading, stp, eee, port status
* fixed several minor issues to the port setup and arp learning
* changed the namespacing as this driver to qca8k

The driver has so far only been tested on qca8337/N. It should work on other QCA
switches such as the qca8327 with minor changes.

John Crispin (3):
  Documentation: devicetree: add qca8k binding
  net-next: dsa: add Qualcomm tag RX/TX handler
  net-next: dsa: add new driver for qca8xxx family

 .../devicetree/bindings/net/dsa/qca8k.txt  |   53 ++
 drivers/net/dsa/Kconfig|9 +
 drivers/net/dsa/Makefile   |1 +
 drivers/net/dsa/qca8k.c|  969 
 drivers/net/dsa/qca8k.h|  201 
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|3 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |2 +
 net/dsa/tag_qca.c  |  158 
 11 files changed, 1401 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h
 create mode 100644 net/dsa/tag_qca.c

-- 
1.7.10.4



[PATCH 2/3] net-next: dsa: add Qualcomm tag RX/TX handler

2016-09-12 Thread John Crispin
Add support for the 2-bytes Qualcomm tag that gigabit switches such as
the QCA8337/N might insert when receiving packets, or that we need
to insert while targeting specific switch ports. The tag is inserted
directly behind the ethernet header.

Signed-off-by: John Crispin <j...@phrozen.org>
---
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|3 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |2 +
 net/dsa/tag_qca.c  |  158 
 6 files changed, 168 insertions(+)
 create mode 100644 net/dsa/tag_qca.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 9d97c52..7556646 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -26,6 +26,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
+   DSA_TAG_PROTO_QCA,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index ff7736f..96e47c5 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -38,4 +38,7 @@ config NET_DSA_TAG_EDSA
 config NET_DSA_TAG_TRAILER
bool
 
+config NET_DSA_TAG_QCA
+   bool
+
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 8af4ded..a3380ed 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -7,3 +7,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
 dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
+dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d8d267e..66e31ac 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -54,6 +54,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
 #ifdef CONFIG_NET_DSA_TAG_BRCM
[DSA_TAG_PROTO_BRCM] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_QCA
+   [DSA_TAG_PROTO_QCA] = _netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 00077a9..6cfd738 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -81,5 +81,7 @@ extern const struct dsa_device_ops trailer_netdev_ops;
 /* tag_brcm.c */
 extern const struct dsa_device_ops brcm_netdev_ops;
 
+/* tag_qca.c */
+extern const struct dsa_device_ops qca_netdev_ops;
 
 #endif
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
new file mode 100644
index 000..8d75663
--- /dev/null
+++ b/net/dsa/tag_qca.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include 
+#include "dsa_priv.h"
+
+#define QCA_HDR_LEN2
+#define QCA_HDR_VERSION0x2
+
+#define QCA_HDR_RECV_VERSION_MASK  GENMASK(15, 14)
+#define QCA_HDR_RECV_VERSION_S 14
+#define QCA_HDR_RECV_PRIORITY_MASK GENMASK(13, 11)
+#define QCA_HDR_RECV_PRIORITY_S11
+#define QCA_HDR_RECV_TYPE_MASK GENMASK(10, 6)
+#define QCA_HDR_RECV_TYPE_S6
+#define QCA_HDR_RECV_FRAME_IS_TAGGED   BIT(3)
+#define QCA_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+
+#define QCA_HDR_XMIT_VERSION_MASK  GENMASK(15, 14)
+#define QCA_HDR_XMIT_VERSION_S 14
+#define QCA_HDR_XMIT_PRIORITY_MASK GENMASK(13, 11)
+#define QCA_HDR_XMIT_PRIORITY_S11
+#define QCA_HDR_XMIT_CONTROL_MASK  GENMASK(10, 8)
+#define QCA_HDR_XMIT_CONTROL_S 8
+#define QCA_HDR_XMIT_FROM_CPU  BIT(7)
+#define QCA_HDR_XMIT_DP_BIT_MASK   GENMASK(6, 0)
+
+static inline int reg_to_port(int reg)
+{
+   if (reg < 5)
+   return reg + 1;
+
+   return -1;
+}
+
+static inline int port_to_reg(int port)
+{
+   if (port >= 1 && port <= 6)
+   return port - 1;
+
+   return -1;
+}
+
+static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u16 *phdr, hdr;
+
+   dev->stats.tx_packets++;
+   dev->stats.tx_bytes += skb->len;
+
+   if (skb_cow_head(skb, 0) < 0)
+   goto out_free;
+
+   skb_push(skb, QCA_HDR_LEN);
+
+   memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN);
+   phdr = (u16 *)(skb->data + 2 * ETH_ALEN);
+
+   /* Set the version field, and set destination port information */
+   hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
+   QCA_HDR_XMIT_FROM_CPU |
+   1 << reg_to_port(p->port);
+
+   *ph

Re: [PATCH net-next v5 2/2] net: ethernet: mediatek: enhance RX path by aggregating more SKBs into NAPI

2016-09-07 Thread John Crispin


On 03/09/2016 11:59, sean.w...@mediatek.com wrote:
> From: Sean Wang <sean.w...@mediatek.com>
> 
> The patch adds support for aggregating more SKBs feed into NAPI in
> order to get more benefits from generic receive offload (GRO) by
> peeking at the RX ring status and moving more packets right before
> returning from NAPI RX polling handler if NAPI budgets are still
> available and some packets already present in hardware.
> 
> Signed-off-by: Sean Wang <sean.w...@mediatek.com>

this looks ok to me, gave it a quick try on my HW and it works well. i
am just not sure if this is something that is commonly done. someone
with more overview of how NAPI should be used might want to comment on this.

Tested-by: John Crispin <j...@phrozen.org>


> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 31 
> -
>  1 file changed, 17 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index a1bdb53..66fd45a 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -893,14 +893,14 @@ release_desc:
>  
>   done++;
>   }
> - /* make sure that all changes to the dma ring are flushed before
> -  * we continue
> -  */
> - wmb();
> - mtk_w32(eth, ring->calc_idx, MTK_PRX_CRX_IDX0);
>  
> - if (done < budget)
> - mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS);
> + if (done) {
> + /* make sure that all changes to the dma ring are flushed before
> +  * we continue
> +  */
> + wmb();
> + mtk_w32(eth, ring->calc_idx, MTK_PRX_CRX_IDX0);
> + }
>  
>   return done;
>  }
> @@ -1020,10 +1020,13 @@ static int mtk_napi_rx(struct napi_struct *napi, int 
> budget)
>   struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
>   u32 status, mask;
>   int rx_done = 0;
> + int remain_budget = budget;
>  
>   mtk_handle_status_irq(eth);
> +
> +poll_again:
>   mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS);
> - rx_done = mtk_poll_rx(napi, budget, eth);
> + rx_done = mtk_poll_rx(napi, remain_budget, eth);
>  
>   if (unlikely(netif_msg_intr(eth))) {
>   status = mtk_r32(eth, MTK_PDMA_INT_STATUS);
> @@ -1032,18 +1035,18 @@ static int mtk_napi_rx(struct napi_struct *napi, int 
> budget)
>"done rx %d, intr 0x%08x/0x%x\n",
>rx_done, status, mask);
>   }
> -
> - if (rx_done == budget)
> + if (rx_done == remain_budget)
>   return budget;
>  
>   status = mtk_r32(eth, MTK_PDMA_INT_STATUS);
> - if (status & MTK_RX_DONE_INT)
> - return budget;
> -
> + if (status & MTK_RX_DONE_INT) {
> + remain_budget -= rx_done;
> + goto poll_again;
> + }
>   napi_complete(napi);
>   mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
>  
> - return rx_done;
> + return rx_done + budget - remain_budget;
>  }
>  
>  static int mtk_tx_alloc(struct mtk_eth *eth)
> 


Re: [PATCH net-next v5 1/2] net: ethernet: mediatek: enhance RX path by reducing the frequency of the memory barrier used

2016-09-07 Thread John Crispin


On 03/09/2016 11:59, sean.w...@mediatek.com wrote:
> From: Sean Wang <sean.w...@mediatek.com>
> 
> The patch makes move wmb() to outside the loop that could help
> RX path handling more faster although that RX descriptors aren't
> freed for DMA to use as soon as possible, but based on my experiment
> and the result shows it still can reach about 943Mbpis without
> performance drop that is tested based on the setup with one port
> using Giga PHY and 256 RX descriptors for DMA to move.
> 
> Signed-off-by: Sean Wang <sean.w...@mediatek.com>

gave it a quick spin on my hardware and it works well even when using
more than 1 gmac.

Acked-by: John Crispin <j...@phrozen.org>

> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 ++-
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index 431b851..a1bdb53 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -890,13 +890,14 @@ release_desc:
>   rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size);
>  
>   ring->calc_idx = idx;
> - /* make sure that all changes to the dma ring are flushed before
> -  * we continue
> -  */
> - wmb();
> - mtk_w32(eth, ring->calc_idx, MTK_PRX_CRX_IDX0);
> +
>   done++;
>   }
> + /* make sure that all changes to the dma ring are flushed before
> +  * we continue
> +  */
> + wmb();
> + mtk_w32(eth, ring->calc_idx, MTK_PRX_CRX_IDX0);
>  
>   if (done < budget)
>   mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS);
> 


Re: [RESEND PATCH net 07/10] net: ethernet: mediatek: fix issue of driver removal with interface is up

2016-08-25 Thread John Crispin


On 25/08/2016 12:44, Sean Wang wrote:
> 1) mtk_stop() must be called to stop for freeing DMA resources
> acquired and restoring state changed by mtk_open() when module
> removal.
> 
> 2) group clock disabled related function into mtk_hw_deinit which
> could be reused with others functionality such as the whole ethernet
> reset that would be posted in the later series of patches.
> 

Hi Sean,

these are 2 unrelated changes so they really need to go into two
separate patches. i also think that change 1) would better fit into the
future series making use of that functionality.

John

> Signed-off-by: Sean Wang 
> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index 0a4c782..c573475 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -1478,6 +1478,16 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
>   return 0;
>  }
>  
> +static int mtk_hw_deinit(struct mtk_eth *eth)
> +{
> + clk_disable_unprepare(eth->clk_esw);
> + clk_disable_unprepare(eth->clk_gp1);
> + clk_disable_unprepare(eth->clk_gp2);
> + clk_disable_unprepare(eth->clk_ethif);
> +
> + return 0;
> +}
> +
>  static int __init mtk_init(struct net_device *dev)
>  {
>   struct mtk_mac *mac = netdev_priv(dev);
> @@ -1919,11 +1929,15 @@ err_free_dev:
>  static int mtk_remove(struct platform_device *pdev)
>  {
>   struct mtk_eth *eth = platform_get_drvdata(pdev);
> + int i;
>  
> - clk_disable_unprepare(eth->clk_ethif);
> - clk_disable_unprepare(eth->clk_esw);
> - clk_disable_unprepare(eth->clk_gp1);
> - clk_disable_unprepare(eth->clk_gp2);
> + /* stop all devices to make sure that dma is properly shut down */
> + for (i = 0; i < MTK_MAC_COUNT; i++) {
> + if (!eth->netdev[i])
> + continue;
> + mtk_stop(eth->netdev[i]);
> + }
> + mtk_hw_deinit(eth);
>  
>   netif_napi_del(>tx_napi);
>   netif_napi_del(>rx_napi);
> 


Re: [RESEND PATCH net 08/10] net: ethernet: mediatek: fix the missing of_node_put() after node is used done inside mtk_mdio_init

2016-08-25 Thread John Crispin


On 25/08/2016 12:44, Sean Wang wrote:
> This patch adds the missing of_node_put() after finishing the usage
> of of_get_child_by_name.
> 
> Signed-off-by: Sean Wang <sean.w...@mediatek.com>

Acked-by: John Crispin <j...@phrozen.org>

> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index c573475..e3baa63 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -320,6 +320,7 @@ static int mtk_mdio_init(struct mtk_eth *eth)
>   err = of_mdiobus_register(eth->mii_bus, mii_np);
>   if (err)
>   goto err_free_bus;
> + of_node_put(mii_np);
>  
>   return 0;
>  
> 


Re: [RESEND PATCH net 02/10] net: ethernet: mediatek: fix incorrect return value of devm_clk_get with EPROBE_DEFER

2016-08-25 Thread John Crispin


On 25/08/2016 12:44, Sean Wang wrote:
> If the return value of devm_clk_get is EPROBE_DEFER, we should
> defer probing the driver. The change is verified and works based
> on 4.8-rc1 staying with the latest clk-next code for MT7623.
> 
> Signed-off-by: Sean Wang 
> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index 6e4a6ca..02b048f 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -1851,8 +1851,15 @@ static int mtk_probe(struct platform_device *pdev)
>   eth->clk_gp1 = devm_clk_get(>dev, "gp1");
>   eth->clk_gp2 = devm_clk_get(>dev, "gp2");
>   if (IS_ERR(eth->clk_esw) || IS_ERR(eth->clk_gp1) ||
> - IS_ERR(eth->clk_gp2) || IS_ERR(eth->clk_ethif))
> - return -ENODEV;
> + IS_ERR(eth->clk_gp2) || IS_ERR(eth->clk_ethif)) {
> + if (PTR_ERR(eth->clk_esw) == -EPROBE_DEFER ||
> + PTR_ERR(eth->clk_gp1) == -EPROBE_DEFER ||
> + PTR_ERR(eth->clk_gp1) == -EPROBE_DEFER ||
> + PTR_ERR(eth->clk_gp2) == -EPROBE_DEFER)
> + return -EPROBE_DEFER;
> + else
> + return -ENODEV;
> + }

Hi Sean,

this looks a bit tedious. maybe a better solution would be to add an
array to struct mtk_eth for the clocks and an enum for the index
mapping. that would allow the usage of loops to work out if all clocks
are fine. the following code calling clk_prepare_enable() could then
also be turned into a loop

John

>  
>   clk_prepare_enable(eth->clk_ethif);
>   clk_prepare_enable(eth->clk_esw);
> 


Re: [RESEND PATCH net 10/10] net: ethernet: mediatek: fix error handling inside mtk_mdio_init

2016-08-25 Thread John Crispin


On 25/08/2016 12:45, Sean Wang wrote:
> return -ENODEV if no child is found in MDIO bus.
> 
> Signed-off-by: Sean Wang <sean.w...@mediatek.com>

Acked-by: John Crispin <j...@phrozen.org>

> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
> b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index 05d85da..2d547c2 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -300,7 +300,7 @@ static int mtk_mdio_init(struct mtk_eth *eth)
>   }
>  
>   if (!of_device_is_available(mii_np)) {
> - err = 0;
> + err = -ENODEV;
>   goto err_put_node;
>   }
>  
> 


  1   2   3   4   >