Re: [net-next 0/2] BPF, kprobes: Add current_in_cgroup helper

2016-08-06 Thread Sargun Dhillon
On Sat, Aug 06, 2016 at 09:32:05PM -0700, Alexei Starovoitov wrote:
> On Sat, Aug 06, 2016 at 09:06:53PM -0700, Sargun Dhillon wrote:
> > This patchset includes a helper and an example to determine whether the 
> > kprobe 
> > is currently executing in the context of a specific cgroup based on a cgroup
> > bpf map / array. 
> 
> description is too short to understand how this new helper is going to be 
> used.
> depending on kprobe current is not always valid.
Anything not in in_interrupt() should have a current, right?

> what are you trying to achieve?
This is primarily to help troubleshoot containers (Docker, and now systemd). A 
lot of the time we want to determine what's going on in a given container 
(opening files, connecting to systems, etc...). There's not really a great way 
to restrict to containers except by manually walking datastructures to check 
for 
the right cgroup. This seems like a better alternative.

> This looks like an alternative to lsm patches submitted earlier?
No. But I would like to use this helper in the LSM patches I'm working on. For 
now, with those patches, and this helper, I can create a map sized 1, and add 
the cgroup I care about to it. Given I can add as many bpf programs to an LSM
hook I want, I can use this mechanism to "attach BPF programs to cgroups" -- 
I put that in quotes because you're not really attaching it to a cgroup,
but just burning some instructions on checking it. 

In my mind it seems better than making cgroup-attachment a first-class part
of the checmate work since I still want to make globally available hooks
possible.

> btw net-next is closed and no new features accepted at the moment.
Sorry, I didn't realize that. I'd still love to get feedback.
> 


Re: [net-next 0/2] BPF, kprobes: Add current_in_cgroup helper

2016-08-06 Thread Alexei Starovoitov
On Sat, Aug 06, 2016 at 09:06:53PM -0700, Sargun Dhillon wrote:
> This patchset includes a helper and an example to determine whether the 
> kprobe 
> is currently executing in the context of a specific cgroup based on a cgroup
> bpf map / array. 

description is too short to understand how this new helper is going to be used.
depending on kprobe current is not always valid.
what are you trying to achieve?
This looks like an alternative to lsm patches submitted earlier?
btw net-next is closed and no new features accepted at the moment.



[net-next 2/2] samples/bpf: Add example using current_in_cgroup

2016-08-06 Thread Sargun Dhillon
This is a simple trace example that shows programs connecting,
but only if they're in a chosen cgroup.

Signed-off-by: Sargun Dhillon 
Cc: Alexei Starovoitov 
Cc: Daniel Borkmann 
---
 samples/bpf/Makefile   |  4 ++
 samples/bpf/bpf_helpers.h  |  2 +
 samples/bpf/trace_current_in_cgroup_kern.c | 44 
 samples/bpf/trace_current_in_cgroup_user.c | 66 ++
 4 files changed, 116 insertions(+)
 create mode 100644 samples/bpf/trace_current_in_cgroup_kern.c
 create mode 100644 samples/bpf/trace_current_in_cgroup_user.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 90ebf7d..61b0534 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -24,6 +24,7 @@ hostprogs-y += test_overhead
 hostprogs-y += test_cgrp2_array_pin
 hostprogs-y += xdp1
 hostprogs-y += xdp2
+hostprogs-y += trace_current_in_cgroup
 
 test_verifier-objs := test_verifier.o libbpf.o
 test_maps-objs := test_maps.o libbpf.o
@@ -49,6 +50,7 @@ test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o
 xdp1-objs := bpf_load.o libbpf.o xdp1_user.o
 # reuse xdp1 source intentionally
 xdp2-objs := bpf_load.o libbpf.o xdp1_user.o
+trace_current_in_cgroup-objs := bpf_load.o libbpf.o 
trace_current_in_cgroup_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -74,6 +76,7 @@ always += parse_varlen.o parse_simple.o parse_ldabs.o
 always += test_cgrp2_tc_kern.o
 always += xdp1_kern.o
 always += xdp2_kern.o
+always += trace_current_in_cgroup_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 
@@ -97,6 +100,7 @@ HOSTLOADLIBES_map_perf_test += -lelf -lrt
 HOSTLOADLIBES_test_overhead += -lelf -lrt
 HOSTLOADLIBES_xdp1 += -lelf
 HOSTLOADLIBES_xdp2 += -lelf
+HOSTLOADLIBES_trace_current_in_cgroup += -lelf
 
 # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on 
cmdline:
 #  make samples/bpf/ LLC=~/git/llvm/build/bin/llc 
CLANG=~/git/llvm/build/bin/clang
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
index 217c8d5..080403c 100644
--- a/samples/bpf/bpf_helpers.h
+++ b/samples/bpf/bpf_helpers.h
@@ -43,6 +43,8 @@ static int (*bpf_get_stackid)(void *ctx, void *map, int 
flags) =
(void *) BPF_FUNC_get_stackid;
 static int (*bpf_probe_write_user)(void *dst, void *src, int size) =
(void *) BPF_FUNC_probe_write_user;
+static int (*bpf_current_in_cgroup)(void *map, int index) =
+   (void *) BPF_FUNC_current_in_cgroup;
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions
diff --git a/samples/bpf/trace_current_in_cgroup_kern.c 
b/samples/bpf/trace_current_in_cgroup_kern.c
new file mode 100644
index 000..7aafb86
--- /dev/null
+++ b/samples/bpf/trace_current_in_cgroup_kern.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2016 Sargun Dhillon 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include "bpf_helpers.h"
+#include 
+
+struct bpf_map_def SEC("maps") test_current_in_cgroup_map = {
+   .type = BPF_MAP_TYPE_CGROUP_ARRAY,
+   .key_size = sizeof(u32),
+   .value_size = sizeof(u32),
+   .max_entries = 1,
+};
+
+SEC("kprobe/sys_connect")
+int bpf_prog1(struct pt_regs *ctx)
+{
+   struct sockaddr_in addr = {};
+   void *sockaddr_arg = (void *)PT_REGS_PARM2(ctx);
+   int sockaddr_len = (int)PT_REGS_PARM3(ctx);
+   char fmt[] = "Connection on port %d\n";
+
+   if (!bpf_current_in_cgroup(_current_in_cgroup_map, 0))
+   return 0;
+   if (sockaddr_len > sizeof(addr))
+   return 0;
+   if (bpf_probe_read(, sizeof(addr), sockaddr_arg) != 0)
+   return 0;
+   if (addr.sin_family != AF_INET)
+   return 0;
+
+   bpf_trace_printk(fmt, sizeof(fmt), be16_to_cpu(addr.sin_port));
+
+   return 1;
+}
+
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/trace_current_in_cgroup_user.c 
b/samples/bpf/trace_current_in_cgroup_user.c
new file mode 100644
index 000..be717bb
--- /dev/null
+++ b/samples/bpf/trace_current_in_cgroup_user.c
@@ -0,0 +1,66 @@
+#include 
+#include 
+#include 
+#include 
+#include "libbpf.h"
+#include "bpf_load.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void usage(char **argv)
+{
+   printf("Usage:  %s [...]\n", argv[0]);
+   printf("-f   Full path of the cgroup2\n");
+   printf("-h  Display this help\n");
+}
+
+int main(int argc, char **argv)
+{
+   char filename[256];
+   const char *cg2 = NULL;
+   int ret, opt, cg2_fd;
+   int array_index = 0;
+
+   while ((opt = getopt(argc, argv, "f:")) != -1) {

[net-next 0/2] BPF, kprobes: Add current_in_cgroup helper

2016-08-06 Thread Sargun Dhillon
This patchset includes a helper and an example to determine whether the kprobe 
is currently executing in the context of a specific cgroup based on a cgroup
bpf map / array. 

Sargun Dhillon (2):
  bpf: Add bpf_current_in_cgroup helper
  samples/bpf: Add example using current_in_cgroup

 include/linux/bpf.h| 24 +++
 include/uapi/linux/bpf.h   | 11 +
 kernel/bpf/arraymap.c  |  2 +-
 kernel/bpf/verifier.c  |  4 +-
 kernel/trace/bpf_trace.c   | 34 +++
 net/core/filter.c  | 11 ++---
 samples/bpf/Makefile   |  4 ++
 samples/bpf/bpf_helpers.h  |  2 +
 samples/bpf/trace_current_in_cgroup_kern.c | 44 
 samples/bpf/trace_current_in_cgroup_user.c | 66 ++
 10 files changed, 193 insertions(+), 9 deletions(-)
 create mode 100644 samples/bpf/trace_current_in_cgroup_kern.c
 create mode 100644 samples/bpf/trace_current_in_cgroup_user.c

-- 
2.7.4



[net-next 1/2] bpf: Add bpf_current_in_cgroup helper

2016-08-06 Thread Sargun Dhillon
This adds a kprobe helper that's similar to the skb_in_cgroup helper. It
checks whether the probe is currently executing in the context of the
cgroup at the given index a CGROUP_ARRAY.

Signed-off-by: Sargun Dhillon 
Cc: Alexei Starovoitov 
Cc: Daniel Borkmann 
---
 include/linux/bpf.h  | 24 
 include/uapi/linux/bpf.h | 11 +++
 kernel/bpf/arraymap.c|  2 +-
 kernel/bpf/verifier.c|  4 +++-
 kernel/trace/bpf_trace.c | 34 ++
 net/core/filter.c| 11 ---
 6 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 1113423..9adf712 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -319,4 +319,28 @@ extern const struct bpf_func_proto bpf_get_stackid_proto;
 void bpf_user_rnd_init_once(void);
 u64 bpf_user_rnd_u32(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
 
+#ifdef CONFIG_CGROUPS
+/* Helper to fetch a cgroup pointer based on index.
+ * @map: a cgroup arraymap
+ * @idx: index of the item you want to fetch
+ *
+ * Returns pointer on success,
+ * Error code if item not found, or out-of-bounds access
+ */
+static inline struct cgroup *fetch_arraymap_ptr(struct bpf_map *map, int idx)
+{
+   struct cgroup *cgrp;
+   struct bpf_array *array = container_of(map, struct bpf_array, map);
+
+   if (unlikely(idx >= array->map.max_entries))
+   return ERR_PTR(-E2BIG);
+
+   cgrp = READ_ONCE(array->ptrs[idx]);
+   if (unlikely(!cgrp))
+   return ERR_PTR(-EAGAIN);
+
+   return cgrp;
+}
+#endif /* CONFIG_CGROUPS */
+
 #endif /* _LINUX_BPF_H */
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index da218fe..23a5b99 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -375,6 +375,17 @@ enum bpf_func_id {
 */
BPF_FUNC_probe_write_user,
 
+   /**
+* bpf_current_in_cgroup(map, index) - Check cgroup2 membership of skb
+* @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
+* @index: index of the cgroup in the bpf_map
+* Return:
+*   == 0 current failed the cgroup2 descendant test
+*   == 1 current succeeded the cgroup2 descendant test
+*< 0 error
+*/
+   BPF_FUNC_current_in_cgroup,
+
__BPF_FUNC_MAX_ID,
 };
 
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 633a650..a2ac051 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -538,7 +538,7 @@ static int __init register_perf_event_array_map(void)
 }
 late_initcall(register_perf_event_array_map);
 
-#ifdef CONFIG_SOCK_CGROUP_DATA
+#ifdef CONFIG_CGROUPS
 static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
 struct file *map_file /* not used */,
 int fd)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f72f23b..e16559b 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1052,7 +1052,8 @@ static int check_map_func_compatibility(struct bpf_map 
*map, int func_id)
goto error;
break;
case BPF_MAP_TYPE_CGROUP_ARRAY:
-   if (func_id != BPF_FUNC_skb_in_cgroup)
+   if (func_id != BPF_FUNC_skb_in_cgroup &&
+   func_id != BPF_FUNC_current_in_cgroup)
goto error;
break;
default:
@@ -1074,6 +1075,7 @@ static int check_map_func_compatibility(struct bpf_map 
*map, int func_id)
if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
goto error;
break;
+   case BPF_FUNC_current_in_cgroup:
case BPF_FUNC_skb_in_cgroup:
if (map->map_type != BPF_MAP_TYPE_CGROUP_ARRAY)
goto error;
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index b20438f..f2a6bc5 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -376,6 +376,36 @@ static const struct bpf_func_proto 
bpf_get_current_task_proto = {
.ret_type   = RET_INTEGER,
 };
 
+#ifdef CONFIG_CGROUPS
+static u64 bpf_current_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
+{
+   struct bpf_map *map = (struct bpf_map *)(long)r1;
+   struct css_set *cset;
+   struct cgroup *cgrp;
+   u32 idx = (u32)r2;
+
+   if (unlikely(in_interrupt()))
+   return -EINVAL;
+
+   cgrp = fetch_arraymap_ptr(map, idx);
+
+   if (unlikely(IS_ERR(cgrp)))
+   return PTR_ERR(cgrp);
+
+   cset = task_css_set(current);
+
+   return cgroup_is_descendant(cset->dfl_cgrp, cgrp);
+}
+
+static const struct bpf_func_proto bpf_current_in_cgroup_proto = {
+   .func   = bpf_current_in_cgroup,
+   .gpl_only   = false,
+   .ret_type   = RET_INTEGER,
+   .arg1_type  = ARG_CONST_MAP_PTR,
+   .arg2_type  = 

[PATCH v2 04/14] net: ethernet: ti: cpsw: remove clk var from priv

2016-08-06 Thread Ivan Khoronzhuk
There is no need to hold link to clk, it's used only once
while probe.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 30e1ddb..70a9570 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -379,7 +379,6 @@ struct cpsw_priv {
u32 coal_intvl;
u32 bus_freq_mhz;
int rx_packet_max;
-   struct clk  *clk;
u8  mac_addr[ETH_ALEN];
struct cpsw_slave   *slaves;
struct cpdma_ctlr   *dma;
@@ -2179,8 +2178,6 @@ static int cpsw_probe_dual_emac(struct platform_device 
*pdev,
memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
 
priv_sl2->slaves = priv->slaves;
-   priv_sl2->clk = priv->clk;
-
priv_sl2->coal_intvl = 0;
priv_sl2->bus_freq_mhz = priv->bus_freq_mhz;
 
@@ -2258,6 +2255,7 @@ MODULE_DEVICE_TABLE(of, cpsw_of_mtable);
 
 static int cpsw_probe(struct platform_device *pdev)
 {
+   struct clk  *clk;
struct cpsw_platform_data   *data;
struct net_device   *ndev;
struct cpsw_priv*priv;
@@ -2336,14 +2334,14 @@ static int cpsw_probe(struct platform_device *pdev)
priv->slaves[0].ndev = ndev;
priv->emac_port = 0;
 
-   priv->clk = devm_clk_get(>dev, "fck");
-   if (IS_ERR(priv->clk)) {
+   clk = devm_clk_get(>dev, "fck");
+   if (IS_ERR(clk)) {
dev_err(priv->dev, "fck is not found\n");
ret = -ENODEV;
goto clean_runtime_disable_ret;
}
priv->coal_intvl = 0;
-   priv->bus_freq_mhz = clk_get_rate(priv->clk) / 100;
+   priv->bus_freq_mhz = clk_get_rate(clk) / 100;
 
ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ss_regs = devm_ioremap_resource(>dev, ss_res);
-- 
1.9.1



[PATCH v2 01/14] net: ethernet: ti: cpsw: simplify submit routine

2016-08-06 Thread Ivan Khoronzhuk
As second net dev is created only in case of dual_emac mode, port
number can be figured out in simpler way. Also no need to pass
redundant ndev struct.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index c51f346..8972bf6 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1065,19 +1065,11 @@ static int cpsw_common_res_usage_state(struct cpsw_priv 
*priv)
return usage_count;
 }
 
-static inline int cpsw_tx_packet_submit(struct net_device *ndev,
-   struct cpsw_priv *priv, struct sk_buff *skb)
+static inline int cpsw_tx_packet_submit(struct cpsw_priv *priv,
+   struct sk_buff *skb)
 {
-   if (!priv->data.dual_emac)
-   return cpdma_chan_submit(priv->txch, skb, skb->data,
- skb->len, 0);
-
-   if (ndev == cpsw_get_slave_ndev(priv, 0))
-   return cpdma_chan_submit(priv->txch, skb, skb->data,
- skb->len, 1);
-   else
-   return cpdma_chan_submit(priv->txch, skb, skb->data,
- skb->len, 2);
+   return cpdma_chan_submit(priv->txch, skb, skb->data, skb->len,
+priv->emac_port + priv->data.dual_emac);
 }
 
 static inline void cpsw_add_dual_emac_def_ale_entries(
@@ -1406,7 +1398,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff 
*skb,
 
skb_tx_timestamp(skb);
 
-   ret = cpsw_tx_packet_submit(ndev, priv, skb);
+   ret = cpsw_tx_packet_submit(priv, skb);
if (unlikely(ret != 0)) {
cpsw_err(priv, tx_err, "desc submit failed\n");
goto fail;
-- 
1.9.1



[PATCH v2 05/14] net: ethernet: ti: cpsw: don't check slave num in runtime

2016-08-06 Thread Ivan Khoronzhuk
No need to check const slave num in runtime for every packet,
and ndev for slaves w/o ndev is anyway NULL. So remove redundant
check.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 70a9570..19aa4bb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -498,8 +498,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
(func)(slave++, ##arg); \
} while (0)
 #define cpsw_get_slave_ndev(priv, __slave_no__)
\
-   ((__slave_no__ < priv->data.slaves) ?   \
-   priv->slaves[__slave_no__].ndev : NULL)
+   priv->slaves[__slave_no__].ndev
 #define cpsw_get_slave_priv(priv, __slave_no__)
\
(((__slave_no__ < priv->data.slaves) && \
(priv->slaves[__slave_no__].ndev)) ?\
-- 
1.9.1



[PATCH v2 13/14] net: ethernet: ti: cpsw: move napi struct to cpsw_common

2016-08-06 Thread Ivan Khoronzhuk
The napi structs are common for both net devices in dual_emac
mode, In order to not hold duplicate links to them, move to
cpsw_common.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 50 +++---
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 395531d..e0a1b80 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -367,6 +367,8 @@ static inline void slave_write(struct cpsw_slave *slave, 
u32 val, u32 offset)
 struct cpsw_common {
struct device   *dev;
struct cpsw_platform_data   data;
+   struct napi_struct  napi_rx;
+   struct napi_struct  napi_tx;
struct cpsw_ss_regs __iomem *regs;
struct cpsw_wr_regs __iomem *wr_regs;
u8 __iomem  *hw_stats;
@@ -383,8 +385,6 @@ struct cpsw_common {
 
 struct cpsw_priv {
struct net_device   *ndev;
-   struct napi_struct  napi_rx;
-   struct napi_struct  napi_tx;
struct device   *dev;
u32 msg_enable;
u32 version;
@@ -489,7 +489,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
 #define CPSW_STATS_LEN ARRAY_SIZE(cpsw_gstrings_stats)
 
 #define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)
-#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi)
+#define napi_to_cpsw(napi) container_of(napi, struct cpsw_common, napi)
 #define for_each_slave(priv, func, arg...) \
do {\
struct cpsw_slave *slave;   \
@@ -755,8 +755,7 @@ requeue:
 
 static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
 {
-   struct cpsw_priv *priv = dev_id;
-   struct cpsw_common *cpsw = priv->cpsw;
+   struct cpsw_common *cpsw = dev_id;
 
writel(0, >wr_regs->tx_en);
cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_TX);
@@ -766,14 +765,13 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void 
*dev_id)
cpsw->tx_irq_disabled = true;
}
 
-   napi_schedule(>napi_tx);
+   napi_schedule(>napi_tx);
return IRQ_HANDLED;
 }
 
 static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
 {
-   struct cpsw_priv *priv = dev_id;
-   struct cpsw_common *cpsw = priv->cpsw;
+   struct cpsw_common *cpsw = dev_id;
 
cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX);
writel(0, >wr_regs->rx_en);
@@ -783,15 +781,14 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void 
*dev_id)
cpsw->rx_irq_disabled = true;
}
 
-   napi_schedule(>napi_rx);
+   napi_schedule(>napi_rx);
return IRQ_HANDLED;
 }
 
 static int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
 {
-   struct cpsw_priv*priv = napi_to_priv(napi_tx);
+   struct cpsw_common  *cpsw = napi_to_cpsw(napi_tx);
int num_tx;
-   struct cpsw_common  *cpsw = priv->cpsw;
 
num_tx = cpdma_chan_process(cpsw->txch, budget);
if (num_tx < budget) {
@@ -811,9 +808,8 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int 
budget)
 
 static int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)
 {
-   struct cpsw_priv*priv = napi_to_priv(napi_rx);
+   struct cpsw_common  *cpsw = napi_to_cpsw(napi_rx);
int num_rx;
-   struct cpsw_common  *cpsw = priv->cpsw;
 
num_rx = cpdma_chan_process(cpsw->rxch, budget);
if (num_rx < budget) {
@@ -1292,7 +1288,6 @@ static int cpsw_ndo_open(struct net_device *ndev)
  ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0);
 
if (!cpsw_common_res_usage_state(cpsw)) {
-   struct cpsw_priv *priv_sl0 = cpsw_get_slave_priv(cpsw, 0);
int buf_num;
 
/* setup tx dma to fixed prio and zero offset */
@@ -1308,8 +1303,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
/* Enable internal fifo flow control */
writel(0x7, >regs->flow_control);
 
-   napi_enable(_sl0->napi_rx);
-   napi_enable(_sl0->napi_tx);
+   napi_enable(>napi_rx);
+   napi_enable(>napi_tx);
 
if (cpsw->tx_irq_disabled) {
cpsw->tx_irq_disabled = false;
@@ -1384,8 +1379,8 @@ static int cpsw_ndo_stop(struct net_device *ndev)
if (cpsw_common_res_usage_state(cpsw) <= 1) {
struct cpsw_priv *priv_sl0 = cpsw_get_slave_priv(cpsw, 0);
 
-   napi_disable(_sl0->napi_rx);
-   napi_disable(_sl0->napi_tx);
+   napi_disable(>napi_rx);
+   

[PATCH v2 08/14] net: ethernet: ti: cpsw: move links on h/w registers to cpsw_common

2016-08-06 Thread Ivan Khoronzhuk
The pointers on h/w registers are common for every cpsw_private
instance, so no need to hold them for every ndev.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 97 +++---
 1 file changed, 53 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a813bac..6fc22df 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -365,6 +365,10 @@ static inline void slave_write(struct cpsw_slave *slave, 
u32 val, u32 offset)
 
 struct cpsw_common {
struct device   *dev;
+   struct cpsw_ss_regs __iomem *regs;
+   struct cpsw_wr_regs __iomem *wr_regs;
+   u8 __iomem  *hw_stats;
+   struct cpsw_host_regs __iomem   *host_port_regs;
 };
 
 struct cpsw_priv {
@@ -373,10 +377,6 @@ struct cpsw_priv {
struct napi_struct  napi_tx;
struct device   *dev;
struct cpsw_platform_data   data;
-   struct cpsw_ss_regs __iomem *regs;
-   struct cpsw_wr_regs __iomem *wr_regs;
-   u8 __iomem  *hw_stats;
-   struct cpsw_host_regs __iomem   *host_port_regs;
u32 msg_enable;
u32 version;
u32 coal_intvl;
@@ -658,8 +658,10 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 static void cpsw_intr_enable(struct cpsw_priv *priv)
 {
-   __raw_writel(0xFF, >wr_regs->tx_en);
-   __raw_writel(0xFF, >wr_regs->rx_en);
+   struct cpsw_common *cpsw = priv->cpsw;
+
+   __raw_writel(0xFF, >wr_regs->tx_en);
+   __raw_writel(0xFF, >wr_regs->rx_en);
 
cpdma_ctlr_int_ctrl(priv->dma, true);
return;
@@ -667,8 +669,10 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
 
 static void cpsw_intr_disable(struct cpsw_priv *priv)
 {
-   __raw_writel(0, >wr_regs->tx_en);
-   __raw_writel(0, >wr_regs->rx_en);
+   struct cpsw_common *cpsw = priv->cpsw;
+
+   __raw_writel(0, >wr_regs->tx_en);
+   __raw_writel(0, >wr_regs->rx_en);
 
cpdma_ctlr_int_ctrl(priv->dma, false);
return;
@@ -752,8 +756,9 @@ requeue:
 static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
 {
struct cpsw_priv *priv = dev_id;
+   struct cpsw_common *cpsw = priv->cpsw;
 
-   writel(0, >wr_regs->tx_en);
+   writel(0, >wr_regs->tx_en);
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
 
if (priv->quirk_irq) {
@@ -768,9 +773,10 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
 static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
 {
struct cpsw_priv *priv = dev_id;
+   struct cpsw_common *cpsw = priv->cpsw;
 
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
-   writel(0, >wr_regs->rx_en);
+   writel(0, >wr_regs->rx_en);
 
if (priv->quirk_irq) {
disable_irq_nosync(priv->irqs_table[0]);
@@ -785,11 +791,12 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int 
budget)
 {
struct cpsw_priv*priv = napi_to_priv(napi_tx);
int num_tx;
+   struct cpsw_common  *cpsw = priv->cpsw;
 
num_tx = cpdma_chan_process(priv->txch, budget);
if (num_tx < budget) {
napi_complete(napi_tx);
-   writel(0xff, >wr_regs->tx_en);
+   writel(0xff, >wr_regs->tx_en);
if (priv->quirk_irq && priv->tx_irq_disabled) {
priv->tx_irq_disabled = false;
enable_irq(priv->irqs_table[1]);
@@ -804,11 +811,12 @@ static int cpsw_rx_poll(struct napi_struct *napi_rx, int 
budget)
 {
struct cpsw_priv*priv = napi_to_priv(napi_rx);
int num_rx;
+   struct cpsw_common  *cpsw = priv->cpsw;
 
num_rx = cpdma_chan_process(priv->rxch, budget);
if (num_rx < budget) {
napi_complete(napi_rx);
-   writel(0xff, >wr_regs->rx_en);
+   writel(0xff, >wr_regs->rx_en);
if (priv->quirk_irq && priv->rx_irq_disabled) {
priv->rx_irq_disabled = false;
enable_irq(priv->irqs_table[0]);
@@ -929,10 +937,11 @@ static int cpsw_set_coalesce(struct net_device *ndev,
u32 prescale = 0;
u32 addnl_dvdr = 1;
u32 coal_intvl = 0;
+   struct cpsw_common *cpsw = priv->cpsw;
 
coal_intvl = coal->rx_coalesce_usecs;
 
-   int_ctrl =  readl(>wr_regs->int_control);
+   int_ctrl =  readl(>wr_regs->int_control);
prescale = priv->bus_freq_mhz * 4;
 
if (!coal->rx_coalesce_usecs) {
@@ -961,15 +970,15 @@ static int cpsw_set_coalesce(struct net_device *ndev,
}
 
num_interrupts = (1000 * addnl_dvdr) / coal_intvl;
-   writel(num_interrupts, >wr_regs->rx_imax);
-  

[PATCH v2 02/14] net: ethernet: ti: cpsw: remove redundant check in napi poll

2016-08-06 Thread Ivan Khoronzhuk
No need to check number of handled packets, when in most cases (> 99%)
it's not 0. It can be 0 only in rare cases, even in this case
it's not bad to print just 0.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8972bf6..85ee9f5 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -793,9 +793,7 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int 
budget)
}
}
 
-   if (num_tx)
-   cpsw_dbg(priv, intr, "poll %d tx pkts\n", num_tx);
-
+   cpsw_dbg(priv, intr, "poll %d tx pkts\n", num_tx);
return num_tx;
 }
 
@@ -814,9 +812,7 @@ static int cpsw_rx_poll(struct napi_struct *napi_rx, int 
budget)
}
}
 
-   if (num_rx)
-   cpsw_dbg(priv, intr, "poll %d rx pkts\n", num_rx);
-
+   cpsw_dbg(priv, intr, "poll %d rx pkts\n", num_rx);
return num_rx;
 }
 
-- 
1.9.1



[PATCH v2 00/14] net: ethernet: ti: cpsw: split driver data and per ndev data

2016-08-06 Thread Ivan Khoronzhuk
In dual_emac mode the driver can handle 2 network devices. Each of them can use
its own private data and common data/resources. This patchset splits common 
driver
data/resources and private per net device data.
It leads to:
- reduce memory usage
- increase code readability
- allows add a bunch of simplification
- create prerequisites to add multi-channel support,
  when channels are shared between net devices

Doesn't have bad impact on performance.
v1: https://lkml.org/lkml/2016/8/4/616

Since v1:
- added several patch improvements
- avoided variable reordering in structures
- removed static variable for common function
- split big patch on several patches:
  net: ethernet: ti: cpsw: remove priv from cpsw_get_slave_port() parameters 
list
  net: ethernet: ti: cpsw: remove clk var from priv
  net: ethernet: ti: cpsw: don't check slave num in runtime
  net: ethernet: ti: cpsw: create common struct to hold shared driver data
  net: ethernet: ti: cpsw: replace pdev on dev
  net: ethernet: ti: cpsw: move links on h/w registers to cpsw_common
  net: ethernet: ti: cpsw: move cpdma resources to cpsw_common
  net; ethernet: ti: cpsw: move irq stuff under cpsw_common
  net: ethernet: ti: cpsw: move data platform data and slaves info to 
cpsw_common
  net: ethernet: ti: cpsw: fix int dbg message
  net: ethernet: ti: cpsw: move napi struct to cpsw_common
  net: ethernet: ti: cpsw: move ale, cpts and drivers params under

Based on net-next/master

Ivan Khoronzhuk (14):
  net: ethernet: ti: cpsw: simplify submit routine
  net: ethernet: ti: cpsw: remove redundant check in napi poll
  net: ethernet: ti: cpsw: remove priv from cpsw_get_slave_port()
parameters list
  net: ethernet: ti: cpsw: remove clk var from priv
  net: ethernet: ti: cpsw: don't check slave num in runtime
  net: ethernet: ti: cpsw: create common struct to hold shared driver
data
  net: ethernet: ti: cpsw: replace pdev on dev
  net: ethernet: ti: cpsw: move links on h/w registers to cpsw_common
  net: ethernet: ti: cpsw: move cpdma resources to cpsw_common
  net; ethernet: ti: cpsw: move irq stuff under cpsw_common
  net: ethernet: ti: cpsw: move data platform data and slaves info to
cpsw_common
  net: ethernet: ti: cpsw: fix int dbg message
  net: ethernet: ti: cpsw: move napi struct to cpsw_common
  net: ethernet: ti: cpsw: move ale, cpts and drivers params under
cpsw_common

 drivers/net/ethernet/ti/cpsw.c | 879 +
 1 file changed, 447 insertions(+), 432 deletions(-)

-- 
1.9.1



[PATCH v2 10/14] net; ethernet: ti: cpsw: move irq stuff under cpsw_common

2016-08-06 Thread Ivan Khoronzhuk
The irq data are common per net device. So no need to hold these
data per net dev, move it under cpsw_common. Also delete irq_num
var, as after optimization it's not needed. Correct number of
irqs to 2, as anyway, driver is using only 2, at least for now.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 65 +++---
 1 file changed, 29 insertions(+), 36 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index d3af373..4080487 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -143,6 +143,7 @@ do {
\
 #define cpsw_slave_index(priv) \
((priv->data.dual_emac) ? priv->emac_port : \
priv->data.active_slave)
+#define IRQ_NUM2
 
 static int debug_level;
 module_param(debug_level, int, 0);
@@ -371,6 +372,10 @@ struct cpsw_common {
struct cpsw_host_regs __iomem   *host_port_regs;
struct cpdma_ctlr   *dma;
struct cpdma_chan   *txch, *rxch;
+   boolquirk_irq;
+   boolrx_irq_disabled;
+   booltx_irq_disabled;
+   u32 irqs_table[IRQ_NUM];
 };
 
 struct cpsw_priv {
@@ -389,12 +394,6 @@ struct cpsw_priv {
struct cpsw_ale *ale;
boolrx_pause;
booltx_pause;
-   boolquirk_irq;
-   boolrx_irq_disabled;
-   booltx_irq_disabled;
-   /* snapshot of IRQ numbers */
-   u32 irqs_table[4];
-   u32 num_irqs;
struct cpts *cpts;
u32 emac_port;
struct cpsw_common *cpsw;
@@ -758,9 +757,9 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
writel(0, >wr_regs->tx_en);
cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_TX);
 
-   if (priv->quirk_irq) {
-   disable_irq_nosync(priv->irqs_table[1]);
-   priv->tx_irq_disabled = true;
+   if (cpsw->quirk_irq) {
+   disable_irq_nosync(cpsw->irqs_table[1]);
+   cpsw->tx_irq_disabled = true;
}
 
napi_schedule(>napi_tx);
@@ -775,9 +774,9 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX);
writel(0, >wr_regs->rx_en);
 
-   if (priv->quirk_irq) {
-   disable_irq_nosync(priv->irqs_table[0]);
-   priv->rx_irq_disabled = true;
+   if (cpsw->quirk_irq) {
+   disable_irq_nosync(cpsw->irqs_table[0]);
+   cpsw->rx_irq_disabled = true;
}
 
napi_schedule(>napi_rx);
@@ -794,9 +793,9 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int 
budget)
if (num_tx < budget) {
napi_complete(napi_tx);
writel(0xff, >wr_regs->tx_en);
-   if (priv->quirk_irq && priv->tx_irq_disabled) {
-   priv->tx_irq_disabled = false;
-   enable_irq(priv->irqs_table[1]);
+   if (cpsw->quirk_irq && cpsw->tx_irq_disabled) {
+   cpsw->tx_irq_disabled = false;
+   enable_irq(cpsw->irqs_table[1]);
}
}
 
@@ -814,9 +813,9 @@ static int cpsw_rx_poll(struct napi_struct *napi_rx, int 
budget)
if (num_rx < budget) {
napi_complete(napi_rx);
writel(0xff, >wr_regs->rx_en);
-   if (priv->quirk_irq && priv->rx_irq_disabled) {
-   priv->rx_irq_disabled = false;
-   enable_irq(priv->irqs_table[0]);
+   if (cpsw->quirk_irq && cpsw->rx_irq_disabled) {
+   cpsw->rx_irq_disabled = false;
+   enable_irq(cpsw->irqs_table[0]);
}
}
 
@@ -1303,14 +1302,14 @@ static int cpsw_ndo_open(struct net_device *ndev)
napi_enable(_sl0->napi_rx);
napi_enable(_sl0->napi_tx);
 
-   if (priv_sl0->tx_irq_disabled) {
-   priv_sl0->tx_irq_disabled = false;
-   enable_irq(priv->irqs_table[1]);
+   if (cpsw->tx_irq_disabled) {
+   cpsw->tx_irq_disabled = false;
+   enable_irq(cpsw->irqs_table[1]);
}
 
-   if (priv_sl0->rx_irq_disabled) {
-   priv_sl0->rx_irq_disabled = false;
-   enable_irq(priv->irqs_table[0]);
+   if (cpsw->rx_irq_disabled) {
+   cpsw->rx_irq_disabled = false;
+   enable_irq(cpsw->irqs_table[0]);
}
 
buf_num = cpdma_chan_get_rx_buf_num(cpsw->dma);
@@ -1659,8 

[PATCH v2 03/14] net: ethernet: ti: cpsw: remove priv from cpsw_get_slave_port() parameters list

2016-08-06 Thread Ivan Khoronzhuk
There is no need in priv here.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 85ee9f5..30e1ddb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -525,7 +525,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
if (priv->data.dual_emac) { \
struct cpsw_slave *slave = priv->slaves +   \
priv->emac_port;\
-   int slave_port = cpsw_get_slave_port(priv,  \
+   int slave_port = cpsw_get_slave_port(   \
slave->slave_num);  \
cpsw_ale_add_mcast(priv->ale, addr, \
1 << slave_port | ALE_PORT_HOST,\
@@ -537,7 +537,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
}   \
} while (0)
 
-static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+static inline int cpsw_get_slave_port(u32 slave_num)
 {
return slave_num + 1;
 }
@@ -849,7 +849,7 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
if (!phy)
return;
 
-   slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+   slave_port = cpsw_get_slave_port(slave->slave_num);
 
if (phy->link) {
mac_control = priv->data.mac_control;
@@ -1120,7 +1120,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, 
struct cpsw_priv *priv)
 
slave->mac_control = 0; /* no link yet */
 
-   slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+   slave_port = cpsw_get_slave_port(slave->slave_num);
 
if (priv->data.dual_emac)
cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
@@ -1222,7 +1222,7 @@ static void cpsw_slave_stop(struct cpsw_slave *slave, 
struct cpsw_priv *priv)
 {
u32 slave_port;
 
-   slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+   slave_port = cpsw_get_slave_port(slave->slave_num);
 
if (!slave->phy)
return;
-- 
1.9.1



[PATCH v2 07/14] net: ethernet: ti: cpsw: replace pdev on dev

2016-08-06 Thread Ivan Khoronzhuk
No need to hold pdev link when only dev is needed.
This allows to simplify a bunch of cpsw->pdev->dev now and farther.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 65 ++
 1 file changed, 34 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index ac875b3..a813bac 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -364,7 +364,7 @@ static inline void slave_write(struct cpsw_slave *slave, 
u32 val, u32 offset)
 }
 
 struct cpsw_common {
-   struct platform_device  *pdev;
+   struct device   *dev;
 };
 
 struct cpsw_priv {
@@ -1159,7 +1159,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, 
struct cpsw_priv *priv)
phy_start(slave->phy);
 
/* Configure GMII_SEL register */
-   cpsw_phy_sel(>pdev->dev, slave->phy->interface, slave->slave_num);
+   cpsw_phy_sel(cpsw->dev, slave->phy->interface, slave->slave_num);
 }
 
 static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
@@ -1245,9 +1245,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
int i, ret;
u32 reg;
 
-   ret = pm_runtime_get_sync(>pdev->dev);
+   ret = pm_runtime_get_sync(cpsw->dev);
if (ret < 0) {
-   pm_runtime_put_noidle(>pdev->dev);
+   pm_runtime_put_noidle(cpsw->dev);
return ret;
}
 
@@ -1324,7 +1324,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 */
cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
-   if (cpts_register(>pdev->dev, priv->cpts,
+   if (cpts_register(cpsw->dev, priv->cpts,
  priv->data.cpts_clock_mult,
  priv->data.cpts_clock_shift))
dev_err(priv->dev, "error registering cpts device\n");
@@ -1349,7 +1349,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 err_cleanup:
cpdma_ctlr_stop(priv->dma);
for_each_slave(priv, cpsw_slave_stop, priv);
-   pm_runtime_put_sync(>pdev->dev);
+   pm_runtime_put_sync(cpsw->dev);
netif_carrier_off(priv->ndev);
return ret;
 }
@@ -1374,7 +1374,7 @@ static int cpsw_ndo_stop(struct net_device *ndev)
cpsw_ale_stop(priv->ale);
}
for_each_slave(priv, cpsw_slave_stop, priv);
-   pm_runtime_put_sync(>pdev->dev);
+   pm_runtime_put_sync(cpsw->dev);
if (priv->data.dual_emac)
priv->slaves[priv->emac_port].open_stat = false;
return 0;
@@ -1614,9 +1614,9 @@ static int cpsw_ndo_set_mac_address(struct net_device 
*ndev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
 
-   ret = pm_runtime_get_sync(>pdev->dev);
+   ret = pm_runtime_get_sync(cpsw->dev);
if (ret < 0) {
-   pm_runtime_put_noidle(>pdev->dev);
+   pm_runtime_put_noidle(cpsw->dev);
return ret;
}
 
@@ -1634,7 +1634,7 @@ static int cpsw_ndo_set_mac_address(struct net_device 
*ndev, void *p)
memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
for_each_slave(priv, cpsw_set_slave_mac, priv);
 
-   pm_runtime_put(>pdev->dev);
+   pm_runtime_put(cpsw->dev);
 
return 0;
 }
@@ -1706,9 +1706,9 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device 
*ndev,
if (vid == priv->data.default_vlan)
return 0;
 
-   ret = pm_runtime_get_sync(>pdev->dev);
+   ret = pm_runtime_get_sync(cpsw->dev);
if (ret < 0) {
-   pm_runtime_put_noidle(>pdev->dev);
+   pm_runtime_put_noidle(cpsw->dev);
return ret;
}
 
@@ -1728,7 +1728,7 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device 
*ndev,
dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
ret = cpsw_add_vlan_ale_entry(priv, vid);
 
-   pm_runtime_put(>pdev->dev);
+   pm_runtime_put(cpsw->dev);
return ret;
 }
 
@@ -1742,9 +1742,9 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device 
*ndev,
if (vid == priv->data.default_vlan)
return 0;
 
-   ret = pm_runtime_get_sync(>pdev->dev);
+   ret = pm_runtime_get_sync(cpsw->dev);
if (ret < 0) {
-   pm_runtime_put_noidle(>pdev->dev);
+   pm_runtime_put_noidle(cpsw->dev);
return ret;
}
 
@@ -1769,7 +1769,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device 
*ndev,
 
ret = cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast,
 0, ALE_VLAN, vid);
-   pm_runtime_put(>pdev->dev);
+   pm_runtime_put(cpsw->dev);
return ret;
 }
 
@@ -1813,10 +1813,11 @@ static void cpsw_get_drvinfo(struct net_device *ndev,
 struct ethtool_drvinfo 

Re: [PATCH net] bridge: Fix problems around fdb entries pointing to the bridge device

2016-08-06 Thread Stephen Hemminger
On Thu, 04 Aug 2016 11:27:25 -0700
Roopa Prabhu  wrote:

> On 8/4/16, 1:15 AM, Toshiaki Makita wrote:
> > On 2016/08/04 16:24, Roopa Prabhu wrote:  
> >> On 8/3/16, 7:11 PM, Toshiaki Makita wrote:  
> >>> Adding fdb entries pointing to the bridge device uses fdb_insert(),
> >>> which lacks various checks and does not respect added_by_user flag.
> >>>
> >>> As a result, some inconsistent behavior can happen:
> >>> * Adding temporary entries succeeds but results in permanent entries.  
> >> IIRC this is not specific to fdb entries on the bridge device. all temp
> >> fdb entries via iproute2 result in permanent entries. thats why 'dynamic'
> >> was added.  
> > Sorry for confusing you, I meant "temp" (i.e., "static") of bridge fdb
> > command.
> > "temp", "dynamic" and "use" should not result in "permanent".
> >  
> >>> * Same goes for "dynamic" and "use".  
> >> This patch seems to not allow dynamic and use entries
> >> on the bridge device. I don't see a strong use-case to
> >> allow them, but any reason you want to add the restriction now ?  
> > Because dynamic fdb entries pointing the bridge device cannot be
> > created. So it is prohibited. I cannot find other appropriate behavior
> > about this.
> > Or are you suggesting local entries with aging supported or something
> > like that?  
> no, i am ok with prohibiting it, just was wondering if this is necessary.
> 
> >  
> >>> * Changing mac address of the bridge device causes deletion of
> >>>   user-added entries.  
> >> unless I am missing something, this does not seem to be related to the
> >> external fdb entry on the bridge device.  
> > Yes this is related to manually-added fdb entries on the bridge device.
> > When manual addition of fdb pointing the bridge device was introduced,
> > we should have set added_by_user on adding the entry and modify
> > br_fdb_change_mac_address() to respect the flag, but both were not done.
> >  
> >>> * Replacing existing entries looks successful from userspace but actually
> >>>   not, regardless of NLM_F_EXCL flag.  
> >> curious about this one. I will try it, but if you have an example that
> >> will help.  
> > Before:
> > # bridge fdb add 12:34:56:78:90:ab dev enp3s0 master
> > # bridge fdb add 12:34:56:78:90:ab dev br0; echo $?
> > 0
> > # bridge fdb show
> > ...
> > 12:34:56:78:90:ab dev enp3s0 master br0 permanent
> >
> > # bridge fdb replace 12:34:56:78:90:ab dev br0; echo $?
> > 0
> > # bridge fdb show
> > ...
> > 12:34:56:78:90:ab dev enp3s0 master br0 permanent
> >
> > After:
> > # bridge fdb add 12:34:56:78:90:ab dev enp3s0 master
> > # bridge fdb add 12:34:56:78:90:ab dev br0; echo $?
> > RTNETLINK answers: File exists
> > 255
> >
> > # bridge fdb replace 12:34:56:78:90:ab dev br0; echo $?
> > 0
> > # bridge fdb show
> > ...
> > 12:34:56:78:90:ab dev br0 master br0 permanent
> >  
> ok, thanks for the example.
> 
> Acked-by: Roopa Prabhu 

It should be possible to manually add fdb entries with any combination
of valid flags. That is it should be possible to add temporary as well as 
permanent
entries. There are people that use this facility to do long and short ageing 
temporary
entries.


Re: [PATCH iproute v2 2/5] ila: Support for configuring ila to use netfilter hook

2016-08-06 Thread Stephen Hemminger
I have no problem with this series in general and wanted to put it in before
closing the lid on 4.7 version, BUT.

This patch generates warnings when built on Debian Strech with gcc-5
 
ipila.c: In function ‘ila_parse_opt.constprop’:
ipila.c:205:2: warning: ‘locator_match’ may be used uninitialized in this 
function [-Wmaybe-uninitialized]
  addattr64(n, 1024, ILA_ATTR_LOCATOR_MATCH, locator_match);

if (matches(*argv, "add") == 0)
> + return do_add(argc-1, argv+1);
> + if (matches(*argv, "delete") == 0)
> + return do_del(argc-1, argv+1);
> + if (matches(*argv, "list") == 0)
> + return do_list(argc-1, argv+1);
> + if (matches(*argv, "help") == 0)
> + usage();
> +
> + fprintf(stderr, "Command \"%s\" is unknown, try \"ip ila help\".\n",
> + *argv);
> + exit(-1);
> +}
> +

You also added a blank line at end of file.

Please fix this and resubmit the series.


Re: [PATCH v2 12/14] net: ethernet: ti: cpsw: fix int dbg message

2016-08-06 Thread Joe Perches
On Sat, 2016-08-06 at 13:48 +0300, Ivan Khoronzhuk wrote:
> While poll handlers there is no possibility to figure out
> which network device is handling packets, as cpdma channels
> are common for both network devices in dual_emac mode. Currently,
> the messages are printed only for one device, in fact, there is two.
> So, better to print integrated num_tx value for both devices if
> any of them is allowed to.
[]
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
[]
> @@ -378,6 +378,7 @@ struct cpsw_common {
>   boolrx_irq_disabled;
>   booltx_irq_disabled;
>   u32 irqs_table[IRQ_NUM];
> + int intr_dbg_msg;

Looks like this should be bool and should
be placed after tx_irq_disabled

[]

> @@ -1848,8 +1853,35 @@ static u32 cpsw_get_msglevel(struct net_device *ndev)
>  
>  static void cpsw_set_msglevel(struct net_device *ndev, u32 value)
>  {
> + int i;
> + struct cpsw_priv *sl_priv;
>   struct cpsw_priv *priv = netdev_priv(ndev);
> + struct cpsw_common *cpsw = priv->cpsw;
> +
>   priv->msg_enable = value;
> +
> + /* There is no possibility to at napi poll level
> +  * to know which netdev is handled, so enable
> +  * common dbg msg print if any interface is enabled to

to? too?

> +  */
> + cpsw->intr_dbg_msg = 0;
> + if (!cpsw->data.dual_emac) {
> + if (netif_msg_intr(priv))
> + cpsw->intr_dbg_msg = 1;
> + return;
> + }
> +
> + for (i = 0; i < cpsw->data.slaves; i++) {
> + ndev = netdev_priv(cpsw->slaves[i].ndev);
> + if (!ndev)
> + continue;
> +
> + sl_priv = netdev_priv(ndev);
> + if (netif_msg_intr(sl_priv)) {
> + cpsw->intr_dbg_msg = 1;
> + break;
> + }
> + }
>  }
>  
>  static int cpsw_get_ts_info(struct net_device *ndev,


[PATCH v2 09/14] net: ethernet: ti: cpsw: move cpdma resources to cpsw_common

2016-08-06 Thread Ivan Khoronzhuk
Every net device private struct holds links to shared cpdma resources.
No need to save and every time synchronize these resources per net dev.
So, move it to common driver struct.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 97 +-
 1 file changed, 48 insertions(+), 49 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 6fc22df..d3af373 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -369,6 +369,8 @@ struct cpsw_common {
struct cpsw_wr_regs __iomem *wr_regs;
u8 __iomem  *hw_stats;
struct cpsw_host_regs __iomem   *host_port_regs;
+   struct cpdma_ctlr   *dma;
+   struct cpdma_chan   *txch, *rxch;
 };
 
 struct cpsw_priv {
@@ -384,8 +386,6 @@ struct cpsw_priv {
int rx_packet_max;
u8  mac_addr[ETH_ALEN];
struct cpsw_slave   *slaves;
-   struct cpdma_ctlr   *dma;
-   struct cpdma_chan   *txch, *rxch;
struct cpsw_ale *ale;
boolrx_pause;
booltx_pause;
@@ -656,25 +656,21 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
}
 }
 
-static void cpsw_intr_enable(struct cpsw_priv *priv)
+static void cpsw_intr_enable(struct cpsw_common *cpsw)
 {
-   struct cpsw_common *cpsw = priv->cpsw;
-
__raw_writel(0xFF, >wr_regs->tx_en);
__raw_writel(0xFF, >wr_regs->rx_en);
 
-   cpdma_ctlr_int_ctrl(priv->dma, true);
+   cpdma_ctlr_int_ctrl(cpsw->dma, true);
return;
 }
 
-static void cpsw_intr_disable(struct cpsw_priv *priv)
+static void cpsw_intr_disable(struct cpsw_common *cpsw)
 {
-   struct cpsw_common *cpsw = priv->cpsw;
-
__raw_writel(0, >wr_regs->tx_en);
__raw_writel(0, >wr_regs->rx_en);
 
-   cpdma_ctlr_int_ctrl(priv->dma, false);
+   cpdma_ctlr_int_ctrl(cpsw->dma, false);
return;
 }
 
@@ -702,6 +698,7 @@ static void cpsw_rx_handler(void *token, int len, int 
status)
struct net_device   *ndev = skb->dev;
struct cpsw_priv*priv = netdev_priv(ndev);
int ret = 0;
+   struct cpsw_common  *cpsw = priv->cpsw;
 
cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
 
@@ -747,8 +744,8 @@ static void cpsw_rx_handler(void *token, int len, int 
status)
}
 
 requeue:
-   ret = cpdma_chan_submit(priv->rxch, new_skb, new_skb->data,
-   skb_tailroom(new_skb), 0);
+   ret = cpdma_chan_submit(cpsw->rxch, new_skb, new_skb->data,
+   skb_tailroom(new_skb), 0);
if (WARN_ON(ret < 0))
dev_kfree_skb_any(new_skb);
 }
@@ -759,7 +756,7 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
struct cpsw_common *cpsw = priv->cpsw;
 
writel(0, >wr_regs->tx_en);
-   cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
+   cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_TX);
 
if (priv->quirk_irq) {
disable_irq_nosync(priv->irqs_table[1]);
@@ -775,7 +772,7 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
struct cpsw_priv *priv = dev_id;
struct cpsw_common *cpsw = priv->cpsw;
 
-   cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
+   cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX);
writel(0, >wr_regs->rx_en);
 
if (priv->quirk_irq) {
@@ -793,7 +790,7 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int 
budget)
int num_tx;
struct cpsw_common  *cpsw = priv->cpsw;
 
-   num_tx = cpdma_chan_process(priv->txch, budget);
+   num_tx = cpdma_chan_process(cpsw->txch, budget);
if (num_tx < budget) {
napi_complete(napi_tx);
writel(0xff, >wr_regs->tx_en);
@@ -813,7 +810,7 @@ static int cpsw_rx_poll(struct napi_struct *napi_rx, int 
budget)
int num_rx;
struct cpsw_common  *cpsw = priv->cpsw;
 
-   num_rx = cpdma_chan_process(priv->rxch, budget);
+   num_rx = cpdma_chan_process(cpsw->rxch, budget);
if (num_rx < budget) {
napi_complete(napi_rx);
writel(0xff, >wr_regs->rx_en);
@@ -1024,17 +1021,16 @@ static void cpsw_get_strings(struct net_device *ndev, 
u32 stringset, u8 *data)
 static void cpsw_get_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data)
 {
-   struct cpsw_priv *priv = netdev_priv(ndev);
struct cpdma_chan_stats rx_stats;
struct cpdma_chan_stats tx_stats;
u32 val;
u8 *p;
int i;
-   struct cpsw_common *cpsw = priv->cpsw;
+   struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
 
/* 

[PATCH v2 11/14] net: ethernet: ti: cpsw: move data platform data and slaves info to cpsw_common

2016-08-06 Thread Ivan Khoronzhuk
These data are common per net dev. No need to hold it in every priv
instance, so move them under cpsw_common.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 271 +
 1 file changed, 140 insertions(+), 131 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4080487..29ff489 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -140,9 +140,9 @@ do {
\
 #define CPSW_CMINTMAX_INTVL(1000 / CPSW_CMINTMIN_CNT)
 #define CPSW_CMINTMIN_INTVL((1000 / CPSW_CMINTMAX_CNT) + 1)
 
-#define cpsw_slave_index(priv) \
-   ((priv->data.dual_emac) ? priv->emac_port : \
-   priv->data.active_slave)
+#define cpsw_slave_index(cpsw, priv)   \
+   ((cpsw->data.dual_emac) ? priv->emac_port : \
+   cpsw->data.active_slave)
 #define IRQ_NUM2
 
 static int debug_level;
@@ -366,10 +366,12 @@ static inline void slave_write(struct cpsw_slave *slave, 
u32 val, u32 offset)
 
 struct cpsw_common {
struct device   *dev;
+   struct cpsw_platform_data   data;
struct cpsw_ss_regs __iomem *regs;
struct cpsw_wr_regs __iomem *wr_regs;
u8 __iomem  *hw_stats;
struct cpsw_host_regs __iomem   *host_port_regs;
+   struct cpsw_slave   *slaves;
struct cpdma_ctlr   *dma;
struct cpdma_chan   *txch, *rxch;
boolquirk_irq;
@@ -383,14 +385,12 @@ struct cpsw_priv {
struct napi_struct  napi_rx;
struct napi_struct  napi_tx;
struct device   *dev;
-   struct cpsw_platform_data   data;
u32 msg_enable;
u32 version;
u32 coal_intvl;
u32 bus_freq_mhz;
int rx_packet_max;
u8  mac_addr[ETH_ALEN];
-   struct cpsw_slave   *slaves;
struct cpsw_ale *ale;
boolrx_pause;
booltx_pause;
@@ -492,40 +492,41 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
 #define for_each_slave(priv, func, arg...) \
do {\
struct cpsw_slave *slave;   \
+   struct cpsw_common *cpsw = (priv)->cpsw;\
int n;  \
-   if (priv->data.dual_emac)   \
-   (func)((priv)->slaves + priv->emac_port, ##arg);\
+   if (cpsw->data.dual_emac)   \
+   (func)((cpsw)->slaves + priv->emac_port, ##arg);\
else\
-   for (n = (priv)->data.slaves,   \
-   slave = (priv)->slaves; \
+   for (n = cpsw->data.slaves, \
+   slave = cpsw->slaves;   \
n; n--) \
(func)(slave++, ##arg); \
} while (0)
-#define cpsw_get_slave_ndev(priv, __slave_no__)
\
-   priv->slaves[__slave_no__].ndev
-#define cpsw_get_slave_priv(priv, __slave_no__)
\
-   (((__slave_no__ < priv->data.slaves) && \
-   (priv->slaves[__slave_no__].ndev)) ?\
-   netdev_priv(priv->slaves[__slave_no__].ndev) : NULL)\
-
-#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb)
\
+#define cpsw_get_slave_ndev(cpsw, __slave_no__)
\
+   cpsw->slaves[__slave_no__].ndev
+#define cpsw_get_slave_priv(cpsw, __slave_no__)
\
+   (((__slave_no__ < cpsw->data.slaves) && \
+   (cpsw->slaves[__slave_no__].ndev)) ?\
+   netdev_priv(cpsw->slaves[__slave_no__].ndev) : NULL)\
+
+#define cpsw_dual_emac_src_port_detect(cpsw, status, priv, ndev, skb)  \
do {\
-   if (!priv->data.dual_emac)  \
+   if (!cpsw->data.dual_emac) 

[PATCH net 1/2] net: vxlan: lwt: Use source ip address during route lookup.

2016-08-06 Thread Pravin B Shelar
LWT user can specify destination as well as source ip address
for given tunnel endpoint. But vxlan is ignoring given source
ip address. Following patch uses both ip address to route the
tunnel packet. This consistent with other LWT implementations,
like GENEVE and GRE.

Fixes: ee122c79d42 ("vxlan: Flow based tunneling").
Signed-off-by: Pravin B Shelar 
---
 drivers/net/vxlan.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index da4e3d6..b812234 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1811,7 +1811,7 @@ static struct rtable *vxlan_get_route(struct vxlan_dev 
*vxlan,
fl4.flowi4_mark = skb->mark;
fl4.flowi4_proto = IPPROTO_UDP;
fl4.daddr = daddr;
-   fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr;
+   fl4.saddr = *saddr;
 
rt = ip_route_output_key(vxlan->net, );
if (!IS_ERR(rt)) {
@@ -1847,7 +1847,7 @@ static struct dst_entry *vxlan6_get_route(struct 
vxlan_dev *vxlan,
memset(, 0, sizeof(fl6));
fl6.flowi6_oif = oif;
fl6.daddr = *daddr;
-   fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
+   fl6.saddr = *saddr;
fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
fl6.flowi6_mark = skb->mark;
fl6.flowi6_proto = IPPROTO_UDP;
@@ -1920,7 +1920,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
struct rtable *rt = NULL;
const struct iphdr *old_iph;
union vxlan_addr *dst;
-   union vxlan_addr remote_ip;
+   union vxlan_addr remote_ip, local_ip;
+   union vxlan_addr *src;
struct vxlan_metadata _md;
struct vxlan_metadata *md = &_md;
__be16 src_port = 0, dst_port;
@@ -1938,6 +1939,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
dst_port = rdst->remote_port ? rdst->remote_port : 
vxlan->cfg.dst_port;
vni = rdst->remote_vni;
dst = >remote_ip;
+   src = >cfg.saddr;
dst_cache = >dst_cache;
} else {
if (!info) {
@@ -1948,11 +1950,15 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
vni = vxlan_tun_id_to_vni(info->key.tun_id);
remote_ip.sa.sa_family = ip_tunnel_info_af(info);
-   if (remote_ip.sa.sa_family == AF_INET)
+   if (remote_ip.sa.sa_family == AF_INET) {
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
-   else
+   local_ip.sin.sin_addr.s_addr = info->key.u.ipv4.src;
+   } else {
remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
+   local_ip.sin6.sin6_addr = info->key.u.ipv6.src;
+   }
dst = _ip;
+   src = _ip;
dst_cache = >dst_cache;
}
 
@@ -1992,15 +1998,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
}
 
if (dst->sa.sa_family == AF_INET) {
-   __be32 saddr;
-
if (!vxlan->vn4_sock)
goto drop;
sk = vxlan->vn4_sock->sock->sk;
 
rt = vxlan_get_route(vxlan, skb,
 rdst ? rdst->remote_ifindex : 0, tos,
-dst->sin.sin_addr.s_addr, ,
+dst->sin.sin_addr.s_addr,
+>sin.sin_addr.s_addr,
 dst_cache, info);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n",
@@ -2043,13 +2048,12 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
if (err < 0)
goto xmit_tx_error;
 
-   udp_tunnel_xmit_skb(rt, sk, skb, saddr,
+   udp_tunnel_xmit_skb(rt, sk, skb, src->sin.sin_addr.s_addr,
dst->sin.sin_addr.s_addr, tos, ttl, df,
src_port, dst_port, xnet, !udp_sum);
 #if IS_ENABLED(CONFIG_IPV6)
} else {
struct dst_entry *ndst;
-   struct in6_addr saddr;
u32 rt6i_flags;
 
if (!vxlan->vn6_sock)
@@ -2058,7 +2062,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
 
ndst = vxlan6_get_route(vxlan, skb,
rdst ? rdst->remote_ifindex : 0, tos,
-   label, >sin6.sin6_addr, ,
+   label, >sin6.sin6_addr,
+   >sin6.sin6_addr,
dst_cache, info);
if (IS_ERR(ndst)) {
   

[PATCH v2 12/14] net: ethernet: ti: cpsw: fix int dbg message

2016-08-06 Thread Ivan Khoronzhuk
While poll handlers there is no possibility to figure out
which network device is handling packets, as cpdma channels
are common for both network devices in dual_emac mode. Currently,
the messages are printed only for one device, in fact, there is two.
So, better to print integrated num_tx value for both devices if
any of them is allowed to.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 36 ++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 29ff489..395531d 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -378,6 +378,7 @@ struct cpsw_common {
boolrx_irq_disabled;
booltx_irq_disabled;
u32 irqs_table[IRQ_NUM];
+   int intr_dbg_msg;
 };
 
 struct cpsw_priv {
@@ -802,7 +803,9 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int 
budget)
}
}
 
-   cpsw_dbg(priv, intr, "poll %d tx pkts\n", num_tx);
+   if (cpsw->intr_dbg_msg && net_ratelimit())
+   dev_dbg(cpsw->dev, "poll %d tx pkts\n", num_tx);
+
return num_tx;
 }
 
@@ -822,7 +825,9 @@ static int cpsw_rx_poll(struct napi_struct *napi_rx, int 
budget)
}
}
 
-   cpsw_dbg(priv, intr, "poll %d rx pkts\n", num_rx);
+   if (cpsw->intr_dbg_msg && net_ratelimit())
+   dev_dbg(cpsw->dev, "poll %d tx pkts\n", num_rx);
+
return num_rx;
 }
 
@@ -1848,8 +1853,35 @@ static u32 cpsw_get_msglevel(struct net_device *ndev)
 
 static void cpsw_set_msglevel(struct net_device *ndev, u32 value)
 {
+   int i;
+   struct cpsw_priv *sl_priv;
struct cpsw_priv *priv = netdev_priv(ndev);
+   struct cpsw_common *cpsw = priv->cpsw;
+
priv->msg_enable = value;
+
+   /* There is no possibility to at napi poll level
+* to know which netdev is handled, so enable
+* common dbg msg print if any interface is enabled to
+*/
+   cpsw->intr_dbg_msg = 0;
+   if (!cpsw->data.dual_emac) {
+   if (netif_msg_intr(priv))
+   cpsw->intr_dbg_msg = 1;
+   return;
+   }
+
+   for (i = 0; i < cpsw->data.slaves; i++) {
+   ndev = netdev_priv(cpsw->slaves[i].ndev);
+   if (!ndev)
+   continue;
+
+   sl_priv = netdev_priv(ndev);
+   if (netif_msg_intr(sl_priv)) {
+   cpsw->intr_dbg_msg = 1;
+   break;
+   }
+   }
 }
 
 static int cpsw_get_ts_info(struct net_device *ndev,
-- 
1.9.1



[PATCH net 2/2] net: vxlan: lwt: Fix vxlan local traffic.

2016-08-06 Thread Pravin B Shelar
vxlan driver has bypass for local vxlan traffic, but that
depends on information about all VNIs on local system in
vxlan driver. This is not available in case of LWT.
Therefore following patch disable encap bypass for LWT
vxlan traffic.

Fixes: ee122c79d42 ("vxlan: Flow based tunneling").
Reported-by: Jakub Libosvar 
Signed-off-by: Pravin B Shelar 
---
 drivers/net/vxlan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index b812234..c0dda6f 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2022,7 +2022,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
}
 
/* Bypass encapsulation if the destination is local */
-   if (rt->rt_flags & RTCF_LOCAL &&
+   if (!info && rt->rt_flags & RTCF_LOCAL &&
!(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
struct vxlan_dev *dst_vxlan;
 
@@ -2082,7 +2082,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
 
/* Bypass encapsulation if the destination is local */
rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
-   if (rt6i_flags & RTF_LOCAL &&
+   if (!info && rt6i_flags & RTF_LOCAL &&
!(rt6i_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
struct vxlan_dev *dst_vxlan;
 
-- 
1.9.1



[PATCH v2 06/14] net: ethernet: ti: cpsw: create common struct to hold shared driver data

2016-08-06 Thread Ivan Khoronzhuk
This patch simply create holder for common data and as a start moves
pdev var to it.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 62 ++
 1 file changed, 39 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 19aa4bb..ac875b3 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -363,8 +363,11 @@ static inline void slave_write(struct cpsw_slave *slave, 
u32 val, u32 offset)
__raw_writel(val, slave->regs + offset);
 }
 
-struct cpsw_priv {
+struct cpsw_common {
struct platform_device  *pdev;
+};
+
+struct cpsw_priv {
struct net_device   *ndev;
struct napi_struct  napi_rx;
struct napi_struct  napi_tx;
@@ -394,6 +397,7 @@ struct cpsw_priv {
u32 num_irqs;
struct cpts *cpts;
u32 emac_port;
+   struct cpsw_common *cpsw;
 };
 
 struct cpsw_stats {
@@ -484,6 +488,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
 
 #define CPSW_STATS_LEN ARRAY_SIZE(cpsw_gstrings_stats)
 
+#define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)
 #define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi)
 #define for_each_slave(priv, func, arg...) \
do {\
@@ -1095,6 +1100,7 @@ static void soft_reset_slave(struct cpsw_slave *slave)
 static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
u32 slave_port;
+   struct cpsw_common *cpsw = priv->cpsw;
 
soft_reset_slave(slave);
 
@@ -1153,7 +1159,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, 
struct cpsw_priv *priv)
phy_start(slave->phy);
 
/* Configure GMII_SEL register */
-   cpsw_phy_sel(>pdev->dev, slave->phy->interface, slave->slave_num);
+   cpsw_phy_sel(>pdev->dev, slave->phy->interface, slave->slave_num);
 }
 
 static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
@@ -1235,12 +1241,13 @@ static void cpsw_slave_stop(struct cpsw_slave *slave, 
struct cpsw_priv *priv)
 static int cpsw_ndo_open(struct net_device *ndev)
 {
struct cpsw_priv *priv = netdev_priv(ndev);
+   struct cpsw_common *cpsw = priv->cpsw;
int i, ret;
u32 reg;
 
-   ret = pm_runtime_get_sync(>pdev->dev);
+   ret = pm_runtime_get_sync(>pdev->dev);
if (ret < 0) {
-   pm_runtime_put_noidle(>pdev->dev);
+   pm_runtime_put_noidle(>pdev->dev);
return ret;
}
 
@@ -1317,7 +1324,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 */
cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
-   if (cpts_register(>pdev->dev, priv->cpts,
+   if (cpts_register(>pdev->dev, priv->cpts,
  priv->data.cpts_clock_mult,
  priv->data.cpts_clock_shift))
dev_err(priv->dev, "error registering cpts device\n");
@@ -1342,7 +1349,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 err_cleanup:
cpdma_ctlr_stop(priv->dma);
for_each_slave(priv, cpsw_slave_stop, priv);
-   pm_runtime_put_sync(>pdev->dev);
+   pm_runtime_put_sync(>pdev->dev);
netif_carrier_off(priv->ndev);
return ret;
 }
@@ -1350,6 +1357,7 @@ err_cleanup:
 static int cpsw_ndo_stop(struct net_device *ndev)
 {
struct cpsw_priv *priv = netdev_priv(ndev);
+   struct cpsw_common *cpsw = priv->cpsw;
 
cpsw_info(priv, ifdown, "shutting down cpsw device\n");
netif_stop_queue(priv->ndev);
@@ -1366,7 +1374,7 @@ static int cpsw_ndo_stop(struct net_device *ndev)
cpsw_ale_stop(priv->ale);
}
for_each_slave(priv, cpsw_slave_stop, priv);
-   pm_runtime_put_sync(>pdev->dev);
+   pm_runtime_put_sync(>pdev->dev);
if (priv->data.dual_emac)
priv->slaves[priv->emac_port].open_stat = false;
return 0;
@@ -1598,6 +1606,7 @@ static int cpsw_ndo_set_mac_address(struct net_device 
*ndev, void *p)
 {
struct cpsw_priv *priv = netdev_priv(ndev);
struct sockaddr *addr = (struct sockaddr *)p;
+   struct cpsw_common *cpsw = priv->cpsw;
int flags = 0;
u16 vid = 0;
int ret;
@@ -1605,9 +1614,9 @@ static int cpsw_ndo_set_mac_address(struct net_device 
*ndev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
 
-   ret = pm_runtime_get_sync(>pdev->dev);
+   ret = pm_runtime_get_sync(>pdev->dev);
if (ret < 0) {
-   pm_runtime_put_noidle(>pdev->dev);
+   pm_runtime_put_noidle(>pdev->dev);
return ret;
}
 
@@ -1625,7 +1634,7 @@ static int cpsw_ndo_set_mac_address(struct 

[PATCH v2 14/14] net: ethernet: ti: cpsw: move ale, cpts and drivers params under cpsw_common

2016-08-06 Thread Ivan Khoronzhuk
The ale, cpts, version, limit, freq, interrupt pacing parameters
are common per net device that uses the same h/w. So, move them to
common driver structure.

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c | 237 ++---
 1 file changed, 106 insertions(+), 131 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index e0a1b80..bd0ea71 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -373,13 +373,19 @@ struct cpsw_common {
struct cpsw_wr_regs __iomem *wr_regs;
u8 __iomem  *hw_stats;
struct cpsw_host_regs __iomem   *host_port_regs;
+   u32 version;
+   u32 coal_intvl;
+   u32 bus_freq_mhz;
+   int rx_packet_max;
struct cpsw_slave   *slaves;
struct cpdma_ctlr   *dma;
struct cpdma_chan   *txch, *rxch;
+   struct cpsw_ale *ale;
boolquirk_irq;
boolrx_irq_disabled;
booltx_irq_disabled;
u32 irqs_table[IRQ_NUM];
+   struct cpts *cpts;
int intr_dbg_msg;
 };
 
@@ -387,15 +393,9 @@ struct cpsw_priv {
struct net_device   *ndev;
struct device   *dev;
u32 msg_enable;
-   u32 version;
-   u32 coal_intvl;
-   u32 bus_freq_mhz;
-   int rx_packet_max;
u8  mac_addr[ETH_ALEN];
-   struct cpsw_ale *ale;
boolrx_pause;
booltx_pause;
-   struct cpts *cpts;
u32 emac_port;
struct cpsw_common *cpsw;
 };
@@ -505,22 +505,16 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
} while (0)
 #define cpsw_get_slave_ndev(cpsw, __slave_no__)
\
cpsw->slaves[__slave_no__].ndev
-#define cpsw_get_slave_priv(cpsw, __slave_no__)
\
-   (((__slave_no__ < cpsw->data.slaves) && \
-   (cpsw->slaves[__slave_no__].ndev)) ?\
-   netdev_priv(cpsw->slaves[__slave_no__].ndev) : NULL)\
 
-#define cpsw_dual_emac_src_port_detect(cpsw, status, priv, ndev, skb)  \
+#define cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb)
\
do {\
if (!cpsw->data.dual_emac)  \
break;  \
if (CPDMA_RX_SOURCE_PORT(status) == 1) {\
ndev = cpsw_get_slave_ndev(cpsw, 0);\
-   priv = netdev_priv(ndev);   \
skb->dev = ndev;\
} else if (CPDMA_RX_SOURCE_PORT(status) == 2) { \
ndev = cpsw_get_slave_ndev(cpsw, 1);\
-   priv = netdev_priv(ndev);   \
skb->dev = ndev;\
}   \
} while (0)
@@ -531,11 +525,11 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
priv->emac_port;\
int slave_port = cpsw_get_slave_port(   \
slave->slave_num);  \
-   cpsw_ale_add_mcast(priv->ale, addr, \
+   cpsw_ale_add_mcast(cpsw->ale, addr, \
1 << slave_port | ALE_PORT_HOST,\
ALE_VLAN, slave->port_vlan, 0); \
} else {\
-   cpsw_ale_add_mcast(priv->ale, addr, \
+   cpsw_ale_add_mcast(cpsw->ale, addr, \
ALE_ALL_PORTS,  \
0, 0, 0);   \
}   \
@@ -548,9 +542,8 @@ static inline int cpsw_get_slave_port(u32 slave_num)
 
 static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
 {
-   struct cpsw_priv *priv = netdev_priv(ndev);
-   struct