Re: regression (4.10) - interface remove uevents not generated

2017-03-11 Thread Andrei Vagin
On Sat, Mar 11, 2017 at 11:24:34PM +0200, Mantas Mikulėnas wrote:
> On 2017-03-11 21:50, Andrei Vagin wrote:
> > Hi Mantas,
> > 
> > Thank you for the report. Could you try out the attached patch?
> 
> Thanks, I tested it on current master but it doesn't seem to help; there
> still aren't any uevents for removed interfaces.

I reproduced the issue on my host and the correct patch is attached to
this message. Thanks!

> 
> -- 
> Mantas Mikulėnas 
> 
>From 456e28813d40f2076d4b9346fe8633c83b7a19d8 Mon Sep 17 00:00:00 2001
From: Andrei Vagin 
Date: Sat, 11 Mar 2017 15:18:25 -0800
Subject: [PATCH] net: check net->count to check whether a netns is alive or
 not

The previous idea was to check whether a net namespace is in
net_exit_list or not. It doesn't work, because net->exit_list is used in
__register_pernet_operations and __unregister_pernet_operations where
all namespaces are added to a temporary list to make cleanup in error
cases, so list_empty(>exit_list) always returns false.

Fixes: 002d8a1a6c11 ("net: skip genenerating uevents for network namespaces 
that are exiting")
Signed-off-by: Andrei Vagin 
---
 net/core/net-sysfs.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b0c04cf..1004418 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -952,7 +952,7 @@ net_rx_queue_update_kobjects(struct net_device *dev, int 
old_num, int new_num)
while (--i >= new_num) {
struct kobject *kobj = >_rx[i].kobj;
 
-   if (!list_empty(_net(dev)->exit_list))
+   if (!atomic_read(_net(dev)->count))
kobj->uevent_suppress = 1;
if (dev->sysfs_rx_queue_group)
sysfs_remove_group(kobj, dev->sysfs_rx_queue_group);
@@ -1370,7 +1370,7 @@ netdev_queue_update_kobjects(struct net_device *dev, int 
old_num, int new_num)
while (--i >= new_num) {
struct netdev_queue *queue = dev->_tx + i;
 
-   if (!list_empty(_net(dev)->exit_list))
+   if (!atomic_read(_net(dev)->count))
queue->kobj.uevent_suppress = 1;
 #ifdef CONFIG_BQL
sysfs_remove_group(>kobj, _group);
@@ -1557,7 +1557,7 @@ void netdev_unregister_kobject(struct net_device *ndev)
 {
struct device *dev = &(ndev->dev);
 
-   if (!list_empty(_net(ndev)->exit_list))
+   if (!atomic_read(_net(ndev)->count))
dev_set_uevent_suppress(dev, 1);
 
kobject_get(>kobj);
-- 
2.9.3



Re: [PATCH 2/5] rds: ib: replace spin_lock_irq with spin_lock_irqsave

2017-03-11 Thread santosh.shilim...@oracle.com

On 3/11/17 6:33 PM, Yanjun Zhu wrote:

Sorry. I have no test case to show some issue.
But from Linux Kernel Development Second Edition by Robert Love.


Yes I know the book and what the API does :D


Use spin_lock_irq is dangerous since spin_unlock_irq unconditionally
enables interrupts.

We can assume the following scenario:

--->the interrupt is disabled.

spin_lock_irq(lock_ptr);   <---this will disable interrupt again
list_del(>ib_node);
spin_unlock_irq(lock_ptr); <---this will enable interrupt

>the interrupt is enabled.

our code change the state of interrupt. This will make potential risk.
But spin_lock_irqsave/spin_unlock_irqrestore will not make potential risk.


ic is well protected for any possible race and hence I asked
if you had any test case. Please re-post the series again with
the subject patch dropper for Dave to pick it up.

Regards,
Santosh


[net-next:master 38/46] drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:1548:36: error: 'IEEE_8021QAZ_MAX_TCS' undeclared

2017-03-11 Thread kbuild test robot
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 
master
head:   01461abe62df44844efc5a57f9a365270a7c0299
commit: 65e0ace2c5cdd7aa898fea17d6e7bdc909394bf9 [38/46] net: dwc-xlgmac: 
Initial driver for DesignWare Enterprise Ethernet
config: i386-randconfig-x0-03121309 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
git checkout 65e0ace2c5cdd7aa898fea17d6e7bdc909394bf9
# save the attached .config to linux build tree
make ARCH=i386 

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

   In file included from include/linux/list.h:8:0,
from include/linux/preempt.h:10,
from include/linux/spinlock.h:50,
from include/linux/phy.h:20,
from drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:20:
   drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c: In function 
'xlgmac_config_queue_mapping':
>> drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:1548:36: error: 
>> 'IEEE_8021QAZ_MAX_TCS' undeclared (first use in this function)
 prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
   ^
   include/linux/kernel.h:753:13: note: in definition of macro '__min'
 t1 min1 = (x); \
^
>> drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:1548:16: note: in expansion of 
>> macro 'min_t'
 prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
   ^
   drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:1548:36: note: each undeclared 
identifier is reported only once for each function it appears in
 prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
   ^
   include/linux/kernel.h:753:13: note: in definition of macro '__min'
 t1 min1 = (x); \
^
>> drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:1548:16: note: in expansion of 
>> macro 'min_t'
 prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
   ^

vim +/IEEE_8021QAZ_MAX_TCS +1548 drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c

  1542MTL_Q_TQOMR));
  1543  queue++;
  1544  }
  1545  }
  1546  
  1547  /* Map the 8 VLAN priority values to available MTL Rx queues */
> 1548  prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
  1549  pdata->rx_q_count);
  1550  ppq = IEEE_8021QAZ_MAX_TCS / prio_queues;
  1551  ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues;

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Proposal...

2017-03-11 Thread Teresa Au


Personal Business proposal for you,contact me via my personal E-mail for more 
detail's: 
ms_teresa_a...@outlook.com



Re: [PATCH 2/5] rds: ib: replace spin_lock_irq with spin_lock_irqsave

2017-03-11 Thread Yanjun Zhu

Sorry. I have no test case to show some issue.
But from Linux Kernel Development Second Edition by Robert Love.

Use spin_lock_irq is dangerous since spin_unlock_irq unconditionally 
enables interrupts.


We can assume the following scenario:

--->the interrupt is disabled.

spin_lock_irq(lock_ptr);   <---this will disable interrupt again
list_del(>ib_node);
spin_unlock_irq(lock_ptr); <---this will enable interrupt

>the interrupt is enabled.

our code change the state of interrupt. This will make potential risk.
But spin_lock_irqsave/spin_unlock_irqrestore will not make potential risk.

Zhu Yanjun
On 2017/3/10 0:50, Santosh Shilimkar wrote:

On 3/8/2017 11:26 PM, Zhu Yanjun wrote:

It is difficult to make sure the state of the interrupt when this
function is called. As such, it is safer to use spin_lock_irqsave
than spin_lock_irq.


There is no reason to hold irqs  and as such the code path is
safe from irq context. I don't see need of this change unless
you have test case which showed some issue.

Regards,
Santosh





Re: [PATCH net-next v2 00/17] net: dsa: mv88e6xxx: rework ATU support

2017-03-11 Thread Florian Fainelli
Le 03/11/17 à 13:12, Vivien Didelot a écrit :
> The purpose of this patch series is to rework the code related to the
> Address Translation Unit (ATU), and bring support for it to the 88E6390
> family of switch chips.
> 
> All Global (1) ATU related code have been reworked and moved to its own
> file. Some port related bits used for ATU configuration (such as the
> Learn2All and MessagePort feature) have also been taken care of.
> 
> The ports' mode and egress flooding mode have been refactored to fix the
> egress of frames with unknown unicast or multicast destination address,
> and write all these bits regardless the port mode (Normal, DSA, etc.)
> 
> Finally remove the eth_addr_greater which was only used by mv88e6xxx.

Just some general note on the way the driver seems to be going there
seems to be a multiplication of new ops being introduced, and most of
them seem to default to the mv88e6xxx (generic) ones. Should you do
something like:

if (!ops->foo)
ops->foo = mv88e6xxx_foo

Such that you reduce the possibility for a specific switch model to lack
such an operation?

> 
> Changes in v2:
>   - add Reviewed-by tags
>   - split mv88e6xxx_g1_atu_set_age_time and mv88e6xxx_atu_setup addition
>   - remove DSA_TAG_PROTO_TRAILER check
>   - split Message Port and Learn2All addition
>   - remove unused MV88E6XXX_FLAG_G1_ATU_FID flag
>   - add dsa_is_normal_port helper
> 
> Vivien Didelot (17):
>   net: dsa: mv88e6xxx: add port mask helper
>   net: dsa: mv88e6xxx: move ATU ageing time setter
>   net: dsa: mv88e6xxx: add ATU setup helper
>   net: dsa: mv88e6xxx: setup message ports
>   net: dsa: mv88e6xxx: enable ATU Learn2All
>   net: dsa: mv88e6xxx: rework ATU Load/Purge
>   net: dsa: mv88e6xxx: rework ATU GetNext
>   net: dsa: mv88e6xxx: rework ATU Flush
>   net: dsa: mv88e6xxx: rework ATU Remove
>   net: dsa: mv88e6xxx: rename new FID helper
>   net: dsa: mv88e6xxx: rename the port vector member
>   net: dsa: add dsa_is_normal_port helper
>   net: dsa: mv88e6xxx: rework port mode setup
>   net: dsa: mv88e6xxx: fix port egress flooding mode
>   net: dsa: mv88e6xxx: add port ATU learn limit op
>   net: dsa: mv88e6xxx: add port priority override op
>   etherdevice: remove unused eth_addr_greater
> 
>  drivers/net/dsa/mv88e6xxx/Makefile  |   1 +
>  drivers/net/dsa/mv88e6xxx/chip.c| 667 
> +++-
>  drivers/net/dsa/mv88e6xxx/global1.h |  11 +
>  drivers/net/dsa/mv88e6xxx/global1_atu.c | 300 ++
>  drivers/net/dsa/mv88e6xxx/mv88e6xxx.h   |  44 ++-
>  drivers/net/dsa/mv88e6xxx/port.c|  78 +++-
>  drivers/net/dsa/mv88e6xxx/port.h|  16 +-
>  include/linux/etherdevice.h |  15 -
>  include/net/dsa.h   |   5 +
>  9 files changed, 638 insertions(+), 499 deletions(-)
>  create mode 100644 drivers/net/dsa/mv88e6xxx/global1_atu.c
> 


-- 
Florian


Re: [PATCH net-next v2 12/17] net: dsa: add dsa_is_normal_port helper

2017-03-11 Thread Florian Fainelli
Le 03/11/17 à 13:12, Vivien Didelot a écrit :
> Introduce a dsa_is_normal_port helper to check if a given port is a
> normal user port as opposed to a CPU port or DSA link.

net/dsa/dsa2.c uses the "user" terminology should we use something like
that here?

> 
> Signed-off-by: Vivien Didelot 
> ---
>  include/net/dsa.h | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 4e13e695f025..bf0e42c2a6f7 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -248,6 +248,11 @@ static inline bool dsa_is_dsa_port(struct dsa_switch 
> *ds, int p)
>   return !!((ds->dsa_port_mask) & (1 << p));
>  }
>  
> +static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
> +{
> + return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
> +}
> +
>  static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
>  {
>   return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
> 


-- 
Florian


[Patch net-next] atm: remove an unnecessary loop

2017-03-11 Thread Chas Williams
From: Francois Romieu 

Andrey reported this kernel warning:

WARNING: CPU: 0 PID: 4114 at kernel/sched/core.c:7737 __might_sleep+0x149/0x1a0
do not call blocking ops when !TASK_RUNNING; state=1 set at
[] prepare_to_wait+0x182/0x530

The deeply nested alloc_skb is a problem.

Diagnosis: nesting is wrong. It makes zero sense. Fix it and the
implicit task state change problem automagically goes away.

alloc_skb() does not need to be in the "while" loop.

alloc_skb() does not need to be in the {prepare_to_wait/add_wait_queue ...
finish_wait/remove_wait_queue} block.

I claim that:
- alloc_tx() should only perform the "wait_for_decent_tx_drain" part
- alloc_skb() ought to be done directly in vcc_sendmsg
- alloc_skb() failure can be handled gracefully in vcc_sendmsg
- alloc_skb() may use a (m->msg_flags & MSG_DONTWAIT) dependent
  GFP_{KERNEL / ATOMIC} flag

Reported-by: Andrey Konovalov 
Reviewed-and-Tested-by: Chas Williams <3ch...@gmail.com>
Signed-off-by: Chas Williams <3ch...@gmail.com>
---
 net/atm/common.c | 22 +-
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/net/atm/common.c b/net/atm/common.c
index 9613381..f06422f 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -62,21 +62,16 @@ static void vcc_remove_socket(struct sock *sk)
write_unlock_irq(_sklist_lock);
 }
 
-static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
+static bool vcc_tx_ready(struct atm_vcc *vcc, unsigned int size)
 {
-   struct sk_buff *skb;
struct sock *sk = sk_atm(vcc);
 
if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {
pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
 sk_wmem_alloc_get(sk), size, sk->sk_sndbuf);
-   return NULL;
+   return false;
}
-   while (!(skb = alloc_skb(size, GFP_KERNEL)))
-   schedule();
-   pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
-   atomic_add(skb->truesize, >sk_wmem_alloc);
-   return skb;
+   return true;
 }
 
 static void vcc_sock_destruct(struct sock *sk)
@@ -606,7 +601,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, 
size_t size)
eff = (size+3) & ~3; /* align to word boundary */
prepare_to_wait(sk_sleep(sk), , TASK_INTERRUPTIBLE);
error = 0;
-   while (!(skb = alloc_tx(vcc, eff))) {
+   while (!vcc_tx_ready(vcc, eff)) {
if (m->msg_flags & MSG_DONTWAIT) {
error = -EAGAIN;
break;
@@ -628,6 +623,15 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, 
size_t size)
finish_wait(sk_sleep(sk), );
if (error)
goto out;
+
+   skb = alloc_skb(eff, GFP_KERNEL);
+   if (!skb) {
+   error = -ENOMEM;
+   goto out;
+   }
+   pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
+   atomic_add(skb->truesize, >sk_wmem_alloc);
+
skb->dev = NULL; /* for paths shared with net_device interfaces */
ATM_SKB(skb)->atm_options = vcc->atm_options;
if (!copy_from_iter_full(skb_put(skb, size), size, >msg_iter)) {
-- 
2.7.4



Proposal...

2017-03-11 Thread Teresa Au


Personal Business proposal for you,contact me via my personal E-mail for more 
detail's: 
ms_teresa_a...@outlook.com



Re: [PATCH net-next v2 03/17] net: dsa: mv88e6xxx: add ATU setup helper

2017-03-11 Thread Andrew Lunn
On Sat, Mar 11, 2017 at 04:12:49PM -0500, Vivien Didelot wrote:
> Move the configuration of the default ageing time in a new
> mv88e6xxx_atu_setup function.
> 
> That function will be extended later to contain all ATU related
> configuration bits.
> 
> Signed-off-by: Vivien Didelot 

Reviewed-by: Andrew Lunn 

Andrew


Re: [PATCH net-next v2 17/17] etherdevice: remove unused eth_addr_greater

2017-03-11 Thread Andrew Lunn
On Sat, Mar 11, 2017 at 04:13:03PM -0500, Vivien Didelot wrote:
> eth_addr_greater() was introduced for the mv88e6xxx driver, but is not
> used anymore. There is no other user, thus remove this function.
> 
> Signed-off-by: Vivien Didelot 

Reviewed-by: Andrew Lunn 

Andrew


Re: [PATCH net-next v2 12/17] net: dsa: add dsa_is_normal_port helper

2017-03-11 Thread Andrew Lunn
On Sat, Mar 11, 2017 at 04:12:58PM -0500, Vivien Didelot wrote:
> Introduce a dsa_is_normal_port helper to check if a given port is a
> normal user port as opposed to a CPU port or DSA link.
> 
> Signed-off-by: Vivien Didelot 

Reviewed-by: Andrew Lunn 

Andrew


Re: [PATCH net-next 04/14] net: dsa: mv88e6xxx: rework ATU Load/Purge

2017-03-11 Thread Andrew Lunn
> > I really wished you had moved the code, unmodified, into
> > global1_atu.c. Then made lots of easy to review small changes. I
> > cannot just look at this patch and know it is correct. What i need to
> > compare against is not in this patch. So it is a lot harder to review.
> 
> I've addressed all of your comments in this patchset except this one.

Hi Vivien

This time, i'm not going to push the issue further. But next time i
will.

The point is, we have working code. You don't just throw that
away. You make lots of small changes to that working code to morph it
into the code you want. These small changes are all very quick and
easy to review, because they are all small and obvious. At each stage
we have working code. If somehow it does break, it is easy to bisect
it down to one small change. The actual likelyhood of breaking it is
small, because the changes are all small and obviously correct.

It does result in more patches, more to review, but it is much easier
to review, because it should be obviously correct. The overall lines
of code at the end is the same. So overall there is no harm is having
lots of small patches.

> A patch file cannot guarantee that a chunk of code moved around has not
> been altered in the process. This will just generate more diff for no
> value, that needs to be updated afterwards anyway.

I don't need a guarantee. I would trust you have moved it, without
editing it. Generating more diff is not a problem. The number of diffs
is not important at all. What is important is lots of small, easy to
review, obviously correct patches.

> Plus you already complained in the first iteration I sent about
> modifying lines that I previously added. I took care of logically
> splitting the new ATU Load/Purge, GetNext, Flush and Remove operations
> into incremental unmodified chunks in this series.

Unfortunately, you are splitting in the wrong dimension. None of this
is obviously correct. But it easily code of been.

   Andrew


Re: [PATCH] Enable tx timestamping on loopback and dummy

2017-03-11 Thread Lara Gomez, Ezequiel
2 and 3 were recommendations by the checkpatch.pl script; as suggested, I've 
broken them down from the timestamping code and resubmitted as two separate 
patches (on separate emails though).


> On 11 Mar 2017, at 23:17, Oliver Hartkopp  wrote:
> 
> Hi Ezequiel,
> 
>> On 03/11/2017 03:42 PM, Ezequiel Lara Gomez wrote:
>> Also, cleanup some warnings from timestamping code.
> 
> in fact you're doing three different things here:
> 
> 1. introduce tx timestamping
> 2. silently change an include:  -> 
> 3. fix some whitespace and empty line issues
> 
> You'd better provide one patch for 1 & 2 and explain why 2 is needed.
> 
> Regards,
> Oliver
> 
>> 
>> This enables testing of SO_TIMESTAMPING options by targetting localhost
>> addresses.
>> 
>> Tested on qemu using txtimestamping.c from the kernel selftests.
>> 
>> Signed-off-by: Ezequiel Lara Gomez 
>> ---
>> drivers/net/dummy.c|  1 +
>> drivers/net/loopback.c | 14 +++---
>> 2 files changed, 8 insertions(+), 7 deletions(-)
>> 
>> diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
>> index 2c80611..32fdc00 100644
>> --- a/drivers/net/dummy.c
>> +++ b/drivers/net/dummy.c
>> @@ -125,6 +125,7 @@ static netdev_tx_t dummy_xmit(struct sk_buff *skb, 
>> struct net_device *dev)
>>dstats->tx_bytes += skb->len;
>>u64_stats_update_end(>syncp);
>> 
>> +skb_tx_timestamp(skb);
>>dev_kfree_skb(skb);
>>return NETDEV_TX_OK;
>> }
>> diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
>> index b23b719..8bcf479 100644
>> --- a/drivers/net/loopback.c
>> +++ b/drivers/net/loopback.c
>> @@ -13,7 +13,7 @@
>>  *
>>  *Alan Cox:Fixed oddments for NET3.014
>>  *Alan Cox:Rejig for NET3.029 snap #3
>> - *Alan Cox:Fixed NET3.029 bugs and sped up
>> + *Alan Cox:Fixed NET3.029 bugs and sped up
>>  *Larry McVoy:Tiny tweak to double performance
>>  *Alan Cox:Backed out LMV's tweak - the linux mm
>>  *can't take it...
>> @@ -41,7 +41,7 @@
>> #include 
>> 
>> #include 
>> -#include 
>> +#include 
>> 
>> #include 
>> #include 
>> @@ -74,6 +74,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
>>struct pcpu_lstats *lb_stats;
>>int len;
>> 
>> +skb_tx_timestamp(skb);
>>skb_orphan(skb);
>> 
>>/* Before queueing this packet to netif_rx(),
>> @@ -149,8 +150,8 @@ static void loopback_dev_free(struct net_device *dev)
>> }
>> 
>> static const struct net_device_ops loopback_ops = {
>> -.ndo_init  = loopback_dev_init,
>> -.ndo_start_xmit= loopback_xmit,
>> +.ndo_init= loopback_dev_init,
>> +.ndo_start_xmit  = loopback_xmit,
>>.ndo_get_stats64 = loopback_get_stats64,
>>.ndo_set_mac_address = eth_mac_addr,
>> };
>> @@ -170,7 +171,7 @@ static void loopback_setup(struct net_device *dev)
>>dev->priv_flags|= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
>>netif_keep_dst(dev);
>>dev->hw_features= NETIF_F_GSO_SOFTWARE;
>> -dev->features= NETIF_F_SG | NETIF_F_FRAGLIST
>> +dev->features= NETIF_F_SG | NETIF_F_FRAGLIST
>>| NETIF_F_GSO_SOFTWARE
>>| NETIF_F_HW_CSUM
>>| NETIF_F_RXCSUM
>> @@ -206,7 +207,6 @@ static __net_init int loopback_net_init(struct net *net)
>>net->loopback_dev = dev;
>>return 0;
>> 
>> -
>> out_free_netdev:
>>free_netdev(dev);
>> out:
>> @@ -217,5 +217,5 @@ static __net_init int loopback_net_init(struct net *net)
>> 
>> /* Registered in net/core/dev.c */
>> struct pernet_operations __net_initdata loopback_net_ops = {
>> -   .init = loopback_net_init,
>> +.init = loopback_net_init,
>> };
>> 
> 
Amazon Data Services Ireland Limited registered office: One Burlington Plaza, 
Burlington Road, Dublin 4, Ireland. Registered in Ireland. Registration number 
390566.



Re: [PATCH] Enable tx timestamping on loopback and dummy

2017-03-11 Thread Oliver Hartkopp

Hi Ezequiel,

On 03/11/2017 03:42 PM, Ezequiel Lara Gomez wrote:

Also, cleanup some warnings from timestamping code.


in fact you're doing three different things here:

1. introduce tx timestamping
2. silently change an include:  -> 
3. fix some whitespace and empty line issues

You'd better provide one patch for 1 & 2 and explain why 2 is needed.

Regards,
Oliver



This enables testing of SO_TIMESTAMPING options by targetting localhost
addresses.

Tested on qemu using txtimestamping.c from the kernel selftests.

Signed-off-by: Ezequiel Lara Gomez 
---
 drivers/net/dummy.c|  1 +
 drivers/net/loopback.c | 14 +++---
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 2c80611..32fdc00 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -125,6 +125,7 @@ static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct 
net_device *dev)
dstats->tx_bytes += skb->len;
u64_stats_update_end(>syncp);

+   skb_tx_timestamp(skb);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
 }
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b23b719..8bcf479 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -13,7 +13,7 @@
  *
  * Alan Cox:   Fixed oddments for NET3.014
  * Alan Cox:   Rejig for NET3.029 snap #3
- * Alan Cox:   Fixed NET3.029 bugs and sped up
+ * Alan Cox:   Fixed NET3.029 bugs and sped up
  * Larry McVoy :   Tiny tweak to double performance
  * Alan Cox:   Backed out LMV's tweak - the linux mm
  * can't take it...
@@ -41,7 +41,7 @@
 #include 

 #include 
-#include 
+#include 

 #include 
 #include 
@@ -74,6 +74,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
struct pcpu_lstats *lb_stats;
int len;

+   skb_tx_timestamp(skb);
skb_orphan(skb);

/* Before queueing this packet to netif_rx(),
@@ -149,8 +150,8 @@ static void loopback_dev_free(struct net_device *dev)
 }

 static const struct net_device_ops loopback_ops = {
-   .ndo_init  = loopback_dev_init,
-   .ndo_start_xmit= loopback_xmit,
+   .ndo_init= loopback_dev_init,
+   .ndo_start_xmit  = loopback_xmit,
.ndo_get_stats64 = loopback_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
 };
@@ -170,7 +171,7 @@ static void loopback_setup(struct net_device *dev)
dev->priv_flags  |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
netif_keep_dst(dev);
dev->hw_features = NETIF_F_GSO_SOFTWARE;
-   dev->features= NETIF_F_SG | NETIF_F_FRAGLIST
+   dev->features= NETIF_F_SG | NETIF_F_FRAGLIST
| NETIF_F_GSO_SOFTWARE
| NETIF_F_HW_CSUM
| NETIF_F_RXCSUM
@@ -206,7 +207,6 @@ static __net_init int loopback_net_init(struct net *net)
net->loopback_dev = dev;
return 0;

-
 out_free_netdev:
free_netdev(dev);
 out:
@@ -217,5 +217,5 @@ static __net_init int loopback_net_init(struct net *net)

 /* Registered in net/core/dev.c */
 struct pernet_operations __net_initdata loopback_net_ops = {
-   .init = loopback_net_init,
+   .init = loopback_net_init,
 };



Proposal...

2017-03-11 Thread Teresa Au


Personal Business proposal for you,contact me via my personal E-mail for more 
detail's: 
ms_teresa_a...@outlook.com



[no subject]

2017-03-11 Thread Karl Aichniger


-- 

Hi, I appreciate your beauty! can we get to know each other better if you don't 
mind? My name is karl, Can you please tell me a little about yourself so that 
we can get to know each other better?

Best Regards
Karl.



Re: [PATCH net-next v5 0/7] gtp: misc improvements

2017-03-11 Thread Harald Welte
Hi Andreas,

> Andreas Schultz (7):
>   gtp: switch from struct socket to struct sock for the GTP sockets
>   gtp: make GTP sockets in gtp_newlink optional
>   gtp: merge gtp_get_net and gtp_genl_find_dev
>   gtp: consolidate gtp socket rx path
>   gtp: unify genl_find_pdp and prepare for per socket lookup
>   gtp: consolidate pdp context destruction into helper
>   gtp: add socket to pdp context


I agree with the conceptual and architectural direction that you're
taking the code, and I also think your current patchset is good to go
ahead, so feel free to add my "Acked-By: Harald Welte ".

However, the usual disclaimer: I've been out of kernel networking land
for a long time, so my review skills are clearly not the best anymore.
I'm happy for any input others can give from that point of view.

There are some minor typos in the commit logs, but at the rate my typos
increase over the years, I am the last one to complain about wasting
time on fixing these ;)

Regards,
Harald

-- 
- Harald Welte    http://laforge.gnumonks.org/

"Privacy in residential applications is a desirable marketing option."
  (ETSI EN 300 175-7 Ch. A6)


Re: regression (4.10) - interface remove uevents not generated

2017-03-11 Thread Mantas Mikulėnas
On 2017-03-11 21:50, Andrei Vagin wrote:
> Hi Mantas,
> 
> Thank you for the report. Could you try out the attached patch?

Thanks, I tested it on current master but it doesn't seem to help; there
still aren't any uevents for removed interfaces.

-- 
Mantas Mikulėnas 



[PATCH net-next v2 02/17] net: dsa: mv88e6xxx: move ATU ageing time setter

2017-03-11 Thread Vivien Didelot
Move the ATU ageing time setter code in a new global1_atu.c file, which
will be extended in future patches to contains all consequent Global (1)
ATU support code.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/Makefile  |  1 +
 drivers/net/dsa/mv88e6xxx/chip.c| 31 ++--
 drivers/net/dsa/mv88e6xxx/global1.h |  3 +++
 drivers/net/dsa/mv88e6xxx/global1_atu.c | 43 +
 4 files changed, 49 insertions(+), 29 deletions(-)
 create mode 100644 drivers/net/dsa/mv88e6xxx/global1_atu.c

diff --git a/drivers/net/dsa/mv88e6xxx/Makefile 
b/drivers/net/dsa/mv88e6xxx/Makefile
index c36be318de1a..31d37a90cec7 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
 mv88e6xxx-objs := chip.o
 mv88e6xxx-objs += global1.o
+mv88e6xxx-objs += global1_atu.o
 mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
 mv88e6xxx-objs += port.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 03dc886ed3d6..b228b8491afc 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2697,33 +2697,6 @@ static int mv88e6xxx_g1_set_switch_mac(struct 
mv88e6xxx_chip *chip, u8 *addr)
return 0;
 }
 
-static int mv88e6xxx_g1_set_age_time(struct mv88e6xxx_chip *chip,
-unsigned int msecs)
-{
-   const unsigned int coeff = chip->info->age_time_coeff;
-   const unsigned int min = 0x01 * coeff;
-   const unsigned int max = 0xff * coeff;
-   u8 age_time;
-   u16 val;
-   int err;
-
-   if (msecs < min || msecs > max)
-   return -ERANGE;
-
-   /* Round to nearest multiple of coeff */
-   age_time = (msecs + coeff / 2) / coeff;
-
-   err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, );
-   if (err)
-   return err;
-
-   /* AgeTime is 11:4 bits */
-   val &= ~0xff0;
-   val |= age_time << 4;
-
-   return mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
-}
-
 static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds,
 unsigned int ageing_time)
 {
@@ -2731,7 +2704,7 @@ static int mv88e6xxx_set_ageing_time(struct dsa_switch 
*ds,
int err;
 
mutex_lock(>reg_lock);
-   err = mv88e6xxx_g1_set_age_time(chip, ageing_time);
+   err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time);
mutex_unlock(>reg_lock);
 
return err;
@@ -2783,7 +2756,7 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
if (err)
return err;
 
-   err = mv88e6xxx_g1_set_age_time(chip, 30);
+   err = mv88e6xxx_g1_atu_set_age_time(chip, 30);
if (err)
return err;
 
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h 
b/drivers/net/dsa/mv88e6xxx/global1.h
index 1aec7382c02d..b8d0fb519bab 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -38,4 +38,7 @@ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, 
int port);
 int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
 
+int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
+ unsigned int msecs);
+
 #endif /* _MV88E6XXX_GLOBAL1_H */
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c 
b/drivers/net/dsa/mv88e6xxx/global1_atu.c
new file mode 100644
index ..4d0ada9efc6d
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -0,0 +1,43 @@
+/*
+ * Marvell 88E6xxx Address Translation Unit (ATU) support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ * Copyright (c) 2017 Savoir-faire Linux, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mv88e6xxx.h"
+#include "global1.h"
+
+/* Offset 0x0A: ATU Control Register */
+
+int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
+ unsigned int msecs)
+{
+   const unsigned int coeff = chip->info->age_time_coeff;
+   const unsigned int min = 0x01 * coeff;
+   const unsigned int max = 0xff * coeff;
+   u8 age_time;
+   u16 val;
+   int err;
+
+   if (msecs < min || msecs > max)
+   return -ERANGE;
+
+   /* Round to nearest multiple of coeff */
+   age_time = (msecs + coeff / 2) / coeff;
+
+   err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, );
+   if (err)
+   return err;
+
+   /* AgeTime is 11:4 bits */
+   val &= ~0xff0;
+   val |= age_time << 4;
+
+   return mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
+}
-- 

[PATCH net-next v2 06/17] net: dsa: mv88e6xxx: rework ATU Load/Purge

2017-03-11 Thread Vivien Didelot
All Marvell switch chips have an ATU accessed using the same Global (1)
register layout. Only the handling of the FID differs as more bits were
necessary to support more and more databases.

Add and use a fresh documented implementation of the ATU Load/Purge.

The static mv88e6xxx_g1_atu_{fid_write,op_wait,op,data_write,mac_write}
functions won't need to be exposed in the end so for the moment keep
their counterparts _mv88e6xxx_atu_{wait,cmd,data_write,mac_write} as is,
since they are still used by other ATU operations.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c|  22 +--
 drivers/net/dsa/mv88e6xxx/global1.h |   2 +
 drivers/net/dsa/mv88e6xxx/global1_atu.c | 108 
 3 files changed, 111 insertions(+), 21 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 1ee0c05f624e..95dbf581b54a 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2045,26 +2045,6 @@ static int _mv88e6xxx_atu_mac_read(struct mv88e6xxx_chip 
*chip,
return 0;
 }
 
-static int _mv88e6xxx_atu_load(struct mv88e6xxx_chip *chip,
-  struct mv88e6xxx_atu_entry *entry)
-{
-   int ret;
-
-   ret = _mv88e6xxx_atu_wait(chip);
-   if (ret < 0)
-   return ret;
-
-   ret = _mv88e6xxx_atu_mac_write(chip, entry->mac);
-   if (ret < 0)
-   return ret;
-
-   ret = _mv88e6xxx_atu_data_write(chip, entry);
-   if (ret < 0)
-   return ret;
-
-   return _mv88e6xxx_atu_cmd(chip, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
-}
-
 static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
  struct mv88e6xxx_atu_entry *entry);
 
@@ -2132,7 +2112,7 @@ static int mv88e6xxx_port_db_load_purge(struct 
mv88e6xxx_chip *chip, int port,
entry.state = state;
}
 
-   return _mv88e6xxx_atu_load(chip, );
+   return mv88e6xxx_g1_atu_loadpurge(chip, vlan.fid, );
 }
 
 static int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h 
b/drivers/net/dsa/mv88e6xxx/global1.h
index 18322d05225a..2c03f2e04639 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -41,5 +41,7 @@ int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
 int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool 
learn2all);
 int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
  unsigned int msecs);
+int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip *chip, u16 fid,
+  struct mv88e6xxx_atu_entry *entry);
 
 #endif /* _MV88E6XXX_GLOBAL1_H */
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c 
b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index 843a21e05f7b..09190559178b 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -13,6 +13,13 @@
 #include "mv88e6xxx.h"
 #include "global1.h"
 
+/* Offset 0x01: ATU FID Register */
+
+static int mv88e6xxx_g1_atu_fid_write(struct mv88e6xxx_chip *chip, u16 fid)
+{
+   return mv88e6xxx_g1_write(chip, GLOBAL_ATU_FID, fid & 0xfff);
+}
+
 /* Offset 0x0A: ATU Control Register */
 
 int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all)
@@ -58,3 +65,104 @@ int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip 
*chip,
 
return mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
 }
+
+/* Offset 0x0B: ATU Operation Register */
+
+static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
+{
+   return mv88e6xxx_g1_wait(chip, GLOBAL_ATU_OP, GLOBAL_ATU_OP_BUSY);
+}
+
+static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
+{
+   u16 val;
+   int err;
+
+   /* FID bits are dispatched all around gradually as more are supported */
+   if (mv88e6xxx_num_databases(chip) > 256) {
+   err = mv88e6xxx_g1_atu_fid_write(chip, fid);
+   if (err)
+   return err;
+   } else {
+   if (mv88e6xxx_num_databases(chip) > 16) {
+   /* ATU DBNum[7:4] are located in ATU Control 15:12 */
+   err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, );
+   if (err)
+   return err;
+
+   val = (val & 0x0fff) | ((fid << 8) & 0xf000);
+   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
+   if (err)
+   return err;
+   }
+
+   /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
+   op |= fid & 0xf;
+   }
+
+   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_OP, op);
+   if (err)
+   return err;
+
+   return mv88e6xxx_g1_atu_op_wait(chip);
+}
+
+/* 

[PATCH net-next v2 03/17] net: dsa: mv88e6xxx: add ATU setup helper

2017-03-11 Thread Vivien Didelot
Move the configuration of the default ageing time in a new
mv88e6xxx_atu_setup function.

That function will be extended later to contain all ATU related
configuration bits.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index b228b8491afc..0ad8200f3321 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1306,6 +1306,11 @@ static void mv88e6xxx_port_stp_state_set(struct 
dsa_switch *ds, int port,
netdev_err(ds->ports[port].netdev, "failed to update state\n");
 }
 
+static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
+{
+   return mv88e6xxx_g1_atu_set_age_time(chip, 30);
+}
+
 static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
 {
struct mv88e6xxx_chip *chip = ds->priv;
@@ -2756,10 +2761,6 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip 
*chip)
if (err)
return err;
 
-   err = mv88e6xxx_g1_atu_set_age_time(chip, 30);
-   if (err)
-   return err;
-
/* Clear all ATU entries */
err = _mv88e6xxx_atu_flush(chip, 0, true);
if (err)
@@ -2845,6 +2846,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
goto unlock;
}
 
+   err = mv88e6xxx_atu_setup(chip);
+   if (err)
+   goto unlock;
+
/* Some generations have the configuration of sending reserved
 * management frames to the CPU in global2, others in
 * global1. Hence it does not fit the two setup functions
-- 
2.12.0



[PATCH net-next v2 13/17] net: dsa: mv88e6xxx: rework port mode setup

2017-03-11 Thread Vivien Didelot
A switch port mode is defined by the association of its egress mode, its
frame mode and if supported or required, the ether type value.

Pack all this in a mv88e6xxx_set_port_mode function and provide helpers
for the Normal Network mode, the DSA mode, and the Ether Type DSA mode,
as well as an helper to setup a port's mode depending on its nature.

Define PORT_ETH_TYPE_DEFAULT for the 0x9100 reset value of port E Type.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c  | 120 +++---
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |   1 +
 2 files changed, 67 insertions(+), 54 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index e9533d4919bc..5f5023215ce1 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2199,69 +2199,82 @@ static int mv88e6xxx_serdes_power_on(struct 
mv88e6xxx_chip *chip)
return err;
 }
 
+static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
+  enum mv88e6xxx_frame_mode frame, u16 egress,
+  u16 etype)
+{
+   int err;
+
+   if (!chip->info->ops->port_set_frame_mode)
+   return -EOPNOTSUPP;
+
+   err = mv88e6xxx_port_set_egress_mode(chip, port, egress);
+   if (err)
+   return err;
+
+   err = chip->info->ops->port_set_frame_mode(chip, port, frame);
+   if (err)
+   return err;
+
+   if (chip->info->ops->port_set_ether_type)
+   return chip->info->ops->port_set_ether_type(chip, port, etype);
+
+   return 0;
+}
+
+static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int 
port)
+{
+   return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
+  PORT_CONTROL_EGRESS_UNMODIFIED,
+  PORT_ETH_TYPE_DEFAULT);
+}
+
+static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
+{
+   return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
+  PORT_CONTROL_EGRESS_UNMODIFIED,
+  PORT_ETH_TYPE_DEFAULT);
+}
+
+static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
+{
+   return mv88e6xxx_set_port_mode(chip, port,
+  MV88E6XXX_FRAME_MODE_ETHERTYPE,
+  PORT_CONTROL_EGRESS_ADD_TAG, ETH_P_EDSA);
+}
+
+static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
+{
+   if (dsa_is_dsa_port(chip->ds, port))
+   return mv88e6xxx_set_port_mode_dsa(chip, port);
+
+   if (dsa_is_normal_port(chip->ds, port))
+   return mv88e6xxx_set_port_mode_normal(chip, port);
+
+   /* Setup CPU port mode depending on its supported tag format */
+   if (chip->info->tag_protocol == DSA_TAG_PROTO_DSA)
+   return mv88e6xxx_set_port_mode_dsa(chip, port);
+
+   if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA)
+   return mv88e6xxx_set_port_mode_edsa(chip, port);
+
+   return -EINVAL;
+}
+
 static int mv88e6xxx_setup_port_dsa(struct mv88e6xxx_chip *chip, int port,
int upstream_port)
 {
-   int err;
-
-   err = chip->info->ops->port_set_frame_mode(
-   chip, port, MV88E6XXX_FRAME_MODE_DSA);
-   if (err)
-   return err;
-
return chip->info->ops->port_set_egress_unknowns(
chip, port, port == upstream_port);
 }
 
 static int mv88e6xxx_setup_port_cpu(struct mv88e6xxx_chip *chip, int port)
 {
-   int err;
-
-   switch (chip->info->tag_protocol) {
-   case DSA_TAG_PROTO_EDSA:
-   err = chip->info->ops->port_set_frame_mode(
-   chip, port, MV88E6XXX_FRAME_MODE_ETHERTYPE);
-   if (err)
-   return err;
-
-   err = mv88e6xxx_port_set_egress_mode(
-   chip, port, PORT_CONTROL_EGRESS_ADD_TAG);
-   if (err)
-   return err;
-
-   if (chip->info->ops->port_set_ether_type)
-   err = chip->info->ops->port_set_ether_type(
-   chip, port, ETH_P_EDSA);
-   break;
-
-   case DSA_TAG_PROTO_DSA:
-   err = chip->info->ops->port_set_frame_mode(
-   chip, port, MV88E6XXX_FRAME_MODE_DSA);
-   if (err)
-   return err;
-
-   err = mv88e6xxx_port_set_egress_mode(
-   chip, port, PORT_CONTROL_EGRESS_UNMODIFIED);
-   break;
-   default:
-   err = -EINVAL;
-   }
-
-   if (err)
-   return err;
-
return chip->info->ops->port_set_egress_unknowns(chip, port, true);
 }
 
 static int 

[PATCH net-next v2 17/17] etherdevice: remove unused eth_addr_greater

2017-03-11 Thread Vivien Didelot
eth_addr_greater() was introduced for the mv88e6xxx driver, but is not
used anymore. There is no other user, thus remove this function.

Signed-off-by: Vivien Didelot 
---
 include/linux/etherdevice.h | 15 ---
 1 file changed, 15 deletions(-)

diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index c62b709b1ce0..2d9f80848d4b 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -447,21 +447,6 @@ static inline void eth_addr_dec(u8 *addr)
 }
 
 /**
- * ether_addr_greater - Compare two Ethernet addresses
- * @addr1: Pointer to a six-byte array containing the Ethernet address
- * @addr2: Pointer other six-byte array containing the Ethernet address
- *
- * Compare two Ethernet addresses, returns true addr1 is greater than addr2
- */
-static inline bool ether_addr_greater(const u8 *addr1, const u8 *addr2)
-{
-   u64 u1 = ether_addr_to_u64(addr1);
-   u64 u2 = ether_addr_to_u64(addr2);
-
-   return u1 > u2;
-}
-
-/**
  * is_etherdev_addr - Tell if given Ethernet address belongs to the device.
  * @dev: Pointer to a device structure
  * @addr: Pointer to a six-byte array containing the Ethernet address
-- 
2.12.0



[PATCH net-next v2 10/17] net: dsa: mv88e6xxx: rename new FID helper

2017-03-11 Thread Vivien Didelot
Rename the _mv88e6xxx_fid_new helper to mv88e6xxx_atu_new to get rid of
the old underscore prefix naming convention and be consistent with the
rest of the chip-wide ATU API.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx/chip.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index a11e5354f14f..df31c2c57e09 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1556,7 +1556,7 @@ static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_chip 
*chip,
return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE);
 }
 
-static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid)
+static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
 {
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
struct mv88e6xxx_vtu_entry vlan;
@@ -1610,7 +1610,7 @@ static int _mv88e6xxx_vtu_new(struct mv88e6xxx_chip 
*chip, u16 vid,
};
int i, err;
 
-   err = _mv88e6xxx_fid_new(chip, );
+   err = mv88e6xxx_atu_new(chip, );
if (err)
return err;
 
-- 
2.12.0



[PATCH net-next v2 01/17] net: dsa: mv88e6xxx: add port mask helper

2017-03-11 Thread Vivien Didelot
Add a mv88e6xxx_port_mask() helper to get the bitmask of ports in a
switch chip, that will be used in several features.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 5 +
 drivers/net/dsa/mv88e6xxx/port.c  | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h 
b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 6033f2f6260a..166b513ff751 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -944,6 +944,11 @@ static inline unsigned int mv88e6xxx_num_ports(struct 
mv88e6xxx_chip *chip)
return chip->info->num_ports;
 }
 
+static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip)
+{
+   return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
+}
+
 int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
 int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
 int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 8875784c4718..9bb0f2134cba 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -539,7 +539,7 @@ int mv88e6351_port_set_egress_unknowns(struct 
mv88e6xxx_chip *chip, int port,
 
 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
 {
-   const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
+   const u16 mask = mv88e6xxx_port_mask(chip);
u16 reg;
int err;
 
-- 
2.12.0



[PATCH net-next v2 11/17] net: dsa: mv88e6xxx: rename the port vector member

2017-03-11 Thread Vivien Didelot
Not all Marvell switch chips support port trunking, which is embedded in
the port vector data for ATU operations.

Rename the portv_trunkid member of the mv88e6xxx_atu_entry structure to
portvec to be more concise and consistent with the different chips.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 8 
 drivers/net/dsa/mv88e6xxx/global1_atu.c | 8 
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h   | 2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index df31c2c57e09..e9533d4919bc 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1928,11 +1928,11 @@ static int mv88e6xxx_port_db_load_purge(struct 
mv88e6xxx_chip *chip, int port,
 
/* Purge the ATU entry only if no port is using it anymore */
if (state == GLOBAL_ATU_DATA_STATE_UNUSED) {
-   entry.portv_trunkid &= ~BIT(port);
-   if (!entry.portv_trunkid)
+   entry.portvec &= ~BIT(port);
+   if (!entry.portvec)
entry.state = GLOBAL_ATU_DATA_STATE_UNUSED;
} else {
-   entry.portv_trunkid |= BIT(port);
+   entry.portvec |= BIT(port);
entry.state = state;
}
 
@@ -1995,7 +1995,7 @@ static int mv88e6xxx_port_db_dump_fid(struct 
mv88e6xxx_chip *chip,
if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED)
break;
 
-   if (addr.trunk || (addr.portv_trunkid & BIT(port)) == 0)
+   if (addr.trunk || (addr.portvec & BIT(port)) == 0)
continue;
 
if (obj->id == SWITCHDEV_OBJ_ID_PORT_FDB) {
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c 
b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index d753e3eb1359..120b7f41a735 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -124,7 +124,7 @@ static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip 
*chip,
if (val & GLOBAL_ATU_DATA_TRUNK)
entry->trunk = true;
 
-   entry->portv_trunkid = (val >> 4) & mv88e6xxx_port_mask(chip);
+   entry->portvec = (val >> 4) & mv88e6xxx_port_mask(chip);
}
 
return 0;
@@ -139,7 +139,7 @@ static int mv88e6xxx_g1_atu_data_write(struct 
mv88e6xxx_chip *chip,
if (entry->trunk)
data |= GLOBAL_ATU_DATA_TRUNK;
 
-   data |= (entry->portv_trunkid & mv88e6xxx_port_mask(chip)) << 4;
+   data |= (entry->portvec & mv88e6xxx_port_mask(chip)) << 4;
}
 
return mv88e6xxx_g1_write(chip, GLOBAL_ATU_DATA, data);
@@ -284,8 +284,8 @@ static int mv88e6xxx_g1_atu_move(struct mv88e6xxx_chip 
*chip, u16 fid,
shift = bitmap_weight(, 16);
 
entry.state = 0xf, /* Full EntryState means Move */
-   entry.portv_trunkid = from_port & mask;
-   entry.portv_trunkid |= (to_port & mask) << shift;
+   entry.portvec = from_port & mask;
+   entry.portvec |= (to_port & mask) << shift;
 
return mv88e6xxx_g1_atu_flushmove(chip, fid, , all);
 }
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h 
b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 1fca6fae2f83..69acb4c40fdc 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -713,7 +713,7 @@ struct mv88e6xxx_info {
 struct mv88e6xxx_atu_entry {
u8  state;
booltrunk;
-   u16 portv_trunkid;
+   u16 portvec;
u8  mac[ETH_ALEN];
 };
 
-- 
2.12.0



[PATCH net-next v2 16/17] net: dsa: mv88e6xxx: add port priority override op

2017-03-11 Thread Vivien Didelot
Add a new operation to disable the DA, SA and VTU priority override.

Setting such limit is not likely to be used soon, so provide a
port_disable_pri_override operation directly. This can be changed later
for port_set_pri_override when we'll need it.

Also remove the now obsolete mv88e6xxx_6320_family helper.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx/chip.c  | 39 +++
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  1 +
 drivers/net/dsa/mv88e6xxx/port.c  |  7 +++
 drivers/net/dsa/mv88e6xxx/port.h  |  1 +
 4 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 06fe86309e27..3354f99df378 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -687,11 +687,6 @@ static bool mv88e6xxx_6165_family(struct mv88e6xxx_chip 
*chip)
return chip->info->family == MV88E6XXX_FAMILY_6165;
 }
 
-static bool mv88e6xxx_6320_family(struct mv88e6xxx_chip *chip)
-{
-   return chip->info->family == MV88E6XXX_FAMILY_6320;
-}
-
 static bool mv88e6xxx_6341_family(struct mv88e6xxx_chip *chip)
 {
return chip->info->family == MV88E6XXX_FAMILY_6341;
@@ -2407,14 +2402,8 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip 
*chip, int port)
return err;
}
 
-   if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
-   mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
-   mv88e6xxx_6320_family(chip) || mv88e6xxx_6341_family(chip)) {
-   /* Priority Override: disable DA, SA and VTU priority
-* override.
-*/
-   err = mv88e6xxx_port_write(chip, port, PORT_PRI_OVERRIDE,
-  0x);
+   if (chip->info->ops->port_disable_pri_override) {
+   err = chip->info->ops->port_disable_pri_override(chip, port);
if (err)
return err;
}
@@ -2840,6 +2829,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
+   .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2890,6 +2880,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
+   .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2912,6 +2903,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.port_set_frame_mode = mv88e6085_port_set_frame_mode,
.port_set_egress_floods = mv88e6352_port_set_egress_floods,
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
+   .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2968,6 +2960,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
+   .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2988,6 +2981,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
+   .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -3016,6 +3010,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
.port_disable_learn_limit = 

[PATCH net-next v2 04/17] net: dsa: mv88e6xxx: setup message ports

2017-03-11 Thread Vivien Didelot
All interconnectable Marvell switch chips have an ATU Learn2All feature
which allows newly learnt addresses to be spanned on ports marked as
"Message Port".

This commit configures the DSA ports as Message Port. Note that this has
no effect until the Learn2All feature is enabled.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c  | 12 
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  1 +
 drivers/net/dsa/mv88e6xxx/port.c  | 18 ++
 drivers/net/dsa/mv88e6xxx/port.h  |  2 ++
 4 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 0ad8200f3321..5c1b5825fe6c 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2504,6 +2504,13 @@ static int mv88e6xxx_setup_port_normal(struct 
mv88e6xxx_chip *chip, int port)
return chip->info->ops->port_set_egress_unknowns(chip, port, false);
 }
 
+static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
+{
+   bool message = dsa_is_dsa_port(chip->ds, port);
+
+   return mv88e6xxx_port_set_message_port(chip, port, message);
+}
+
 static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
 {
struct dsa_switch *ds = chip->ds;
@@ -2658,10 +2665,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip 
*chip, int port)
return err;
}
 
-   /* Port Control 1: disable trunking, disable sending
-* learning messages to this port.
-*/
-   err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, 0x);
+   err = mv88e6xxx_setup_message_port(chip, port);
if (err)
return err;
 
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h 
b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 166b513ff751..45205519b9fe 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -144,6 +144,7 @@
 #define PORT_CONTROL_STATE_LEARNING0x02
 #define PORT_CONTROL_STATE_FORWARDING  0x03
 #define PORT_CONTROL_1 0x05
+#define PORT_CONTROL_1_MESSAGE_PORTBIT(15)
 #define PORT_CONTROL_1_FID_11_4_MASK   (0xff << 0)
 #define PORT_BASE_VLAN 0x06
 #define PORT_BASE_VLAN_FID_3_0_MASK(0xf << 12)
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 9bb0f2134cba..40fe48188056 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -535,6 +535,24 @@ int mv88e6351_port_set_egress_unknowns(struct 
mv88e6xxx_chip *chip, int port,
 
 /* Offset 0x05: Port Control 1 */
 
+int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
+   bool message_port)
+{
+   u16 val;
+   int err;
+
+   err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, );
+   if (err)
+   return err;
+
+   if (message_port)
+   val |= PORT_CONTROL_1_MESSAGE_PORT;
+   else
+   val &= ~PORT_CONTROL_1_MESSAGE_PORT;
+
+   return mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, val);
+}
+
 /* Offset 0x06: Port Based VLAN Map */
 
 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index c83cbb3f4491..4328d6f29d4d 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -64,6 +64,8 @@ int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip 
*chip, int port,
   bool on);
 int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
  u16 etype);
+int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
+   bool message_port);
 int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port);
 int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
 int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
-- 
2.12.0



[PATCH net-next v2 09/17] net: dsa: mv88e6xxx: rework ATU Remove

2017-03-11 Thread Vivien Didelot
Add a fresh documented implementation of the ATU Move operation, and use
it to replace the current ATU Remove operation.

Note that not all Marvell switch chip support the ATU Move operation.
For those supporting it, the number of bits used to mask the destination
port may vary. 6352 and such use 4-bit, while 6390 use 5-bit. Thus add a
new atu_move_port_mask member in the info structure to describe the
presence and variant of ATU Move operation.

Note that the ATU Move operation is not documented in the 6185 datasheet
but the chip does support the operation.

All remaining _mv88e6xxx_atu_* functions are now unused as well as the
MV88E6XXX_FLAG_G1_ATU_FID flag, thus remove them.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 140 +++-
 drivers/net/dsa/mv88e6xxx/global1.h |   2 +
 drivers/net/dsa/mv88e6xxx/global1_atu.c |  29 +++
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h   |  18 ++--
 4 files changed, 67 insertions(+), 122 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8b8c3cb167c1..a11e5354f14f 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1066,11 +1066,6 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, 
int port,
mutex_unlock(>reg_lock);
 }
 
-static int _mv88e6xxx_atu_wait(struct mv88e6xxx_chip *chip)
-{
-   return mv88e6xxx_g1_wait(chip, GLOBAL_ATU_OP, GLOBAL_ATU_OP_BUSY);
-}
-
 static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
 struct ethtool_eee *e)
 {
@@ -1130,111 +1125,6 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int 
port,
return err;
 }
 
-static int _mv88e6xxx_atu_cmd(struct mv88e6xxx_chip *chip, u16 fid, u16 cmd)
-{
-   u16 val;
-   int err;
-
-   if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G1_ATU_FID)) {
-   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_FID, fid);
-   if (err)
-   return err;
-   } else if (mv88e6xxx_num_databases(chip) == 256) {
-   /* ATU DBNum[7:4] are located in ATU Control 15:12 */
-   err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, );
-   if (err)
-   return err;
-
-   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL,
-(val & 0xfff) | ((fid << 8) & 0xf000));
-   if (err)
-   return err;
-
-   /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
-   cmd |= fid & 0xf;
-   }
-
-   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_OP, cmd);
-   if (err)
-   return err;
-
-   return _mv88e6xxx_atu_wait(chip);
-}
-
-static int _mv88e6xxx_atu_data_write(struct mv88e6xxx_chip *chip,
-struct mv88e6xxx_atu_entry *entry)
-{
-   u16 data = entry->state & GLOBAL_ATU_DATA_STATE_MASK;
-
-   if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
-   unsigned int mask, shift;
-
-   if (entry->trunk) {
-   data |= GLOBAL_ATU_DATA_TRUNK;
-   mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK;
-   shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT;
-   } else {
-   mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK;
-   shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT;
-   }
-
-   data |= (entry->portv_trunkid << shift) & mask;
-   }
-
-   return mv88e6xxx_g1_write(chip, GLOBAL_ATU_DATA, data);
-}
-
-static int _mv88e6xxx_atu_flush_move(struct mv88e6xxx_chip *chip,
-struct mv88e6xxx_atu_entry *entry,
-bool static_too)
-{
-   int op;
-   int err;
-
-   err = _mv88e6xxx_atu_wait(chip);
-   if (err)
-   return err;
-
-   err = _mv88e6xxx_atu_data_write(chip, entry);
-   if (err)
-   return err;
-
-   if (entry->fid) {
-   op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB :
-   GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
-   } else {
-   op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL :
-   GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
-   }
-
-   return _mv88e6xxx_atu_cmd(chip, entry->fid, op);
-}
-
-static int _mv88e6xxx_atu_move(struct mv88e6xxx_chip *chip, u16 fid,
-  int from_port, int to_port, bool static_too)
-{
-   struct mv88e6xxx_atu_entry entry = {
-   .trunk = false,
-   .fid = fid,
-   };
-
-   /* EntryState bits must be 0xF */
-   entry.state = GLOBAL_ATU_DATA_STATE_MASK;
-
-   /* ToPort and FromPort are respectively in PortVec bits 7:4 and 3:0 */
-   entry.portv_trunkid = (to_port & 0x0f) << 4;
-   entry.portv_trunkid |= from_port & 0x0f;
-
-   

[PATCH net-next v2 00/17] net: dsa: mv88e6xxx: rework ATU support

2017-03-11 Thread Vivien Didelot
The purpose of this patch series is to rework the code related to the
Address Translation Unit (ATU), and bring support for it to the 88E6390
family of switch chips.

All Global (1) ATU related code have been reworked and moved to its own
file. Some port related bits used for ATU configuration (such as the
Learn2All and MessagePort feature) have also been taken care of.

The ports' mode and egress flooding mode have been refactored to fix the
egress of frames with unknown unicast or multicast destination address,
and write all these bits regardless the port mode (Normal, DSA, etc.)

Finally remove the eth_addr_greater which was only used by mv88e6xxx.

Changes in v2:
  - add Reviewed-by tags
  - split mv88e6xxx_g1_atu_set_age_time and mv88e6xxx_atu_setup addition
  - remove DSA_TAG_PROTO_TRAILER check
  - split Message Port and Learn2All addition
  - remove unused MV88E6XXX_FLAG_G1_ATU_FID flag
  - add dsa_is_normal_port helper

Vivien Didelot (17):
  net: dsa: mv88e6xxx: add port mask helper
  net: dsa: mv88e6xxx: move ATU ageing time setter
  net: dsa: mv88e6xxx: add ATU setup helper
  net: dsa: mv88e6xxx: setup message ports
  net: dsa: mv88e6xxx: enable ATU Learn2All
  net: dsa: mv88e6xxx: rework ATU Load/Purge
  net: dsa: mv88e6xxx: rework ATU GetNext
  net: dsa: mv88e6xxx: rework ATU Flush
  net: dsa: mv88e6xxx: rework ATU Remove
  net: dsa: mv88e6xxx: rename new FID helper
  net: dsa: mv88e6xxx: rename the port vector member
  net: dsa: add dsa_is_normal_port helper
  net: dsa: mv88e6xxx: rework port mode setup
  net: dsa: mv88e6xxx: fix port egress flooding mode
  net: dsa: mv88e6xxx: add port ATU learn limit op
  net: dsa: mv88e6xxx: add port priority override op
  etherdevice: remove unused eth_addr_greater

 drivers/net/dsa/mv88e6xxx/Makefile  |   1 +
 drivers/net/dsa/mv88e6xxx/chip.c| 667 +++-
 drivers/net/dsa/mv88e6xxx/global1.h |  11 +
 drivers/net/dsa/mv88e6xxx/global1_atu.c | 300 ++
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h   |  44 ++-
 drivers/net/dsa/mv88e6xxx/port.c|  78 +++-
 drivers/net/dsa/mv88e6xxx/port.h|  16 +-
 include/linux/etherdevice.h |  15 -
 include/net/dsa.h   |   5 +
 9 files changed, 638 insertions(+), 499 deletions(-)
 create mode 100644 drivers/net/dsa/mv88e6xxx/global1_atu.c

-- 
2.12.0



[PATCH net-next v2 07/17] net: dsa: mv88e6xxx: rework ATU GetNext

2017-03-11 Thread Vivien Didelot
Add and use a fresh documented implementation of the ATU GetNext.

Since it is not necessary to write the MAC address to iterate from, only
do it once directly in the ATU GetNext operation, if the provided ATU
entry structure is not valid. This makes the user code simpler.

Also, there is no need to loop when getting a single ATU entry. So
remove the mv88e6xxx_atu_get helper and add a simpler snippet in
mv88e6xxx_port_db_load_purge to lookup a given MAC address.

The _mv88e6xxx_atu_mac_{read,write} are not used anymore thus remove
them. _mv88e6xxx_atu_data_{read,write} are still used so keep them.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 140 
 drivers/net/dsa/mv88e6xxx/global1.h |   2 +
 drivers/net/dsa/mv88e6xxx/global1_atu.c |  66 +++
 3 files changed, 84 insertions(+), 124 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 95dbf581b54a..2d1ec0d79fb6 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2012,76 +2012,6 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch 
*ds, int port,
return err;
 }
 
-static int _mv88e6xxx_atu_mac_write(struct mv88e6xxx_chip *chip,
-   const unsigned char *addr)
-{
-   int i, err;
-
-   for (i = 0; i < 3; i++) {
-   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_MAC_01 + i,
-(addr[i * 2] << 8) | addr[i * 2 + 1]);
-   if (err)
-   return err;
-   }
-
-   return 0;
-}
-
-static int _mv88e6xxx_atu_mac_read(struct mv88e6xxx_chip *chip,
-  unsigned char *addr)
-{
-   u16 val;
-   int i, err;
-
-   for (i = 0; i < 3; i++) {
-   err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_MAC_01 + i, );
-   if (err)
-   return err;
-
-   addr[i * 2] = val >> 8;
-   addr[i * 2 + 1] = val & 0xff;
-   }
-
-   return 0;
-}
-
-static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
- struct mv88e6xxx_atu_entry *entry);
-
-static int mv88e6xxx_atu_get(struct mv88e6xxx_chip *chip, int fid,
-const u8 *addr, struct mv88e6xxx_atu_entry *entry)
-{
-   struct mv88e6xxx_atu_entry next;
-   int err;
-
-   memcpy(next.mac, addr, ETH_ALEN);
-   eth_addr_dec(next.mac);
-
-   err = _mv88e6xxx_atu_mac_write(chip, next.mac);
-   if (err)
-   return err;
-
-   do {
-   err = _mv88e6xxx_atu_getnext(chip, fid, );
-   if (err)
-   return err;
-
-   if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED)
-   break;
-
-   if (ether_addr_equal(next.mac, addr)) {
-   *entry = next;
-   return 0;
-   }
-   } while (ether_addr_greater(addr, next.mac));
-
-   memset(entry, 0, sizeof(*entry));
-   entry->fid = fid;
-   ether_addr_copy(entry->mac, addr);
-
-   return 0;
-}
-
 static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
const unsigned char *addr, u16 vid,
u8 state)
@@ -2098,10 +2028,21 @@ static int mv88e6xxx_port_db_load_purge(struct 
mv88e6xxx_chip *chip, int port,
if (err)
return err;
 
-   err = mv88e6xxx_atu_get(chip, vlan.fid, addr, );
+   entry.state = GLOBAL_ATU_DATA_STATE_UNUSED;
+   ether_addr_copy(entry.mac, addr);
+   eth_addr_dec(entry.mac);
+
+   err = mv88e6xxx_g1_atu_getnext(chip, vlan.fid, );
if (err)
return err;
 
+   /* Initialize a fresh ATU entry if it isn't found */
+   if (entry.state == GLOBAL_ATU_DATA_STATE_UNUSED ||
+   !ether_addr_equal(entry.mac, addr)) {
+   memset(, 0, sizeof(entry));
+   ether_addr_copy(entry.mac, addr);
+   }
+
/* Purge the ATU entry only if no port is using it anymore */
if (state == GLOBAL_ATU_DATA_STATE_UNUSED) {
entry.portv_trunkid &= ~BIT(port);
@@ -2152,68 +2093,19 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch 
*ds, int port,
return err;
 }
 
-static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
- struct mv88e6xxx_atu_entry *entry)
-{
-   struct mv88e6xxx_atu_entry next = { 0 };
-   u16 val;
-   int err;
-
-   next.fid = fid;
-
-   err = _mv88e6xxx_atu_wait(chip);
-   if (err)
-   return err;
-
-   err = _mv88e6xxx_atu_cmd(chip, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
-   if (err)
-   return err;
-
-   err = _mv88e6xxx_atu_mac_read(chip, next.mac);
-   if (err)
-   

[PATCH net-next v2 12/17] net: dsa: add dsa_is_normal_port helper

2017-03-11 Thread Vivien Didelot
Introduce a dsa_is_normal_port helper to check if a given port is a
normal user port as opposed to a CPU port or DSA link.

Signed-off-by: Vivien Didelot 
---
 include/net/dsa.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 4e13e695f025..bf0e42c2a6f7 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -248,6 +248,11 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, 
int p)
return !!((ds->dsa_port_mask) & (1 << p));
 }
 
+static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
+{
+   return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
+}
+
 static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
 {
return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
-- 
2.12.0



[PATCH net-next v2 15/17] net: dsa: mv88e6xxx: add port ATU learn limit op

2017-03-11 Thread Vivien Didelot
Add a new operation to disable the limiting of learnt MAC addresses.

Setting such limit is not likely to be used soon, so provide a
port_disable_learn_limit operation directly. This can be changed later
for port_set_learn_limit when we'll need it.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx/chip.c  | 36 +--
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  1 +
 drivers/net/dsa/mv88e6xxx/port.c  |  7 +++
 drivers/net/dsa/mv88e6xxx/port.h  |  3 +++
 4 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 0844df1b25e9..06fe86309e27 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2401,15 +2401,15 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip 
*chip, int port)
return err;
}
 
+   if (chip->info->ops->port_disable_learn_limit) {
+   err = chip->info->ops->port_disable_learn_limit(chip, port);
+   if (err)
+   return err;
+   }
+
if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
mv88e6xxx_6320_family(chip) || mv88e6xxx_6341_family(chip)) {
-   /* Port ATU control: disable limiting the number of
-* address database entries that this port is allowed
-* to use.
-*/
-   err = mv88e6xxx_port_write(chip, port, PORT_ATU_CONTROL,
-  0x);
/* Priority Override: disable DA, SA and VTU priority
 * override.
 */
@@ -2839,6 +2839,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.port_set_ether_type = mv88e6351_port_set_ether_type,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
+   .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2888,6 +2889,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.port_jumbo_config = mv88e6165_port_jumbo_config,
.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
+   .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2909,6 +2911,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.port_set_speed = mv88e6185_port_set_speed,
.port_set_frame_mode = mv88e6085_port_set_frame_mode,
.port_set_egress_floods = mv88e6352_port_set_egress_floods,
+   .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2964,6 +2967,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.port_jumbo_config = mv88e6165_port_jumbo_config,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
+   .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -2983,6 +2987,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+   .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -3010,6 +3015,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.port_jumbo_config = mv88e6165_port_jumbo_config,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
+   .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -3039,6 +3045,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.port_jumbo_config = 

[PATCH net-next v2 05/17] net: dsa: mv88e6xxx: enable ATU Learn2All

2017-03-11 Thread Vivien Didelot
The ATU Learn2All feature allows newly learnt addresses to be spanned on
ports marked as "Message Port", currently all DSA ports.

This commit enables this feature which is necessary and quite convenient
for multi-chip switch fabrics.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 15 ++-
 drivers/net/dsa/mv88e6xxx/global1.h |  1 +
 drivers/net/dsa/mv88e6xxx/global1_atu.c | 17 +
 3 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 5c1b5825fe6c..1ee0c05f624e 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1308,6 +1308,12 @@ static void mv88e6xxx_port_stp_state_set(struct 
dsa_switch *ds, int port,
 
 static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
 {
+   int err;
+
+   err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
+   if (err)
+   return err;
+
return mv88e6xxx_g1_atu_set_age_time(chip, 30);
 }
 
@@ -2756,15 +2762,6 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip 
*chip)
if (err < 0)
return err;
 
-   /* Set the default address aging time to 5 minutes, and
-* enable address learn messages to be sent to all message
-* ports.
-*/
-   err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL,
-GLOBAL_ATU_CONTROL_LEARN2ALL);
-   if (err)
-   return err;
-
/* Clear all ATU entries */
err = _mv88e6xxx_atu_flush(chip, 0, true);
if (err)
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h 
b/drivers/net/dsa/mv88e6xxx/global1.h
index b8d0fb519bab..18322d05225a 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -38,6 +38,7 @@ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, 
int port);
 int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
 
+int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool 
learn2all);
 int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
  unsigned int msecs);
 
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c 
b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index 4d0ada9efc6d..843a21e05f7b 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -15,6 +15,23 @@
 
 /* Offset 0x0A: ATU Control Register */
 
+int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all)
+{
+   u16 val;
+   int err;
+
+   err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, );
+   if (err)
+   return err;
+
+   if (learn2all)
+   val |= GLOBAL_ATU_CONTROL_LEARN2ALL;
+   else
+   val &= ~GLOBAL_ATU_CONTROL_LEARN2ALL;
+
+   return mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
+}
+
 int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
  unsigned int msecs)
 {
-- 
2.12.0



[PATCH net-next v2 08/17] net: dsa: mv88e6xxx: rework ATU Flush

2017-03-11 Thread Vivien Didelot
Add a fresh documented implementation of the ATU Flush/Move operation.
Use it to replace the current ATU Flush operation.

_mv88e6xxx_atu_flush_move is still used by the Move operation so keep it
until the Move operation is refactored in a next commit.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 22 +---
 drivers/net/dsa/mv88e6xxx/global1.h |  1 +
 drivers/net/dsa/mv88e6xxx/global1_atu.c | 37 +
 3 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 2d1ec0d79fb6..8b8c3cb167c1 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1210,17 +1210,6 @@ static int _mv88e6xxx_atu_flush_move(struct 
mv88e6xxx_chip *chip,
return _mv88e6xxx_atu_cmd(chip, entry->fid, op);
 }
 
-static int _mv88e6xxx_atu_flush(struct mv88e6xxx_chip *chip,
-   u16 fid, bool static_too)
-{
-   struct mv88e6xxx_atu_entry entry = {
-   .fid = fid,
-   .state = 0, /* EntryState bits must be 0 */
-   };
-
-   return _mv88e6xxx_atu_flush_move(chip, , static_too);
-}
-
 static int _mv88e6xxx_atu_move(struct mv88e6xxx_chip *chip, u16 fid,
   int from_port, int to_port, bool static_too)
 {
@@ -1310,6 +1299,10 @@ static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip 
*chip)
 {
int err;
 
+   err = mv88e6xxx_g1_atu_flush(chip, 0, true);
+   if (err)
+   return err;
+
err = mv88e6xxx_g1_atu_set_learn2all(chip, true);
if (err)
return err;
@@ -1714,7 +1707,7 @@ static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip 
*chip, u16 *fid)
return -ENOSPC;
 
/* Clear the database */
-   return _mv88e6xxx_atu_flush(chip, *fid, true);
+   return mv88e6xxx_g1_atu_flush(chip, *fid, true);
 }
 
 static int _mv88e6xxx_vtu_new(struct mv88e6xxx_chip *chip, u16 vid,
@@ -2634,11 +2627,6 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip 
*chip)
if (err < 0)
return err;
 
-   /* Clear all ATU entries */
-   err = _mv88e6xxx_atu_flush(chip, 0, true);
-   if (err)
-   return err;
-
/* Configure the IP ToS mapping registers. */
err = mv88e6xxx_g1_write(chip, GLOBAL_IP_PRI_0, 0x);
if (err)
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h 
b/drivers/net/dsa/mv88e6xxx/global1.h
index 8dd8ecc9f064..187acfc8ed37 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -45,5 +45,6 @@ int mv88e6xxx_g1_atu_getnext(struct mv88e6xxx_chip *chip, u16 
fid,
 struct mv88e6xxx_atu_entry *entry);
 int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip *chip, u16 fid,
   struct mv88e6xxx_atu_entry *entry);
+int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all);
 
 #endif /* _MV88E6XXX_GLOBAL1_H */
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c 
b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index 94e940522849..7ec9b22feaee 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -232,3 +232,40 @@ int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip 
*chip, u16 fid,
 
return mv88e6xxx_g1_atu_op(chip, fid, GLOBAL_ATU_OP_LOAD_DB);
 }
+
+static int mv88e6xxx_g1_atu_flushmove(struct mv88e6xxx_chip *chip, u16 fid,
+ struct mv88e6xxx_atu_entry *entry,
+ bool all)
+{
+   u16 op;
+   int err;
+
+   err = mv88e6xxx_g1_atu_op_wait(chip);
+   if (err)
+   return err;
+
+   err = mv88e6xxx_g1_atu_data_write(chip, entry);
+   if (err)
+   return err;
+
+   /* Flush/Move all or non-static entries from all or a given database */
+   if (all && fid)
+   op = GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB;
+   else if (fid)
+   op = GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
+   else if (all)
+   op = GLOBAL_ATU_OP_FLUSH_MOVE_ALL;
+   else
+   op = GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
+
+   return mv88e6xxx_g1_atu_op(chip, fid, op);
+}
+
+int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all)
+{
+   struct mv88e6xxx_atu_entry entry = {
+   .state = 0, /* Null EntryState means Flush */
+   };
+
+   return mv88e6xxx_g1_atu_flushmove(chip, fid, , all);
+}
-- 
2.12.0



[PATCH net-next v2 14/17] net: dsa: mv88e6xxx: fix port egress flooding mode

2017-03-11 Thread Vivien Didelot
The Marvell switch ports can be configured to allow or prevent egress of
frames with an unknown unicast or multicast destination address.

Some switch chips such as 88E6095 and 88E6185 have two disjoint bits in
Port Control Register (0x04) bit 2 "Forward Unknown" (for unicast) and
Port Control 2 Register (0x08) bit 6 "Default Forward" (for multicast).

Other chips such as 88E6085, 88E6123, 88E6352, and 88E6390 have a 2-bit
value in Port Control Register (0x04) bits 3:2 "EgressFloods".

The current code does not fully implement the disjoint bits variant and
assigns incorrect ones to some chip models. Fix that with two
implementation references (6185 and 6352 that I currently have) of a
port_set_egress_floods operation (as named in datasheets).

Old chips such as 88E6060 don't have egress flooding mode, so don't
error out if the operation is not provided.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c  | 111 +-
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  15 +++--
 drivers/net/dsa/mv88e6xxx/port.c  |  44 ++
 drivers/net/dsa/mv88e6xxx/port.h  |  10 ++-
 4 files changed, 84 insertions(+), 96 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 5f5023215ce1..0844df1b25e9 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2261,23 +2261,6 @@ static int mv88e6xxx_setup_port_mode(struct 
mv88e6xxx_chip *chip, int port)
return -EINVAL;
 }
 
-static int mv88e6xxx_setup_port_dsa(struct mv88e6xxx_chip *chip, int port,
-   int upstream_port)
-{
-   return chip->info->ops->port_set_egress_unknowns(
-   chip, port, port == upstream_port);
-}
-
-static int mv88e6xxx_setup_port_cpu(struct mv88e6xxx_chip *chip, int port)
-{
-   return chip->info->ops->port_set_egress_unknowns(chip, port, true);
-}
-
-static int mv88e6xxx_setup_port_normal(struct mv88e6xxx_chip *chip, int port)
-{
-   return chip->info->ops->port_set_egress_unknowns(chip, port, false);
-}
-
 static int mv88e6xxx_setup_message_port(struct mv88e6xxx_chip *chip, int port)
 {
bool message = dsa_is_dsa_port(chip->ds, port);
@@ -2285,6 +2268,18 @@ static int mv88e6xxx_setup_message_port(struct 
mv88e6xxx_chip *chip, int port)
return mv88e6xxx_port_set_message_port(chip, port, message);
 }
 
+static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
+{
+   bool flood = port == dsa_upstream_port(chip->ds);
+
+   /* Upstream ports flood frames with unknown unicast or multicast DA */
+   if (chip->info->ops->port_set_egress_floods)
+   return chip->info->ops->port_set_egress_floods(chip, port,
+  flood, flood);
+
+   return 0;
+}
+
 static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
 {
struct dsa_switch *ds = chip->ds;
@@ -2327,21 +2322,14 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip 
*chip, int port)
if (err)
return err;
 
-   if (dsa_is_cpu_port(ds, port)) {
-   err = mv88e6xxx_setup_port_cpu(chip, port);
-   } else if (dsa_is_dsa_port(ds, port)) {
-   err = mv88e6xxx_setup_port_dsa(chip, port,
-  dsa_upstream_port(ds));
-   } else {
-   err = mv88e6xxx_setup_port_normal(chip, port);
-   }
-   if (err)
-   return err;
-
err = mv88e6xxx_setup_port_mode(chip, port);
if (err)
return err;
 
+   err = mv88e6xxx_setup_egress_floods(chip, port);
+   if (err)
+   return err;
+
/* If this port is connected to a SerDes, make sure the SerDes is not
 * powered down.
 */
@@ -2847,7 +2835,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.port_set_speed = mv88e6185_port_set_speed,
.port_tag_remap = mv88e6095_port_tag_remap,
.port_set_frame_mode = mv88e6351_port_set_frame_mode,
-   .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+   .port_set_egress_floods = mv88e6352_port_set_egress_floods,
.port_set_ether_type = mv88e6351_port_set_ether_type,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6097_port_pause_config,
@@ -2873,7 +2861,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
.port_set_frame_mode = mv88e6085_port_set_frame_mode,
-   .port_set_egress_unknowns = mv88e6095_port_set_egress_unknowns,
+   .port_set_egress_floods = mv88e6185_port_set_egress_floods,
.port_set_upstream_port = mv88e6095_port_set_upstream_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,

[PATCH v2] net: tun: use new api ethtool_{get|set}_link_ksettings

2017-03-11 Thread Philippe Reynes
The ethtool api {get|set}_settings is deprecated.
We move this driver to new api {get|set}_link_ksettings.

Signed-off-by: Philippe Reynes 
---
Changelog:
v2:
- Finaly, I've found the hardware and do basic test ;)
  thanks Michael S. Tsirkin and Eric Dumazet for the feedback

 drivers/net/tun.c |   24 +++-
 1 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index dc1b1dd..c418f0a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2430,18 +2430,16 @@ static void tun_chr_show_fdinfo(struct seq_file *m, 
struct file *f)
 
 /* ethtool interface */
 
-static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-   cmd->supported  = 0;
-   cmd->advertising= 0;
-   ethtool_cmd_speed_set(cmd, SPEED_10);
-   cmd->duplex = DUPLEX_FULL;
-   cmd->port   = PORT_TP;
-   cmd->phy_address= 0;
-   cmd->transceiver= XCVR_INTERNAL;
-   cmd->autoneg= AUTONEG_DISABLE;
-   cmd->maxtxpkt   = 0;
-   cmd->maxrxpkt   = 0;
+static int tun_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
+{
+   ethtool_link_ksettings_zero_link_mode(cmd, supported);
+   ethtool_link_ksettings_zero_link_mode(cmd, advertising);
+   cmd->base.speed = SPEED_10;
+   cmd->base.duplex= DUPLEX_FULL;
+   cmd->base.port  = PORT_TP;
+   cmd->base.phy_address   = 0;
+   cmd->base.autoneg   = AUTONEG_DISABLE;
return 0;
 }
 
@@ -2504,7 +2502,6 @@ static int tun_set_coalesce(struct net_device *dev,
 }
 
 static const struct ethtool_ops tun_ethtool_ops = {
-   .get_settings   = tun_get_settings,
.get_drvinfo= tun_get_drvinfo,
.get_msglevel   = tun_get_msglevel,
.set_msglevel   = tun_set_msglevel,
@@ -2512,6 +2509,7 @@ static int tun_set_coalesce(struct net_device *dev,
.get_ts_info= ethtool_op_get_ts_info,
.get_coalesce   = tun_get_coalesce,
.set_coalesce   = tun_set_coalesce,
+   .get_link_ksettings = tun_get_link_ksettings,
 };
 
 static int tun_queue_resize(struct tun_struct *tun)
-- 
1.7.4.4



Re: [PATCH net-next 04/14] net: dsa: mv88e6xxx: rework ATU Load/Purge

2017-03-11 Thread Vivien Didelot
Hi Andrew,

Andrew Lunn  writes:

> On Thu, Mar 09, 2017 at 06:33:14PM -0500, Vivien Didelot wrote:
>> All Marvell switch chips have an ATU accessed using the same Global (1)
>> register layout. Only the handling of the FID differs as more bits were
>> necessary to support more and more databases.
>> 
>> Add and use a fresh documented implementation of the ATU Load/Purge.
>
> This is not really the Linux way of doing something. You don't throw
> something away and replace it. You incrementally modify what you have
> into something better.
>
> I really wished you had moved the code, unmodified, into
> global1_atu.c. Then made lots of easy to review small changes. I
> cannot just look at this patch and know it is correct. What i need to
> compare against is not in this patch. So it is a lot harder to review.

I've addressed all of your comments in this patchset except this one.

A patch file cannot guarantee that a chunk of code moved around has not
been altered in the process. This will just generate more diff for no
value, that needs to be updated afterwards anyway.

Plus you already complained in the first iteration I sent about
modifying lines that I previously added. I took care of logically
splitting the new ATU Load/Purge, GetNext, Flush and Remove operations
into incremental unmodified chunks in this series.

I have updated the commit messages to detail the addition of the static
helpers and their counterparts, but I will resend this patch as is.

Thanks,

Vivien


[PATCH] Cleanup some warning from timestamping code.

2017-03-11 Thread Ezequiel Lara Gomez
---
 drivers/net/loopback.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b23b719..122cc2d 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -13,7 +13,7 @@
  *
  * Alan Cox:   Fixed oddments for NET3.014
  * Alan Cox:   Rejig for NET3.029 snap #3
- * Alan Cox:   Fixed NET3.029 bugs and sped up
+ * Alan Cox:   Fixed NET3.029 bugs and sped up
  * Larry McVoy :   Tiny tweak to double performance
  * Alan Cox:   Backed out LMV's tweak - the linux mm
  * can't take it...
@@ -41,7 +41,7 @@
 #include 
 
 #include 
-#include 
+#include 
 
 #include 
 #include 
@@ -149,8 +149,8 @@ static void loopback_dev_free(struct net_device *dev)
 }
 
 static const struct net_device_ops loopback_ops = {
-   .ndo_init  = loopback_dev_init,
-   .ndo_start_xmit= loopback_xmit,
+   .ndo_init= loopback_dev_init,
+   .ndo_start_xmit  = loopback_xmit,
.ndo_get_stats64 = loopback_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
 };
@@ -170,7 +170,7 @@ static void loopback_setup(struct net_device *dev)
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
netif_keep_dst(dev);
dev->hw_features= NETIF_F_GSO_SOFTWARE;
-   dev->features   = NETIF_F_SG | NETIF_F_FRAGLIST
+   dev->features   = NETIF_F_SG | NETIF_F_FRAGLIST
| NETIF_F_GSO_SOFTWARE
| NETIF_F_HW_CSUM
| NETIF_F_RXCSUM
@@ -206,7 +206,6 @@ static __net_init int loopback_net_init(struct net *net)
net->loopback_dev = dev;
return 0;
 
-
 out_free_netdev:
free_netdev(dev);
 out:
@@ -217,5 +216,5 @@ static __net_init int loopback_net_init(struct net *net)
 
 /* Registered in net/core/dev.c */
 struct pernet_operations __net_initdata loopback_net_ops = {
-   .init = loopback_net_init,
+   .init = loopback_net_init,
 };
-- 
1.9.1

Amazon Data Services Ireland Limited registered office: One Burlington Plaza, 
Burlington Road, Dublin 4, Ireland. Registered in Ireland. Registration number 
390566.



[PATCH] Enable tx timestamping on loopback and dummy

2017-03-11 Thread Ezequiel Lara Gomez
This enables testing of SO_TIMESTAMPING options by targetting localhost
addresses.

Tested on qemu using txtimestamping.c from the kernel selftests.
---
 drivers/net/dummy.c| 1 +
 drivers/net/loopback.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 2c80611..32fdc00 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -125,6 +125,7 @@ static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct 
net_device *dev)
dstats->tx_bytes += skb->len;
u64_stats_update_end(>syncp);
 
+   skb_tx_timestamp(skb);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
 }
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 122cc2d..8bcf479 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -74,6 +74,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
struct pcpu_lstats *lb_stats;
int len;
 
+   skb_tx_timestamp(skb);
skb_orphan(skb);
 
/* Before queueing this packet to netif_rx(),
-- 
1.9.1

Amazon Data Services Ireland Limited registered office: One Burlington Plaza, 
Burlington Road, Dublin 4, Ireland. Registered in Ireland. Registration number 
390566.



Re: regression (4.10) - interface remove uevents not generated

2017-03-11 Thread Andrei Vagin
Hi Mantas,

Thank you for the report. Could you try out the attached patch?

On Sat, Mar 11, 2017 at 05:10:22PM +0200, Mantas Mikulėnas wrote:
> Hello,
> 
> It seems that commit 002d8a1a6c11b9b2a8ac615095589111dd52749b ("net:
> skip genenerating uevents for network namespaces that are exiting")
> broke 'remove' uevents for *all* network interfaces, even for those in
> the main/default namespace.
> 
> Other than breaking some of my udev rules, this also causes problems for
> NetworkManager, which apparently relies on those uevents to update its
> interface information cache. (I ended up reverting that commit locally
> just so I could connect to VPNs again.)
> 
> This problem is present in both v4.10.1 and current master
> (v4.11-rc1-290-g434fd6353b4c).
> 
> -- 
> Mantas Mikulėnas 
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 3c4bbec..20c48cf 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -34,6 +34,7 @@ EXPORT_SYMBOL_GPL(net_namespace_list);
 
 struct net init_net = {
.dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
+   .exit_list = LIST_HEAD_INIT(init_net.exit_list),
 };
 EXPORT_SYMBOL(init_net);
 
@@ -286,6 +287,7 @@ static __net_init int setup_net(struct net *net, struct 
user_namespace *user_ns)
net->user_ns = user_ns;
idr_init(>netns_ids);
spin_lock_init(>nsid_lock);
+   INIT_LIST_HEAD(>exit_list);
 
list_for_each_entry(ops, _list, list) {
error = ops_init(ops, net);


Proposal...

2017-03-11 Thread Teresa Au


Personal Business proposal for you,contact me via my personal E-mail for more 
detail's: 
ms_teresa_a...@outlook.com



Re: [PATCH] Enable tx timestamping on loopback and dummy

2017-03-11 Thread Soheil Hassas Yeganeh
On Sat, Mar 11, 2017 at 9:42 AM, Ezequiel Lara Gomez
 wrote:
> Also, cleanup some warnings from timestamping code.

Can you please submit the styling fixes as a separate patch?

Thanks,
Soheil


[PATCH net] bpf: improve read-only handling

2017-03-11 Thread Daniel Borkmann
Improve bpf_{prog,jit_binary}_{un,}lock_ro() by throwing a
one-time warning in case of an error when the image couldn't
be set read-only, and also mark struct bpf_prog as locked when
bpf_prog_lock_ro() was called.

Reason for the latter is that bpf_prog_unlock_ro() is called from
various places including error paths, and we shouldn't mess with
page attributes when really not needed.

For bpf_jit_binary_unlock_ro() this is not needed as jited flag
implicitly indicates this, thus for archs with ARCH_HAS_SET_MEMORY
we're guaranteed to have a previously locked image. Overall, this
should also help us to identify any further potential issues with
set_memory_*() helpers.

Signed-off-by: Daniel Borkmann 
Acked-by: Alexei Starovoitov 
---
 ( My preference is on -net, so we can potentially find and fix
   any remaining unexpected issue with set_memory_*(). Thanks! )

 include/linux/filter.h | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 0c167fd..fbf7b39 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -409,6 +409,7 @@ struct bpf_prog {
u16 pages;  /* Number of allocated pages */
kmemcheck_bitfield_begin(meta);
u16 jited:1,/* Is our filter JIT'ed? */
+   locked:1,   /* Program image locked? */
gpl_compatible:1, /* Is filter GPL compatible? 
*/
cb_access:1,/* Is control block accessed? */
dst_needed:1,   /* Do we need dst entry? */
@@ -554,22 +555,29 @@ static inline bool bpf_prog_was_classic(const struct 
bpf_prog *prog)
 #ifdef CONFIG_ARCH_HAS_SET_MEMORY
 static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
 {
-   set_memory_ro((unsigned long)fp, fp->pages);
+   fp->locked = 1;
+   WARN_ON_ONCE(set_memory_ro((unsigned long)fp, fp->pages));
 }
 
 static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
 {
-   set_memory_rw((unsigned long)fp, fp->pages);
+   if (fp->locked) {
+   WARN_ON_ONCE(set_memory_rw((unsigned long)fp, fp->pages));
+   /* In case set_memory_rw() fails, we want to be the first
+* to crash here instead of some random place later on.
+*/
+   fp->locked = 0;
+   }
 }
 
 static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
 {
-   set_memory_ro((unsigned long)hdr, hdr->pages);
+   WARN_ON_ONCE(set_memory_ro((unsigned long)hdr, hdr->pages));
 }
 
 static inline void bpf_jit_binary_unlock_ro(struct bpf_binary_header *hdr)
 {
-   set_memory_rw((unsigned long)hdr, hdr->pages);
+   WARN_ON_ONCE(set_memory_rw((unsigned long)hdr, hdr->pages));
 }
 #else
 static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
-- 
1.9.3



regression (4.10) - interface remove uevents not generated

2017-03-11 Thread Mantas Mikulėnas
Hello,

It seems that commit 002d8a1a6c11b9b2a8ac615095589111dd52749b ("net:
skip genenerating uevents for network namespaces that are exiting")
broke 'remove' uevents for *all* network interfaces, even for those in
the main/default namespace.

Other than breaking some of my udev rules, this also causes problems for
NetworkManager, which apparently relies on those uevents to update its
interface information cache. (I ended up reverting that commit locally
just so I could connect to VPNs again.)

This problem is present in both v4.10.1 and current master
(v4.11-rc1-290-g434fd6353b4c).

-- 
Mantas Mikulėnas 


[PATCH] Enable tx timestamping on loopback and dummy

2017-03-11 Thread Ezequiel Lara Gomez
Also, cleanup some warnings from timestamping code.

This enables testing of SO_TIMESTAMPING options by targetting localhost
addresses.

Tested on qemu using txtimestamping.c from the kernel selftests.

Signed-off-by: Ezequiel Lara Gomez 
---
 drivers/net/dummy.c|  1 +
 drivers/net/loopback.c | 14 +++---
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 2c80611..32fdc00 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -125,6 +125,7 @@ static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct 
net_device *dev)
dstats->tx_bytes += skb->len;
u64_stats_update_end(>syncp);
 
+   skb_tx_timestamp(skb);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
 }
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b23b719..8bcf479 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -13,7 +13,7 @@
  *
  * Alan Cox:   Fixed oddments for NET3.014
  * Alan Cox:   Rejig for NET3.029 snap #3
- * Alan Cox:   Fixed NET3.029 bugs and sped up
+ * Alan Cox:   Fixed NET3.029 bugs and sped up
  * Larry McVoy :   Tiny tweak to double performance
  * Alan Cox:   Backed out LMV's tweak - the linux mm
  * can't take it...
@@ -41,7 +41,7 @@
 #include 
 
 #include 
-#include 
+#include 
 
 #include 
 #include 
@@ -74,6 +74,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
struct pcpu_lstats *lb_stats;
int len;
 
+   skb_tx_timestamp(skb);
skb_orphan(skb);
 
/* Before queueing this packet to netif_rx(),
@@ -149,8 +150,8 @@ static void loopback_dev_free(struct net_device *dev)
 }
 
 static const struct net_device_ops loopback_ops = {
-   .ndo_init  = loopback_dev_init,
-   .ndo_start_xmit= loopback_xmit,
+   .ndo_init= loopback_dev_init,
+   .ndo_start_xmit  = loopback_xmit,
.ndo_get_stats64 = loopback_get_stats64,
.ndo_set_mac_address = eth_mac_addr,
 };
@@ -170,7 +171,7 @@ static void loopback_setup(struct net_device *dev)
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
netif_keep_dst(dev);
dev->hw_features= NETIF_F_GSO_SOFTWARE;
-   dev->features   = NETIF_F_SG | NETIF_F_FRAGLIST
+   dev->features   = NETIF_F_SG | NETIF_F_FRAGLIST
| NETIF_F_GSO_SOFTWARE
| NETIF_F_HW_CSUM
| NETIF_F_RXCSUM
@@ -206,7 +207,6 @@ static __net_init int loopback_net_init(struct net *net)
net->loopback_dev = dev;
return 0;
 
-
 out_free_netdev:
free_netdev(dev);
 out:
@@ -217,5 +217,5 @@ static __net_init int loopback_net_init(struct net *net)
 
 /* Registered in net/core/dev.c */
 struct pernet_operations __net_initdata loopback_net_ops = {
-   .init = loopback_net_init,
+   .init = loopback_net_init,
 };
-- 
1.9.1

Amazon Data Services Ireland Limited registered office: One Burlington Plaza, 
Burlington Road, Dublin 4, Ireland. Registered in Ireland. Registration number 
390566.



ANNOUNCE: Netdev Conference: What you have been missing

2017-03-11 Thread Jamal Hadi Salim

As announced last time, we are making more frequent announcements on
peo...@netdevconf.org

You can subscribe via mailman here:
https://lists.netdevconf.org/cgi-bin/mailman/listinfo/people

We urge people to subscribe to that list to get more up to date
information and conference discussions. We will still be sending
weekly summaries and announcements on the netdev list.

If you have already registered for the conference we will
very likely have registered you already.

Register early so we can plan better (and so you can save some $$).
https://onlineregistrations.ca/netdev21/

- hotel (unfortunately space is running out here. If you cant
get in and need help from us, please send email to i...@netdevconf.org):
https://www.netdevconf.org/2.1/hotel.html

And here's a summary of whats new since last posting on netdev:

1) New sponsors
a) Mojatatu - Gold sponsor
https://netdevconf.org/2.1/news.html?sponsor-mojatatu

b) Verizon - Platinum
https://netdevconf.org/2.1/news.html?news-verizon-sponsor
Accepted sessions:

2) New sessions
a) Talk:  XDP in practice: integrating XDP in our DDoS mitigation 
pipeline from Gilberto Bertin

https://netdevconf.org/2.1/news.html?news-bertin

b)Workshop: Network Performance Workshop chaired by
Alex Duyck
https://netdevconf.org/2.1/news.html?news-duyck

c) Talk: Netfilter's connection tracking subsystem by
Florian Westphal
https://netdevconf.org/2.1/news.html?news-netfilters-talk

d) Talk: IOT Without Things: Building virtual 6LoWPAN Mesh Networks
by Alexander Aring
https://netdevconf.org/2.1/news.html?news-aring-talk

e) Talk: Kernel HTTP/TCP/IP stack for HTTP DDoS mitigation
by Alexander Krizhanovsky
https://netdevconf.org/2.1/news.html?news-krizhanovsky-talk

A lot more exciting announcements coming.

cheers,
jamal


Re: [PATCH net] selftests/bpf: fix broken build

2017-03-11 Thread Daniel Borkmann

On 03/11/2017 07:05 AM, Alexei Starovoitov wrote:

Recent merge of 'linux-kselftest-4.11-rc1' tree broke bpf test build.
None of the tests were building and test_verifier.c had tons of compiler errors.
Fix it and add #ifdef CAP_IS_SUPPORTED to support old versions of libcap.
Tested on centos 6.8 and 7

Signed-off-by: Alexei Starovoitov 


Fix looks correct to me and makes the test suite work again.

Acked-by: Daniel Borkmann 
Tested-by: Daniel Borkmann 


Re: [PATCH] netfilter: Force fake conntrack entry to be at least 8 bytes aligned

2017-03-11 Thread Florian Westphal
Steven Rostedt (VMware)  wrote:
> Since the nfct and nfctinfo have been combined, the nf_conn structure
> must be at least 8 bytes aligned, as the 3 LSB bits are used for the
> nfctinfo. But there's a fake nf_conn structure to denote untracked
> connections, which is created by a PER_CPU construct. This does not
> guarantee that it will be 8 bytes aligned and can break the logic in
> determining the correct nfctinfo.
> 
> I triggered this on a 32bit machine with the following error:
[..]

Ugh.  Originally I had planned to also submit followup changes
to get rid of the untracked objects but that part got delayed.

> By using DEFINE/DECLARE_PER_CPU_ALIGNED we can enforce at least 8 byte
> alignment as all cache line sizes are at least 8 bytes or more.

Thanks for fixing this!

Acked-by: Florian Westphal 


[patch net-next 6/9] mlxsw: spectrum: Add periodic ACL rule activity update

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Introduce periodic task for dumping the activity status for the ACL
rule TCAM entries. This is done in order to emulate last use statistics.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 74 +-
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 1888092..d2f6cbb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -50,11 +50,17 @@
 #include "spectrum_acl_flex_keys.h"
 
 struct mlxsw_sp_acl {
+   struct mlxsw_sp *mlxsw_sp;
struct mlxsw_afk *afk;
struct mlxsw_afa *afa;
const struct mlxsw_sp_acl_ops *ops;
struct rhashtable ruleset_ht;
struct list_head rules;
+   struct {
+   struct delayed_work dw;
+   unsigned long interval; /* ms */
+#define MLXSW_SP_ACL_RULE_ACTIVITY_UPDATE_PERIOD_MS 1000
+   } rule_activity_update;
unsigned long priv[0];
/* priv has to be always the last item */
 };
@@ -85,6 +91,7 @@ struct mlxsw_sp_acl_rule {
unsigned long cookie; /* HT key */
struct mlxsw_sp_acl_ruleset *ruleset;
struct mlxsw_sp_acl_rule_info *rulei;
+   u64 last_used;
unsigned long priv[0];
/* priv has to be always the last item */
 };
@@ -459,6 +466,64 @@ mlxsw_sp_acl_rule_rulei(struct mlxsw_sp_acl_rule *rule)
return rule->rulei;
 }
 
+static int mlxsw_sp_acl_rule_activity_update(struct mlxsw_sp *mlxsw_sp,
+struct mlxsw_sp_acl_rule *rule)
+{
+   struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
+   const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
+   bool active;
+   int err;
+
+   err = ops->rule_activity_get(mlxsw_sp, rule->priv, );
+   if (err)
+   return err;
+   if (active)
+   rule->last_used = jiffies;
+   return 0;
+}
+
+static int mlxsw_sp_acl_rules_activity_update(struct mlxsw_sp_acl *acl)
+{
+   struct mlxsw_sp_acl_rule *rule;
+   int err;
+
+   /* Protect internal structures from changes */
+   rtnl_lock();
+   list_for_each_entry(rule, >rules, list) {
+   err = mlxsw_sp_acl_rule_activity_update(acl->mlxsw_sp,
+   rule);
+   if (err)
+   goto err_rule_update;
+   }
+   rtnl_unlock();
+   return 0;
+
+err_rule_update:
+   rtnl_unlock();
+   return err;
+}
+
+static void mlxsw_sp_acl_rule_activity_work_schedule(struct mlxsw_sp_acl *acl)
+{
+   unsigned long interval = acl->rule_activity_update.interval;
+
+   mlxsw_core_schedule_dw(>rule_activity_update.dw,
+  msecs_to_jiffies(interval));
+}
+
+static void mlxsw_sp_acl_rul_activity_update_work(struct work_struct *work)
+{
+   struct mlxsw_sp_acl *acl = container_of(work, struct mlxsw_sp_acl,
+   rule_activity_update.dw.work);
+   int err;
+
+   err = mlxsw_sp_acl_rules_activity_update(acl);
+   if (err)
+   dev_err(acl->mlxsw_sp->bus_info->dev, "Could not update acl 
activity");
+
+   mlxsw_sp_acl_rule_activity_work_schedule(acl);
+}
+
 #define MLXSW_SP_KDVL_ACT_EXT_SIZE 1
 
 static int mlxsw_sp_act_kvdl_set_add(void *priv, u32 *p_kvdl_index,
@@ -551,7 +616,7 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp)
if (!acl)
return -ENOMEM;
mlxsw_sp->acl = acl;
-
+   acl->mlxsw_sp = mlxsw_sp;
acl->afk = mlxsw_afk_create(MLXSW_CORE_RES_GET(mlxsw_sp->core,
   ACL_FLEX_KEYS),
mlxsw_sp_afk_blocks,
@@ -580,6 +645,12 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp)
goto err_acl_ops_init;
 
acl->ops = acl_ops;
+
+   /* Create the delayed work for the rule activity_update */
+   INIT_DELAYED_WORK(>rule_activity_update.dw,
+ mlxsw_sp_acl_rul_activity_update_work);
+   acl->rule_activity_update.interval = 
MLXSW_SP_ACL_RULE_ACTIVITY_UPDATE_PERIOD_MS;
+   mlxsw_core_schedule_dw(>rule_activity_update.dw, 0);
return 0;
 
 err_acl_ops_init:
@@ -598,6 +669,7 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp)
struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
const struct mlxsw_sp_acl_ops *acl_ops = acl->ops;
 
+   cancel_delayed_work_sync(_sp->acl->rule_activity_update.dw);
acl_ops->fini(mlxsw_sp, acl->priv);
WARN_ON(!list_empty(>rules));
rhashtable_destroy(>ruleset_ht);
-- 
2.7.4



[patch net-next 9/9] mlxsw: spectrum: Add support for TC flower offload statistics

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Add support for TC flower offload statistics including number of packets,
bytes and last use timestamp. Currently the statistics are gathered on a
per-rule basis.

Signed-off-by: Arkadi Sharshvesky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |  3 ++
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  2 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 28 +
 .../net/ethernet/mellanox/mlxsw/spectrum_flower.c  | 49 ++
 4 files changed, 82 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index af43048..475499b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1434,6 +1434,9 @@ static int mlxsw_sp_setup_tc(struct net_device *dev, u32 
handle,
mlxsw_sp_flower_destroy(mlxsw_sp_port, ingress,
tc->cls_flower);
return 0;
+   case TC_CLSFLOWER_STATS:
+   return mlxsw_sp_flower_stats(mlxsw_sp_port, ingress,
+tc->cls_flower);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index b4f32a6..5502232 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -688,6 +688,8 @@ int mlxsw_sp_flower_replace(struct mlxsw_sp_port 
*mlxsw_sp_port, bool ingress,
__be16 protocol, struct tc_cls_flower_offload *f);
 void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
 struct tc_cls_flower_offload *f);
+int mlxsw_sp_flower_stats(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
+ struct tc_cls_flower_offload *f);
 int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
  unsigned int counter_index, u64 *packets,
  u64 *bytes);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 87d0111..4d6920d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -92,6 +92,8 @@ struct mlxsw_sp_acl_rule {
struct mlxsw_sp_acl_ruleset *ruleset;
struct mlxsw_sp_acl_rule_info *rulei;
u64 last_used;
+   u64 last_packets;
+   u64 last_bytes;
unsigned long priv[0];
/* priv has to be always the last item */
 };
@@ -559,6 +561,32 @@ static void mlxsw_sp_acl_rul_activity_update_work(struct 
work_struct *work)
mlxsw_sp_acl_rule_activity_work_schedule(acl);
 }
 
+int mlxsw_sp_acl_rule_get_stats(struct mlxsw_sp *mlxsw_sp,
+   struct mlxsw_sp_acl_rule *rule,
+   u64 *packets, u64 *bytes, u64 *last_use)
+
+{
+   struct mlxsw_sp_acl_rule_info *rulei;
+   u64 current_packets;
+   u64 current_bytes;
+   int err;
+
+   rulei = mlxsw_sp_acl_rule_rulei(rule);
+   err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
+   _packets, _bytes);
+   if (err)
+   return err;
+
+   *packets = current_packets - rule->last_packets;
+   *bytes = current_bytes - rule->last_bytes;
+   *last_use = rule->last_used;
+
+   rule->last_bytes = current_bytes;
+   rule->last_packets = current_packets;
+
+   return 0;
+}
+
 #define MLXSW_SP_KDVL_ACT_EXT_SIZE 1
 
 static int mlxsw_sp_act_kvdl_set_add(void *priv, u32 *p_kvdl_index,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index f2ed0b3..28bc989 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -56,6 +56,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp 
*mlxsw_sp,
if (tc_no_actions(exts))
return 0;
 
+   /* Count action is inserted first */
+   err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei);
+   if (err)
+   return err;
+
tcf_exts_to_list(exts, );
list_for_each_entry(a, , list) {
if (is_tcf_gact_shot(a)) {
@@ -346,3 +351,47 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp_port 
*mlxsw_sp_port, bool ingress,
 
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
 }
+
+int mlxsw_sp_flower_stats(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
+ struct tc_cls_flower_offload *f)
+{
+   struct mlxsw_sp *mlxsw_sp = 

[patch net-next 4/9] mlxsw: spectrum_acl_tcam: Add support for retrieving TCAM entry activity

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Add support for retrieving TCAM entry activity. In order to support ACL
rule activity corresponding TCAM entry should be queried.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  2 ++
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c| 42 ++
 2 files changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index b0500b8..26718b1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -607,6 +607,8 @@ struct mlxsw_sp_acl_profile_ops {
void *ruleset_priv, void *rule_priv,
struct mlxsw_sp_acl_rule_info *rulei);
void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv);
+   int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
+bool *activity);
 };
 
 struct mlxsw_sp_acl_ops {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 6858439..3a24289 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -561,6 +561,24 @@ mlxsw_sp_acl_tcam_region_entry_remove(struct mlxsw_sp 
*mlxsw_sp,
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
 }
 
+static int
+mlxsw_sp_acl_tcam_region_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
+   struct mlxsw_sp_acl_tcam_region 
*region,
+   unsigned int offset,
+   bool *activity)
+{
+   char ptce2_pl[MLXSW_REG_PTCE2_LEN];
+   int err;
+
+   mlxsw_reg_ptce2_pack(ptce2_pl, true, 
MLXSW_REG_PTCE2_OP_QUERY_CLEAR_ON_READ,
+region->tcam_region_info, offset);
+   err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+   if (err)
+   return err;
+   *activity = mlxsw_reg_ptce2_a_get(ptce2_pl);
+   return 0;
+}
+
 #define MLXSW_SP_ACL_TCAM_CATCHALL_PRIO (~0U)
 
 static int
@@ -940,6 +958,19 @@ static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp 
*mlxsw_sp,
mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk);
 }
 
+static int
+mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
+struct mlxsw_sp_acl_tcam_entry *entry,
+bool *activity)
+{
+   struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk;
+   struct mlxsw_sp_acl_tcam_region *region = chunk->region;
+
+   return mlxsw_sp_acl_tcam_region_entry_activity_get(mlxsw_sp, region,
+  
entry->parman_item.index,
+  activity);
+}
+
 static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = {
MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
MLXSW_AFK_ELEMENT_DMAC,
@@ -1048,6 +1079,16 @@ mlxsw_sp_acl_tcam_flower_rule_del(struct mlxsw_sp 
*mlxsw_sp, void *rule_priv)
mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, >entry);
 }
 
+static int
+mlxsw_sp_acl_tcam_flower_rule_activity_get(struct mlxsw_sp *mlxsw_sp,
+  void *rule_priv, bool *activity)
+{
+   struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv;
+
+   return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, >entry,
+   activity);
+}
+
 static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = {
.ruleset_priv_size  = sizeof(struct 
mlxsw_sp_acl_tcam_flower_ruleset),
.ruleset_add= mlxsw_sp_acl_tcam_flower_ruleset_add,
@@ -1057,6 +1098,7 @@ static const struct mlxsw_sp_acl_profile_ops 
mlxsw_sp_acl_tcam_flower_ops = {
.rule_priv_size = sizeof(struct mlxsw_sp_acl_tcam_flower_rule),
.rule_add   = mlxsw_sp_acl_tcam_flower_rule_add,
.rule_del   = mlxsw_sp_acl_tcam_flower_rule_del,
+   .rule_activity_get  = mlxsw_sp_acl_tcam_flower_rule_activity_get,
 };
 
 static const struct mlxsw_sp_acl_profile_ops *
-- 
2.7.4



[patch net-next 5/9] mlxsw: spectrum: Add support for direct rule access

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Currently the ACL rules can be accessed only by hashing. In order to
dump the activity the rules are also placed in a list.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 3c5ea7e..1888092 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -54,6 +54,7 @@ struct mlxsw_sp_acl {
struct mlxsw_afa *afa;
const struct mlxsw_sp_acl_ops *ops;
struct rhashtable ruleset_ht;
+   struct list_head rules;
unsigned long priv[0];
/* priv has to be always the last item */
 };
@@ -80,6 +81,7 @@ struct mlxsw_sp_acl_ruleset {
 
 struct mlxsw_sp_acl_rule {
struct rhash_head ht_node; /* Member of rule HT */
+   struct list_head list;
unsigned long cookie; /* HT key */
struct mlxsw_sp_acl_ruleset *ruleset;
struct mlxsw_sp_acl_rule_info *rulei;
@@ -422,6 +424,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_rhashtable_insert;
 
+   list_add_tail(>list, _sp->acl->rules);
return 0;
 
 err_rhashtable_insert:
@@ -435,6 +438,7 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
 
+   list_del(>list);
rhashtable_remove_fast(>rule_ht, >ht_node,
   mlxsw_sp_acl_rule_ht_params);
ops->rule_del(mlxsw_sp, rule->priv);
@@ -570,6 +574,7 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp)
if (err)
goto err_rhashtable_init;
 
+   INIT_LIST_HEAD(>rules);
err = acl_ops->init(mlxsw_sp, acl->priv);
if (err)
goto err_acl_ops_init;
@@ -594,6 +599,7 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp)
const struct mlxsw_sp_acl_ops *acl_ops = acl->ops;
 
acl_ops->fini(mlxsw_sp, acl->priv);
+   WARN_ON(!list_empty(>rules));
rhashtable_destroy(>ruleset_ht);
mlxsw_afa_destroy(acl->afa);
mlxsw_afk_destroy(acl->afk);
-- 
2.7.4



[patch net-next 8/9] mlxsw: spectrum: Add support for counters on TCAM entries

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Add support for packets and byte statistics on TCAM entries. The counters
are allocated from the generic flow counters pool.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  7 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 35 ++
 2 files changed, 42 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 26718b1..b4f32a6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -588,6 +588,8 @@ struct mlxsw_sp_acl_rule_info {
unsigned int priority;
struct mlxsw_afk_element_values values;
struct mlxsw_afa_block *act_block;
+   unsigned int counter_index;
+   bool counter_valid;
 };
 
 enum mlxsw_sp_acl_profile {
@@ -652,6 +654,8 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
 int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
u32 action, u16 vid, u16 proto, u8 prio);
+int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
+struct mlxsw_sp_acl_rule_info *rulei);
 
 struct mlxsw_sp_acl_rule;
 
@@ -671,6 +675,9 @@ mlxsw_sp_acl_rule_lookup(struct mlxsw_sp *mlxsw_sp,
 unsigned long cookie);
 struct mlxsw_sp_acl_rule_info *
 mlxsw_sp_acl_rule_rulei(struct mlxsw_sp_acl_rule *rule);
+int mlxsw_sp_acl_rule_get_stats(struct mlxsw_sp *mlxsw_sp,
+   struct mlxsw_sp_acl_rule *rule,
+   u64 *packets, u64 *bytes, u64 *last_use);
 
 int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index d2f6cbb..87d0111 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -247,6 +247,27 @@ void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset);
 }
 
+static int
+mlxsw_sp_acl_rulei_counter_alloc(struct mlxsw_sp *mlxsw_sp,
+struct mlxsw_sp_acl_rule_info *rulei)
+{
+   int err;
+
+   err = mlxsw_sp_flow_counter_alloc(mlxsw_sp, >counter_index);
+   if (err)
+   return err;
+   rulei->counter_valid = true;
+   return 0;
+}
+
+static void
+mlxsw_sp_acl_rulei_counter_free(struct mlxsw_sp *mlxsw_sp,
+   struct mlxsw_sp_acl_rule_info *rulei)
+{
+   rulei->counter_valid = false;
+   mlxsw_sp_flow_counter_free(mlxsw_sp, rulei->counter_index);
+}
+
 struct mlxsw_sp_acl_rule_info *
 mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl)
 {
@@ -373,6 +394,13 @@ int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
}
 }
 
+int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
+struct mlxsw_sp_acl_rule_info *rulei)
+{
+   return mlxsw_afa_block_append_counter(rulei->act_block,
+ rulei->counter_index);
+}
+
 struct mlxsw_sp_acl_rule *
 mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
 struct mlxsw_sp_acl_ruleset *ruleset,
@@ -396,8 +424,14 @@ mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
err = PTR_ERR(rule->rulei);
goto err_rulei_create;
}
+
+   err = mlxsw_sp_acl_rulei_counter_alloc(mlxsw_sp, rule->rulei);
+   if (err)
+   goto err_counter_alloc;
return rule;
 
+err_counter_alloc:
+   mlxsw_sp_acl_rulei_destroy(rule->rulei);
 err_rulei_create:
kfree(rule);
 err_alloc:
@@ -410,6 +444,7 @@ void mlxsw_sp_acl_rule_destroy(struct mlxsw_sp *mlxsw_sp,
 {
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
 
+   mlxsw_sp_acl_rulei_counter_free(mlxsw_sp, rule->rulei);
mlxsw_sp_acl_rulei_destroy(rule->rulei);
kfree(rule);
mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset);
-- 
2.7.4



[patch net-next 7/9] mlxsw: spectrum: Add support for Policing and Counting action block

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Add support for Policing and Counting action block. This action block
will be used to bind counter to TCAM entries.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 .../mellanox/mlxsw/core_acl_flex_actions.c | 51 ++
 .../mellanox/mlxsw/core_acl_flex_actions.h |  2 +
 2 files changed, 53 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c 
b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
index fe3c6ea1..a984c36 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
@@ -760,3 +760,54 @@ int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block 
*block,
return err;
 }
 EXPORT_SYMBOL(mlxsw_afa_block_append_fwd);
+
+/* Policing and Counting Action
+ * 
+ * Policing and Counting action is used for binding policer and counter
+ * to ACL rules.
+ */
+
+#define MLXSW_AFA_POLCNT_CODE 0x08
+#define MLXSW_AFA_POLCNT_SIZE 1
+
+enum mlxsw_afa_polcnt_counter_set_type {
+   /* No count */
+   MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_NO_COUNT = 0x00,
+   /* Count packets and bytes */
+   MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS_BYTES = 0x03,
+   /* Count only packets */
+   MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS = 0x05,
+};
+
+/* afa_polcnt_counter_set_type
+ * Counter set type for flow counters.
+ */
+MLXSW_ITEM32(afa, polcnt, counter_set_type, 0x04, 24, 8);
+
+/* afa_polcnt_counter_index
+ * Counter index for flow counters.
+ */
+MLXSW_ITEM32(afa, polcnt, counter_index, 0x04, 0, 24);
+
+static inline void
+mlxsw_afa_polcnt_pack(char *payload,
+ enum mlxsw_afa_polcnt_counter_set_type set_type,
+ u32 counter_index)
+{
+   mlxsw_afa_polcnt_counter_set_type_set(payload, set_type);
+   mlxsw_afa_polcnt_counter_index_set(payload, counter_index);
+}
+
+int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
+  u32 counter_index)
+{
+   char *act = mlxsw_afa_block_append_action(block,
+ MLXSW_AFA_POLCNT_CODE,
+ MLXSW_AFA_POLCNT_SIZE);
+   if (!act)
+   return -ENOBUFS;
+   mlxsw_afa_polcnt_pack(act, 
MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS_BYTES,
+ counter_index);
+   return 0;
+}
+EXPORT_SYMBOL(mlxsw_afa_block_append_counter);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h 
b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
index 6e103ac..a03362c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
@@ -64,5 +64,7 @@ int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
   u8 local_port, bool in_port);
 int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
   u16 vid, u8 pcp, u8 et);
+int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
+  u32 counter_index);
 
 #endif
-- 
2.7.4



[patch net-next 2/9] mlxsw: reg: Add Monitoring General Purpose Counter Set register

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

The MGPC register retrieves generic flow counter value. It will be
used to query ACL counters.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 65 +++
 1 file changed, 65 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h 
b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index eb94a5a..393743c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -5506,6 +5506,70 @@ static inline void mlxsw_reg_mpsc_pack(char *payload, u8 
local_port, bool e,
mlxsw_reg_mpsc_rate_set(payload, rate);
 }
 
+/* MGPC - Monitoring General Purpose Counter Set Register
+ * The MGPC register retrieves and sets the General Purpose Counter Set.
+ */
+#define MLXSW_REG_MGPC_ID 0x9081
+#define MLXSW_REG_MGPC_LEN 0x18
+
+MLXSW_REG_DEFINE(mgpc, MLXSW_REG_MGPC_ID, MLXSW_REG_MGPC_LEN);
+
+enum mlxsw_reg_mgpc_counter_set_type {
+   /* No count */
+   MLXSW_REG_MGPC_COUNTER_SET_TYPE_NO_COUT = 0x00,
+   /* Count packets and bytes */
+   MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES = 0x03,
+   /* Count only packets */
+   MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS = 0x05,
+};
+
+/* reg_mgpc_counter_set_type
+ * Counter set type.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, mgpc, counter_set_type, 0x00, 24, 8);
+
+/* reg_mgpc_counter_index
+ * Counter index.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mgpc, counter_index, 0x00, 0, 24);
+
+enum mlxsw_reg_mgpc_opcode {
+   /* Nop */
+   MLXSW_REG_MGPC_OPCODE_NOP = 0x00,
+   /* Clear counters */
+   MLXSW_REG_MGPC_OPCODE_CLEAR = 0x08,
+};
+
+/* reg_mgpc_opcode
+ * Opcode.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, mgpc, opcode, 0x04, 28, 4);
+
+/* reg_mgpc_byte_counter
+ * Byte counter value.
+ * Access: RW
+ */
+MLXSW_ITEM64(reg, mgpc, byte_counter, 0x08, 0, 64);
+
+/* reg_mgpc_packet_counter
+ * Packet counter value.
+ * Access: RW
+ */
+MLXSW_ITEM64(reg, mgpc, packet_counter, 0x10, 0, 64);
+
+static inline void mlxsw_reg_mgpc_pack(char *payload, u32 counter_index,
+  enum mlxsw_reg_mgpc_opcode opcode,
+  enum mlxsw_reg_mgpc_counter_set_type 
set_type)
+{
+   MLXSW_REG_ZERO(mgpc, payload);
+   mlxsw_reg_mgpc_counter_index_set(payload, counter_index);
+   mlxsw_reg_mgpc_counter_set_type_set(payload, set_type);
+   mlxsw_reg_mgpc_opcode_set(payload, opcode);
+}
+
 /* SBPR - Shared Buffer Pools Register
  * ---
  * The SBPR configures and retrieves the shared buffer pools and configuration.
@@ -5979,6 +6043,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(mpar),
MLXSW_REG(mlcr),
MLXSW_REG(mpsc),
+   MLXSW_REG(mgpc),
MLXSW_REG(sbpr),
MLXSW_REG(sbcm),
MLXSW_REG(sbpm),
-- 
2.7.4



[patch net-next 3/9] mlxsw: spectrum: Add support for generic flow counter allocation

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Add support for allocating generic flow counter. Generic flow counter
can count packets or packets and bytes and can be assigned to different
hardware processes. First use will be for counting packets and bytes of
ACL rules, and will be introduced in the following patches.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/resources.h|  2 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 54 ++
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  7 +++
 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c | 23 -
 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h |  3 +-
 5 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h 
b/drivers/net/ethernet/mellanox/mlxsw/resources.h
index 15b8086..905a8e2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/resources.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h
@@ -45,6 +45,7 @@ enum mlxsw_res_id {
MLXSW_RES_ID_MAX_TRAP_GROUPS,
MLXSW_RES_ID_COUNTER_POOL_SIZE,
MLXSW_RES_ID_MAX_SPAN,
+   MLXSW_RES_ID_COUNTER_SIZE_PACKETS_BYTES,
MLXSW_RES_ID_MAX_SYSTEM_PORT,
MLXSW_RES_ID_MAX_LAG,
MLXSW_RES_ID_MAX_LAG_MEMBERS,
@@ -78,6 +79,7 @@ static u16 mlxsw_res_ids[] = {
[MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
[MLXSW_RES_ID_COUNTER_POOL_SIZE] = 0x2410,
[MLXSW_RES_ID_MAX_SPAN] = 0x2420,
+   [MLXSW_RES_ID_COUNTER_SIZE_PACKETS_BYTES] = 0x2443,
[MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502,
[MLXSW_RES_ID_MAX_LAG] = 0x2520,
[MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index b8237f9..af43048 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -139,6 +139,60 @@ MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16);
  */
 MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
 
+int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
+ unsigned int counter_index, u64 *packets,
+ u64 *bytes)
+{
+   char mgpc_pl[MLXSW_REG_MGPC_LEN];
+   int err;
+
+   mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_NOP,
+   MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES);
+   err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
+   if (err)
+   return err;
+   *packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl);
+   *bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl);
+   return 0;
+}
+
+static int mlxsw_sp_flow_counter_clear(struct mlxsw_sp *mlxsw_sp,
+  unsigned int counter_index)
+{
+   char mgpc_pl[MLXSW_REG_MGPC_LEN];
+
+   mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_CLEAR,
+   MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES);
+   return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
+}
+
+int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp,
+   unsigned int *p_counter_index)
+{
+   int err;
+
+   err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
+p_counter_index);
+   if (err)
+   return err;
+   err = mlxsw_sp_flow_counter_clear(mlxsw_sp, *p_counter_index);
+   if (err)
+   goto err_counter_clear;
+   return 0;
+
+err_counter_clear:
+   mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
+ *p_counter_index);
+   return err;
+}
+
+void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
+   unsigned int counter_index)
+{
+mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
+  counter_index);
+}
+
 static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
 const struct mlxsw_tx_info *tx_info)
 {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index dd59a9b..b0500b8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -679,5 +679,12 @@ int mlxsw_sp_flower_replace(struct mlxsw_sp_port 
*mlxsw_sp_port, bool ingress,
__be16 protocol, struct tc_cls_flower_offload *f);
 void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
 struct tc_cls_flower_offload *f);
+int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
+ unsigned int counter_index, u64 *packets,
+ u64 *bytes);
+int 

[patch net-next 1/9] mlxsw: spectrum: Add support for counter allocator

2017-03-11 Thread Jiri Pirko
From: Arkadi Sharshevsky 

Add implementation for counter allocator. The ASIC has special memory
pool for various counting purposes. Counter memory is distributed between
equal size banks.

The static sub-pool configuration should specify the following parameters
for each sub-pool:
- Number of required banks.
- Maximum entry size.

Each module can add dedicated sub-pool or use existing one.

Signed-off-by: Arkadi Sharshevsky 
Reviewed-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/Makefile   |   3 +-
 drivers/net/ethernet/mellanox/mlxsw/resources.h|   2 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |  10 ++
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |   2 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c | 177 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h |  54 +++
 6 files changed, 247 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h

diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile 
b/drivers/net/ethernet/mellanox/mlxsw/Makefile
index 6b6c30d..95fcacf 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile
@@ -15,7 +15,8 @@ obj-$(CONFIG_MLXSW_SPECTRUM)  += mlxsw_spectrum.o
 mlxsw_spectrum-objs:= spectrum.o spectrum_buffers.o \
   spectrum_switchdev.o spectrum_router.o \
   spectrum_kvdl.o spectrum_acl_tcam.o \
-  spectrum_acl.o spectrum_flower.o
+  spectrum_acl.o spectrum_flower.o \
+  spectrum_cnt.o
 mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB)+= spectrum_dcb.o
 obj-$(CONFIG_MLXSW_MINIMAL)+= mlxsw_minimal.o
 mlxsw_minimal-objs := minimal.o
diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h 
b/drivers/net/ethernet/mellanox/mlxsw/resources.h
index bce8c2e..15b8086 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/resources.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h
@@ -43,6 +43,7 @@ enum mlxsw_res_id {
MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE,
MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE,
MLXSW_RES_ID_MAX_TRAP_GROUPS,
+   MLXSW_RES_ID_COUNTER_POOL_SIZE,
MLXSW_RES_ID_MAX_SPAN,
MLXSW_RES_ID_MAX_SYSTEM_PORT,
MLXSW_RES_ID_MAX_LAG,
@@ -75,6 +76,7 @@ static u16 mlxsw_res_ids[] = {
[MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002,
[MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003,
[MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
+   [MLXSW_RES_ID_COUNTER_POOL_SIZE] = 0x2410,
[MLXSW_RES_ID_MAX_SPAN] = 0x2420,
[MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502,
[MLXSW_RES_ID_MAX_LAG] = 0x2520,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 2104ee4..b8237f9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -66,6 +66,7 @@
 #include "port.h"
 #include "trap.h"
 #include "txheader.h"
+#include "spectrum_cnt.h"
 
 static const char mlxsw_sp_driver_name[] = "mlxsw_spectrum";
 static const char mlxsw_sp_driver_version[] = "1.0";
@@ -3224,6 +3225,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_acl_init;
}
 
+   err = mlxsw_sp_counter_pool_init(mlxsw_sp);
+   if (err) {
+   dev_err(mlxsw_sp->bus_info->dev, "Failed to init counter 
pool\n");
+   goto err_counter_pool_init;
+   }
+
err = mlxsw_sp_ports_create(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n");
@@ -3233,6 +3240,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
return 0;
 
 err_ports_create:
+   mlxsw_sp_counter_pool_fini(mlxsw_sp);
+err_counter_pool_init:
mlxsw_sp_acl_fini(mlxsw_sp);
 err_acl_init:
mlxsw_sp_span_fini(mlxsw_sp);
@@ -3255,6 +3264,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
 
mlxsw_sp_ports_remove(mlxsw_sp);
+   mlxsw_sp_counter_pool_fini(mlxsw_sp);
mlxsw_sp_acl_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_router_fini(mlxsw_sp);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 3bc1b09..dd59a9b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -246,6 +246,7 @@ struct mlxsw_sp_router {
 };
 
 struct mlxsw_sp_acl;
+struct mlxsw_sp_counter_pool;
 
 struct mlxsw_sp {
struct {
@@ -281,6 +282,7 @@ struct mlxsw_sp {

[patch net-next 0/9] mlxsw: Add support for TC flower offload statistics

2017-03-11 Thread Jiri Pirko
From: Jiri Pirko 

Arkadi says:
This patchset adds support for retrieving TC flower statistics for
offloaded rules, which includes packets count, bytes count and last used
time stamp. Currently The statistics are gathered on a per-rule basis.

This patchset also includes generic allocator for counters.

Arkadi Sharshevsky (9):
  mlxsw: spectrum: Add support for counter allocator
  mlxsw: reg: Add Monitoring General Purpose Counter Set register
  mlxsw: spectrum: Add support for generic flow counter allocation
  mlxsw: spectrum_acl_tcam: Add support for retrieving TCAM entry
activity
  mlxsw: spectrum: Add support for direct rule access
  mlxsw: spectrum: Add periodic ACL rule activity update
  mlxsw: spectrum: Add support for Policing and Counting action block
  mlxsw: spectrum: Add support for counters on TCAM entries
  mlxsw: spectrum: Add support for TC flower offload statistics

 drivers/net/ethernet/mellanox/mlxsw/Makefile   |   3 +-
 .../mellanox/mlxsw/core_acl_flex_actions.c |  51 ++
 .../mellanox/mlxsw/core_acl_flex_actions.h |   2 +
 drivers/net/ethernet/mellanox/mlxsw/reg.h  |  65 +++
 drivers/net/ethernet/mellanox/mlxsw/resources.h|   4 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |  67 +++
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  20 +++
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 143 ++-
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c|  42 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c | 198 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h |  53 ++
 .../net/ethernet/mellanox/mlxsw/spectrum_flower.c  |  49 +
 12 files changed, 695 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h

-- 
2.7.4