Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel

2016-06-20 Thread Takashi Iwai
On Mon, 20 Jun 2016 17:21:26 +0200,
Richard Cochran wrote:
> 
> On Mon, Jun 20, 2016 at 02:31:48PM +0200, Richard Cochran wrote:
> > Where is this "audio_time" program of which you speak?
> 
> Never mind, found it in alsa-lib.
> 
> I still would appreciate an answer to my other questions, though...

Currently HD-audio (both ASoC and legacy ones) are the only drivers
providing the link timestamp.  In the recent code, it's PCM
get_time_info ops, so you can easily grep it.


HTH,

Takashi


Re: [PATCH v10 08/22] IB/hns: Add icm support

2016-06-20 Thread Wei Hu (Xavier)



On 2016/6/20 21:04, Leon Romanovsky wrote:

On Mon, Jun 20, 2016 at 05:48:15PM +0800, Wei Hu (Xavier) wrote:


On 2016/6/20 17:27, Leon Romanovsky wrote:

On Mon, Jun 20, 2016 at 03:49:24PM +0800, Wei Hu (Xavier) wrote:

On 2016/6/20 14:06, Leon Romanovsky wrote:

On Mon, Jun 20, 2016 at 12:37:40PM +0800, Wei Hu (Xavier) wrote:

On 2016/6/17 17:58, Leon Romanovsky wrote:

On Thu, Jun 16, 2016 at 10:35:16PM +0800, Lijun Ou wrote:

This patch mainly added icm support for RoCE. It initializes icm
which managers the relative memory blocks for RoCE. The data
structures of RoCE will be located in it. For example, CQ table,
QP table and MTPT table so on.

Signed-off-by: Wei Hu 
Signed-off-by: Nenglong Zhao 
Signed-off-by: Lijun Ou 
---

<...>


+

Another question which you didn't answer [1].

"I wonder if you have the same needs for ICM as it is in mlx4 device.
Do you have firmware?"

[1] http://marc.info/?l=linux-rdma=146545553104913=2

Hi, Leon
 Now we haven't firmware.
 But hardware still need memory for QPC\CQC\MTPT\mtt etc.

ICM stands for InfiniHost (Interconnect) Context Memory is a specific
memory place to share between host <-> FW and host <-> HW if HW is
aware of specific structures.

I assume that in your case, it is enough to allocate memory region and
supply it to HW. Am I right?

For Our hardware,
1. ICM has a memory management method, It's very good for QPC\CQC\MTPT\mtt
etc. we need it.

You need special HW to leverage its. AFAIK it is Mellanox specific.
For our hardware, we use ICM to memory management, the memory shared 
with host and HW.

QPC\CQC\MTPT\mtt has specific memory requirement.
QPC\CQC\MTPT need continuous memory. we use ICM to management the block 
of memory. It's very good!

2. The meomry for QPC\CQC\MTPT\mtt only used for RoCE hardware and driver,
we don't want use MR.

I didn't mean Infiniband MR, but memory region returned from standard
allocation functions (kmalloc, ...).


3. Now we haven't firmware, maybe we need it next version.

You are always invited to add support once it will be needed, no need to
add it in advance.

Thanks





more fallout from sch locking changes?

2016-06-20 Thread David Ahern
I just updated to top of next-net tree (697666eac66) and still seeing an 
occasional lockdep splat. It is not reliable to the point I would 
attempt a git bisect. 2 splats -- 1 for ipv4 (first login to VM after 
boot) and ipv6 (second login to VM after boot). Perhaps it is more 
fallout of the packet scheduling changes you have been making this 
iteration. Just a guess based on sch_direct_xmit in both traces.


IPv4 one:


[  189.120375] [ cut here ]
[  189.121476] WARNING: CPU: 2 PID: 1463 at 
../kernel/locking/lockdep.c:2099 validate_chain.isra.37+0x25b/0xa5b

[  189.123420] DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)
[  189.124641] Modules linked in:
[  189.125353] CPU: 2 PID: 1463 Comm: sshd Not tainted 4.7.0-rc2+ #310
[  189.126614] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), 
BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
[  189.128600]   8800b977b718 8127e51e 
8800b977b768
[  189.130173]   8800b977b758 8104d190 
0833b977b7d0
[  189.131804]  81decec0 6519 01a1c10e0898ad0c 
8800bac64680

[  189.133277] Call Trace:
[  189.133759]  [] dump_stack+0x81/0xb6
[  189.134718]  [] __warn+0xc5/0xe0
[  189.135611]  [] warn_slowpath_fmt+0x46/0x4e
[  189.136681]  [] validate_chain.isra.37+0x25b/0xa5b
[  189.137874]  [] ? kvm_clock_read+0x25/0x2e
[  189.138932]  [] ? kvm_sched_clock_read+0x9/0x12
[  189.140084]  [] ? paravirt_sched_clock+0x9/0xd
[  189.141193]  [] __lock_acquire+0x5e4/0x690
[  189.142130]  [] ? __lock_acquire+0x5e4/0x690
[  189.143006]  [] lock_acquire+0x140/0x1d8
[  189.143832]  [] ? sch_direct_xmit+0x6f/0x167
[  189.144712]  [] _raw_spin_lock+0x2f/0x65
[  189.145547]  [] ? sch_direct_xmit+0x6f/0x167
[  189.146426]  [] sch_direct_xmit+0x6f/0x167
[  189.147276]  [] __dev_queue_xmit+0x43b/0x72d
[  189.148154]  [] ? eth_header+0x27/0xaf
[  189.148960]  [] dev_queue_xmit+0xb/0xd
[  189.149768]  [] neigh_resolve_output+0x113/0x12e
[  189.150722]  [] ip_finish_output2+0x3c0/0x41c
[  189.151619]  [] ip_finish_output+0x132/0x13e
[  189.152548]  [] NF_HOOK_COND.constprop.43+0x21/0x8a
[  189.153557]  [] ? lock_is_held+0x69/0x70
[  189.154347]  [] ? rcu_read_lock_held+0x29/0x2f
[  189.155200]  [] ip_output+0x65/0x6a
[  189.155920]  [] dst_output+0x2b/0x30
[  189.156649]  [] ip_local_out+0x2a/0x31
[  189.157425]  [] ip_queue_xmit+0x2c3/0x315
[  189.158223]  [] tcp_transmit_skb+0x696/0x6c5
[  189.159048]  [] tcp_write_xmit+0x820/0xb1c
[  189.159863]  [] ? __might_fault+0xa0/0xa2
[  189.160659]  [] ? copy_from_iter+0x1cb/0x296
[  189.161493]  [] __tcp_push_pending_frames+0x2b/0x67
[  189.162409]  [] tcp_push+0x94/0xff
[  189.163176]  [] tcp_sendmsg+0x775/0x83a
[  189.164006]  [] inet_sendmsg+0x35/0x5c
[  189.164760]  [] sock_sendmsg_nosec+0x12/0x1d
[  189.165556]  [] sock_write_iter+0x75/0x8d
[  189.166324]  [] __vfs_write+0x77/0xa0
[  189.167040]  [] vfs_write+0xa2/0xc6
[  189.167723]  [] SyS_write+0x4b/0x79
[  189.168437]  [] entry_SYSCALL_64_fastpath+0x1f/0xbd
[  189.169318]  [] ? trace_hardirqs_off_caller+0xbc/0x122
[  189.170247] ---[ end trace 24ee736782fa0dbd ]---
[  189.170870]
[  189.171084] ==
[  189.171555] [chain_key collision ]
[  189.172020] 4.7.0-rc2+ #310 Tainted: GW
[  189.172729] --
[  189.173192] sshd/1463: Hash chain already cached but the contents 
don't match!

[  189.174236] Held locks:depth: 6
[  189.174707]  class_idx:1253 -> chain_key:04e5 
(sk_lock-AF_INET){+.+.+.}, at: [] lock_sock+0xb/0xd
[  189.176376]  class_idx:26 -> chain_key:009ca01a 
(rcu_read_lock){..}, at: [] rcu_lock_acquire+0x0/0x20
[  189.178014]  class_idx:898 -> chain_key:001394034382 
(rcu_read_lock_bh){..}, at: [] 
rcu_lock_acquire+0x0/0x20
[  189.179712]  class_idx:898 -> chain_key:0002728068704382 
(rcu_read_lock_bh){..}, at: [] 
rcu_lock_acquire+0x0/0x20
[  189.181374]  class_idx:1221 -> chain_key:4e500d0e087044c5 
(dev->qdisc_running_key ?: _running_key){+.}, at: 
[] __dev_queue_xmit+0x40c/0x72d
[  189.183400]  class_idx:1222 -> chain_key:01a1c10e0898ad0c 
(_xmit_ETHER#2){+.-...}, at: [] sch_direct_xmit+0x6f/0x167

[  189.185178] Locks in cached chain:depth: 6
[  189.185791]  class_idx:1252 -> chain_key:04e4 
(((>rs_timer))){+.-...}
[  189.186957]  class_idx:26 -> chain_key:009c801a 
(rcu_read_lock){..}
[  189.187991]  class_idx:898 -> chain_key:001390034382 
(rcu_read_lock_bh){..}
[  189.189023]  class_idx:898 -> chain_key:0002720068704382 
(rcu_read_lock_bh){..}
[  189.190050]  class_idx:1221 -> chain_key:4e400d0e087044c5 
(dev->qdisc_running_key ?: _running_key){+.}
[  189.191370]  class_idx:1220 -> chain_key:01a1c10e0898ad0c 
(&(>lock)->rlock#3){+.-...}

[  189.192503]
[  189.192503] stack backtrace:
[  189.193052] CPU: 2 PID: 1463 Comm: sshd Tainted: GW 
4.7.0-rc2+ #310
[  189.193988] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), 

Re: [PATCH] net: vrf: replace hard tab with space in assignment

2016-06-20 Thread David Ahern

On 6/20/16 9:39 PM, Chris Packham wrote:

The assignment of rth->dst.output in vrf_rt6_create() and
vrf_rtable_create() used a hard tab before the '='. The neighboring
assignments did not. Make the assignment of rth->dst.output consistent
with the surrounding code.

Signed-off-by: Chris Packham 
---
 drivers/net/vrf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)


Acked-by: David Ahern 



[PATCH net-next 05/19] net: hns: Remove unnecessary device resource free

2016-06-20 Thread Yisen Zhuang
From: Qianqian Xie 

The driver uses devm_ioremap_resource, it will unmap the map
automatically, remove the unnecessary the resource free.

Signed-off-by: Qianqian Xie 
Reported-by: Kefeng Wang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 39 +++---
 1 file changed, 4 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 422f97d..b8b2ff9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -176,7 +176,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
desc_num > HNS_DSAF_MAX_DESC_CNT) {
dev_err(dsaf_dev->dev, "get desc-num(%d) fail, ret=%d!\n",
desc_num, ret);
-   goto unmap_base_addr;
+   return -EINVAL;
}
dsaf_dev->desc_num = desc_num;
 
@@ -192,7 +192,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
if (ret < 0) {
dev_err(dsaf_dev->dev,
"get buf-size fail, ret=%d!\r\n", ret);
-   goto unmap_base_addr;
+   return ret;
}
dsaf_dev->buf_size = buf_size;
 
@@ -200,7 +200,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
if (dsaf_dev->buf_size_type < 0) {
dev_err(dsaf_dev->dev,
"buf_size(%d) is wrong!\n", buf_size);
-   goto unmap_base_addr;
+   return -EINVAL;
}
 
dsaf_dev->misc_op = hns_misc_op_get(dsaf_dev);
@@ -213,32 +213,6 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
dev_err(dsaf_dev->dev, "set mask to 64bit fail!\n");
 
return 0;
-
-unmap_base_addr:
-   if (dsaf_dev->io_base)
-   iounmap(dsaf_dev->io_base);
-   if (dsaf_dev->ppe_base)
-   iounmap(dsaf_dev->ppe_base);
-   if (dsaf_dev->sds_base)
-   iounmap(dsaf_dev->sds_base);
-   if (dsaf_dev->sc_base)
-   iounmap(dsaf_dev->sc_base);
-   return ret;
-}
-
-static void hns_dsaf_free_cfg(struct dsaf_device *dsaf_dev)
-{
-   if (dsaf_dev->io_base)
-   iounmap(dsaf_dev->io_base);
-
-   if (dsaf_dev->ppe_base)
-   iounmap(dsaf_dev->ppe_base);
-
-   if (dsaf_dev->sds_base)
-   iounmap(dsaf_dev->sds_base);
-
-   if (dsaf_dev->sc_base)
-   iounmap(dsaf_dev->sc_base);
 }
 
 /**
@@ -2645,7 +2619,7 @@ static int hns_dsaf_probe(struct platform_device *pdev)
 
ret = hns_dsaf_init(dsaf_dev);
if (ret)
-   goto free_cfg;
+   goto free_dev;
 
ret = hns_mac_init(dsaf_dev);
if (ret)
@@ -2670,9 +2644,6 @@ uninit_mac:
 uninit_dsaf:
hns_dsaf_free(dsaf_dev);
 
-free_cfg:
-   hns_dsaf_free_cfg(dsaf_dev);
-
 free_dev:
hns_dsaf_free_dev(dsaf_dev);
 
@@ -2695,8 +2666,6 @@ static int hns_dsaf_remove(struct platform_device *pdev)
 
hns_dsaf_free(dsaf_dev);
 
-   hns_dsaf_free_cfg(dsaf_dev);
-
hns_dsaf_free_dev(dsaf_dev);
 
return 0;
-- 
1.9.1



[PATCH net-next 06/19] net: hns: fix the error info when dma_set_mask_and_coherent fail

2016-06-20 Thread Yisen Zhuang
From: Qianqian Xie 

The error info should be printed as "set mask to 64bit fail!" instead of
"set mask to 32bit fail!" in dma_set_mask_and_coherent().

Signed-off-by: Qianqian Xie 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index b978db4..00e529f 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1972,7 +1972,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
dev_dbg(dev, "set mask to 64bit\n");
else
-   dev_err(dev, "set mask to 32bit fail!\n");
+   dev_err(dev, "set mask to 64bit fail!\n");
 
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(ndev);
-- 
1.9.1



[PATCH net-next 16/19] net: hns: fix bug that alloc skb fail lead to port unavailable

2016-06-20 Thread Yisen Zhuang
From: Jun He 

When hns_nic_poll_rx_skb alloc skb fail, it will break receive cycle and
read new fbd_num to start new receive cycle. It recomputes cycle num is
fbd_num minus clean_count, actually this cycle num is too big because
it drop out receive cycle. It brings about the port unavailable.

So we will goto out when alloc skb fail to fix this bug.

Signed-off-by: Jun He 
Signed-off-by: Ding Tianhong 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index f49246d..c0ce37b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -768,10 +768,10 @@ recv:
clean_count = 0;
}
 
-   /* poll one pkg*/
+   /* poll one pkt*/
err = hns_nic_poll_rx_skb(ring_data, , );
if (unlikely(!skb)) /* this fault cannot be repaired */
-   break;
+   goto out;
 
recv_bds += bnum;
clean_count += bnum;
@@ -797,6 +797,7 @@ recv:
}
}
 
+out:
/* make all data has been write before submit */
if (clean_count > 0)
hns_nic_alloc_rx_buffers(ring_data, clean_count);
-- 
1.9.1



[PATCH net-next 04/19] net: hns: typo fix of annotation info for hns_nic_reset_subtask()

2016-06-20 Thread Yisen Zhuang
From: Qianqian Xie 

The annotation info for hns_nic_reset_subtask() should be
"for resetting subtask" instead of "for resetting suntask".

Signed-off-by: Qianqian Xie 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 15200e4..b978db4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1633,7 +1633,7 @@ static void hns_nic_dump(struct hns_nic_priv *priv)
}
 }
 
-/* for resetting suntask*/
+/* for resetting subtask */
 static void hns_nic_reset_subtask(struct hns_nic_priv *priv)
 {
enum hnae_port_type type = priv->ae_handle->port_type;
-- 
1.9.1



[PATCH net-next 08/19] net: hns: fix ethtool loopback fail bug

2016-06-20 Thread Yisen Zhuang
From: Kejian Yan 

When run ethtool cmd(ethtool -t ethx) again and again for a long
time, it will be probabilistically fail. The PHYs' registers may
be on different pages, so it must be switch to the right page
before setting PHYs' registers.
And __lb_up() calls phy_start() to startup the PHYs device, but
this function may change Copper Control Register(Page 0, Register 0)
to an other value. It would cause phy loopback test fail. if we
remove phy_start(), we have to remove the relative phy_stop(),
phy_disconnect() when doing phy loopback to keep the phy stay in
right status.

Reported-by: hejun 
Signed-off-by: Kejian Yan 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 35 ++--
 1 file changed, 14 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index a809f52..5b3dccb 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -242,6 +242,7 @@ static const char hns_nic_test_strs[][ETH_GSTRING_LEN] = {
 static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
 {
 #define COPPER_CONTROL_REG 0
+#define PHY_POWER_DOWN BIT(11)
 #define PHY_LOOP_BACK BIT(14)
u16 val = 0;
 
@@ -252,33 +253,40 @@ static int hns_nic_config_phy_loopback(struct phy_device 
*phy_dev, u8 en)
/* speed : 1000M */
phy_write(phy_dev, HNS_PHY_PAGE_REG, 2);
phy_write(phy_dev, 21, 0x1046);
+
+   phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
/* Force Master */
phy_write(phy_dev, 9, 0x1F00);
+
/* Soft-reset */
phy_write(phy_dev, 0, 0x9140);
/* If autoneg disabled,two soft-reset operations */
phy_write(phy_dev, 0, 0x9140);
-   phy_write(phy_dev, 22, 0xFA);
+
+   phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);
 
/* Default is 0x0400 */
phy_write(phy_dev, 1, 0x418);
 
/* Force 1000M Link, Default is 0x0200 */
phy_write(phy_dev, 7, 0x20C);
-   phy_write(phy_dev, 22, 0);
+   phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
 
-   /* Enable MAC loop-back */
+   /* Enable PHY loop-back */
val = phy_read(phy_dev, COPPER_CONTROL_REG);
val |= PHY_LOOP_BACK;
+   val &= ~PHY_POWER_DOWN;
phy_write(phy_dev, COPPER_CONTROL_REG, val);
} else {
-   phy_write(phy_dev, 22, 0xFA);
+   phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);
phy_write(phy_dev, 1, 0x400);
phy_write(phy_dev, 7, 0x200);
-   phy_write(phy_dev, 22, 0);
+   phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
+   phy_write(phy_dev, 9, 0xF00);
 
val = phy_read(phy_dev, COPPER_CONTROL_REG);
val &= ~PHY_LOOP_BACK;
+   val |= PHY_POWER_DOWN;
phy_write(phy_dev, COPPER_CONTROL_REG, val);
}
return 0;
@@ -339,28 +347,16 @@ static int __lb_up(struct net_device *ndev,
 
hns_nic_net_reset(ndev);
 
-   if (priv->phy) {
-   phy_disconnect(priv->phy);
-   msleep(100);
-
-   ret = hns_nic_init_phy(ndev, h);
-   if (ret)
-   return ret;
-   }
-
ret = __lb_setup(ndev, loop_mode);
if (ret)
return ret;
 
-   msleep(100);
+   msleep(200);
 
ret = h->dev->ops->start ? h->dev->ops->start(h) : 0;
if (ret)
return ret;
 
-   if (priv->phy)
-   phy_start(priv->phy);
-
/* link adjust duplex*/
if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
speed = 1000;
@@ -561,9 +557,6 @@ static int __lb_down(struct net_device *ndev)
   __func__,
   ret);
 
-   if (priv->phy)
-   phy_stop(priv->phy);
-
if (h->dev->ops->stop)
h->dev->ops->stop(h);
 
-- 
1.9.1



[PATCH net-next 19/19] net: hns: bug fix about TSO on|off when there is traffic

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

When enable/disable tso, the driver tries to access the hardware register,
but this operation will cause the port unavalible when there is traffic.
This patch tries to enable TSO when initialize, then control tso through
TSE bit in transmit descriptor.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index c0ce37b..d5297ec 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1441,7 +1441,6 @@ static int hns_nic_set_features(struct net_device *netdev,
netdev_features_t features)
 {
struct hns_nic_priv *priv = netdev_priv(netdev);
-   struct hnae_handle *h = priv->ae_handle;
 
switch (priv->enet_ver) {
case AE_VERSION_1:
@@ -1454,11 +1453,9 @@ static int hns_nic_set_features(struct net_device 
*netdev,
priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tso;
/* The chip only support 7*4096 */
netif_set_gso_max_size(netdev, 7 * 4096);
-   h->dev->ops->set_tso_stats(h, 1);
} else {
priv->ops.fill_desc = fill_v2_desc;
priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tx;
-   h->dev->ops->set_tso_stats(h, 0);
}
break;
}
@@ -1804,11 +1801,14 @@ static void hns_nic_set_priv_ops(struct net_device 
*netdev)
priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tso;
/* This chip only support 7*4096 */
netif_set_gso_max_size(netdev, 7 * 4096);
-   h->dev->ops->set_tso_stats(h, 1);
} else {
priv->ops.fill_desc = fill_v2_desc;
priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tx;
}
+   /* enable tso when init
+* control tso on/off through TSE bit in bd
+*/
+   h->dev->ops->set_tso_stats(h, 1);
}
 }
 
-- 
1.9.1



[PATCH net-next 03/19] net: hns: add skb_reset_mac_header() after skb being alloc

2016-06-20 Thread Yisen Zhuang
From: Kejian Yan 

HNS receives a packet without doing anything, but it should call
skb_reset_mac_header() to initialize the header before using
eth_hdr().

Fixes: 0d6b425a3773c3445b0f51b2f333821beaacb619
Signed-off-by: Kejian Yan 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index ad742a6..15200e4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -600,6 +600,7 @@ static int hns_nic_poll_rx_skb(struct hns_nic_ring_data 
*ring_data,
ring->stats.sw_err_cnt++;
return -ENOMEM;
}
+   skb_reset_mac_header(skb);
 
prefetchw(skb->data);
length = le16_to_cpu(desc->rx.pkt_len);
-- 
1.9.1



[PATCH net-next 02/19] net: hns: fix hns dsaf v1 dont support tx_pause close

2016-06-20 Thread Yisen Zhuang
From: Qianqian Xie 

For service port, hns dsaf v1 support to close tx_pause.
However, the port will be invalid when it run command
ethtool to close tx_pause. This patch will fix it.

Signed-off-by: Qianqian Xie 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index ac03c4a..422f97d 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -1114,10 +1114,10 @@ int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device 
*dsaf_dev, int mac_id,
 u32 en)
 {
if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
-   if (!en)
+   if (!en) {
dev_err(dsaf_dev->dev, "dsafv1 can't close 
rx_pause!\n");
-
-   return -EINVAL;
+   return -EINVAL;
+   }
}
 
dsaf_set_dev_bit(dsaf_dev, DSAF_PAUSE_CFG_REG + mac_id * 4,
-- 
1.9.1



[PATCH net-next 17/19] net: hns: fix sbm default parameters config error

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

The default sbm config parameter leaves little buffer when there is heavy
traffic, which will cause packets drop. This patch changes them to make
enough buffers for handling packets.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 40 ++
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h  | 16 +++--
 2 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 7f5c248..67e8e13 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -516,10 +516,10 @@ static void hns_dsafv2_sbm_bp_wl_cfg(struct dsaf_device 
*dsaf_dev)
o_sbm_bp_cfg = dsaf_read_dev(dsaf_dev, reg);
dsaf_set_field(o_sbm_bp_cfg,
   DSAFV2_SBM_CFG3_SET_BUF_NUM_NO_PFC_M,
-  DSAFV2_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 110);
+  DSAFV2_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 48);
dsaf_set_field(o_sbm_bp_cfg,
   DSAFV2_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M,
-  DSAFV2_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 160);
+  DSAFV2_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 80);
dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
 
/* for no enable pfc mode */
@@ -527,29 +527,39 @@ static void hns_dsafv2_sbm_bp_wl_cfg(struct dsaf_device 
*dsaf_dev)
o_sbm_bp_cfg = dsaf_read_dev(dsaf_dev, reg);
dsaf_set_field(o_sbm_bp_cfg,
   DSAFV2_SBM_CFG4_SET_BUF_NUM_NO_PFC_M,
-  DSAFV2_SBM_CFG4_SET_BUF_NUM_NO_PFC_S, 128);
+  DSAFV2_SBM_CFG4_SET_BUF_NUM_NO_PFC_S, 192);
dsaf_set_field(o_sbm_bp_cfg,
   DSAFV2_SBM_CFG4_RESET_BUF_NUM_NO_PFC_M,
-  DSAFV2_SBM_CFG4_RESET_BUF_NUM_NO_PFC_S, 192);
+  DSAFV2_SBM_CFG4_RESET_BUF_NUM_NO_PFC_S, 240);
dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
}
 
/* PPE */
-   reg = DSAF_SBM_BP_CFG_2_PPE_REG_0_REG + 0x80 * i;
-   o_sbm_bp_cfg = dsaf_read_dev(dsaf_dev, reg);
-   dsaf_set_field(o_sbm_bp_cfg, DSAFV2_SBM_CFG2_SET_BUF_NUM_M,
-  DSAFV2_SBM_CFG2_SET_BUF_NUM_S, 10);
-   dsaf_set_field(o_sbm_bp_cfg, DSAFV2_SBM_CFG2_RESET_BUF_NUM_M,
-  DSAFV2_SBM_CFG2_RESET_BUF_NUM_S, 12);
-   dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
+   for (i = 0; i < DSAFV2_SBM_PPE_CHN; i++) {
+   reg = DSAF_SBM_BP_CFG_2_PPE_REG_0_REG + 0x80 * i;
+   o_sbm_bp_cfg = dsaf_read_dev(dsaf_dev, reg);
+   dsaf_set_field(o_sbm_bp_cfg,
+  DSAFV2_SBM_CFG2_PPE_SET_BUF_NUM_M,
+  DSAFV2_SBM_CFG2_PPE_SET_BUF_NUM_S, 2);
+   dsaf_set_field(o_sbm_bp_cfg,
+  DSAFV2_SBM_CFG2_PPE_RESET_BUF_NUM_M,
+  DSAFV2_SBM_CFG2_PPE_RESET_BUF_NUM_S, 3);
+   dsaf_set_field(o_sbm_bp_cfg,
+  DSAFV2_SBM_CFG2_PPE_CFG_USEFUL_NUM_M,
+  DSAFV2_SBM_CFG2_PPE_CFG_USEFUL_NUM_S, 52);
+   dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
+   }
+
/* RoCEE */
for (i = 0; i < DASFV2_ROCEE_CRD_NUM; i++) {
reg = DSAFV2_SBM_BP_CFG_2_ROCEE_REG_0_REG + 0x80 * i;
o_sbm_bp_cfg = dsaf_read_dev(dsaf_dev, reg);
-   dsaf_set_field(o_sbm_bp_cfg, DSAFV2_SBM_CFG2_SET_BUF_NUM_M,
-  DSAFV2_SBM_CFG2_SET_BUF_NUM_S, 2);
-   dsaf_set_field(o_sbm_bp_cfg, DSAFV2_SBM_CFG2_RESET_BUF_NUM_M,
-  DSAFV2_SBM_CFG2_RESET_BUF_NUM_S, 4);
+   dsaf_set_field(o_sbm_bp_cfg,
+  DSAFV2_SBM_CFG2_ROCEE_SET_BUF_NUM_M,
+  DSAFV2_SBM_CFG2_ROCEE_SET_BUF_NUM_S, 2);
+   dsaf_set_field(o_sbm_bp_cfg,
+  DSAFV2_SBM_CFG2_ROCEE_RESET_BUF_NUM_M,
+  DSAFV2_SBM_CFG2_ROCEE_RESET_BUF_NUM_S, 4);
dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
}
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index e35d0cb..235f744 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -32,7 +32,7 @@
 #define DSAFV2_SBM_NUM 8
 #define DSAFV2_SBM_XGE_CHN6
 #define DSAFV2_SBM_PPE_CHN1
-#define DASFV2_ROCEE_CRD_NUM  8
+#define DASFV2_ROCEE_CRD_NUM  1
 
 #define 

[PATCH net-next 15/19] net: hns: bug fix about led control logic when link down

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

The default driver sets anchor led bit to 0 when link down,
actually, the anchor bit should be set to 1, so fixes it when
link status is down.
Secondly, change the return value of cpld_set_led_id to 0, which
means leave the cpld to control led blink frequece other than the
driver itself.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index aff9d77..8473287 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -86,9 +86,10 @@ static void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int 
link_status,
mac_cb->cpld_led_value = value;
}
} else {
-   dsaf_write_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg,
- CPLD_LED_DEFAULT_VALUE);
-   mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE;
+   value = (mac_cb->cpld_led_value) & (0x1 << DSAF_LED_ANCHOR_B);
+   dsaf_write_syscon(mac_cb->cpld_ctrl,
+ mac_cb->cpld_ctrl_reg, value);
+   mac_cb->cpld_led_value = value;
}
 }
 
@@ -114,7 +115,7 @@ static int cpld_set_led_id(struct hns_mac_cb *mac_cb,
 CPLD_LED_ON_VALUE);
dsaf_write_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg,
  mac_cb->cpld_led_value);
-   return 2;
+   break;
case HNAE_LED_INACTIVE:
dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B,
 CPLD_LED_DEFAULT_VALUE);
@@ -122,7 +123,8 @@ static int cpld_set_led_id(struct hns_mac_cb *mac_cb,
  mac_cb->cpld_led_value);
break;
default:
-   break;
+   dev_err(mac_cb->dev, "invalid led state: %d!", status);
+   return -EINVAL;
}
 
return 0;
-- 
1.9.1



[PATCH net-next 12/19] net: hns: fix bug of getting the wrong tcam data

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

The current driver stores the high bit value of tcam data register
to the tcam data low element, stores the low bit value of tcam data
register to tcam data high element, this patch fixes this bug.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 0958ceb..7f5c248 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -975,9 +975,9 @@ static void hns_dsaf_tcam_uc_get(
 
/*read tcam data*/
ptbl_tcam_data->tbl_tcam_data_high
-   = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
-   ptbl_tcam_data->tbl_tcam_data_low
= dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
+   ptbl_tcam_data->tbl_tcam_data_low
+   = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
 
/*read tcam mcast*/
tcam_read_data0 = dsaf_read_dev(dsaf_dev,
@@ -1027,9 +1027,9 @@ static void hns_dsaf_tcam_mc_get(
 
/*read tcam data*/
ptbl_tcam_data->tbl_tcam_data_high =
-   dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
-   ptbl_tcam_data->tbl_tcam_data_low =
dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
+   ptbl_tcam_data->tbl_tcam_data_low =
+   dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
 
/*read tcam mcast*/
ptbl_tcam_mcast->tbl_mcast_port_msk[0] =
-- 
1.9.1



[PATCH] net: vrf: replace hard tab with space in assignment

2016-06-20 Thread Chris Packham
The assignment of rth->dst.output in vrf_rt6_create() and
vrf_rtable_create() used a hard tab before the '='. The neighboring
assignments did not. Make the assignment of rth->dst.output consistent
with the surrounding code.

Signed-off-by: Chris Packham 
---
 drivers/net/vrf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index dff08842f26d..8bd8c7e1ee87 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -304,7 +304,7 @@ static int vrf_rt6_create(struct net_device *dev)
dst_hold(>dst);
 
rt6->rt6i_table = rt6i_table;
-   rt6->dst.output = vrf_output6;
+   rt6->dst.output = vrf_output6;
rcu_assign_pointer(vrf->rt6, rt6);
 
rc = 0;
@@ -403,7 +403,7 @@ static int vrf_rtable_create(struct net_device *dev)
if (!rth)
return -ENOMEM;
 
-   rth->dst.output = vrf_output;
+   rth->dst.output = vrf_output;
rth->rt_table_id = vrf->tb_id;
 
rcu_assign_pointer(vrf->rth, rth);
-- 
2.8.4



[PATCH net-next 14/19] net: hns: delete redundancy ring enable operations

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

When network interface is enabled, the ring enable operation is
conducted twice. This patch deletes the redundancy code of ring enable,
and integrates hnae_ae_ops.toggle_queue_status other functions to
hns_ae_start.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hnae.c |  1 -
 drivers/net/ethernet/hisilicon/hns/hnae.h |  1 -
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 22 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  7 +--
 4 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c 
b/drivers/net/ethernet/hisilicon/hns/hnae.c
index 5d3047c..c54c6fa 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.c
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -400,7 +400,6 @@ int hnae_ae_register(struct hnae_ae_dev *hdev, struct 
module *owner)
 
if (!hdev->ops || !hdev->ops->get_handle ||
!hdev->ops->toggle_ring_irq ||
-   !hdev->ops->toggle_queue_status ||
!hdev->ops->get_status || !hdev->ops->adjust_link)
return -EINVAL;
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h 
b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 962e445..3869322 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -454,7 +454,6 @@ struct hnae_ae_ops {
int (*get_info)(struct hnae_handle *handle,
u8 *auto_neg, u16 *speed, u8 *duplex);
void (*toggle_ring_irq)(struct hnae_ring *ring, u32 val);
-   void (*toggle_queue_status)(struct hnae_queue *queue, u32 val);
void (*adjust_link)(struct hnae_handle *handle, int speed, int duplex);
int (*set_loopback)(struct hnae_handle *handle,
enum hnae_loop loop_mode, int en);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index 6b3796f..835521b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -247,12 +247,21 @@ static void hns_ae_set_tso_stats(struct hnae_handle 
*handle, int enable)
 static int hns_ae_start(struct hnae_handle *handle)
 {
int ret;
+   int k;
struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
 
ret = hns_mac_vm_config_bc_en(mac_cb, 0, true);
if (ret)
return ret;
 
+   for (k = 0; k < handle->q_num; k++) {
+   if (AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver))
+   hns_rcb_int_clr_hw(handle->qs[k],
+  RCB_INT_FLAG_TX | RCB_INT_FLAG_RX);
+   else
+   hns_rcbv2_int_clr_hw(handle->qs[k],
+RCB_INT_FLAG_TX | RCB_INT_FLAG_RX);
+   }
hns_ae_ring_enable_all(handle, 1);
msleep(100);
 
@@ -313,18 +322,6 @@ static void hns_aev2_toggle_ring_irq(struct hnae_ring 
*ring, u32 mask)
hns_rcbv2_int_ctrl_hw(ring->q, flag, mask);
 }
 
-static void hns_ae_toggle_queue_status(struct hnae_queue *queue, u32 val)
-{
-   struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(queue->dev);
-
-   if (AE_IS_VER1(dsaf_dev->dsaf_ver))
-   hns_rcb_int_clr_hw(queue, RCB_INT_FLAG_TX | RCB_INT_FLAG_RX);
-   else
-   hns_rcbv2_int_clr_hw(queue, RCB_INT_FLAG_TX | RCB_INT_FLAG_RX);
-
-   hns_rcb_start(queue, val);
-}
-
 static int hns_ae_get_link_status(struct hnae_handle *handle)
 {
u32 link_status;
@@ -808,7 +805,6 @@ static struct hnae_ae_ops hns_dsaf_ops = {
.stop = hns_ae_stop,
.reset = hns_ae_reset,
.toggle_ring_irq = hns_ae_toggle_ring_irq,
-   .toggle_queue_status = hns_ae_toggle_queue_status,
.get_status = hns_ae_get_link_status,
.get_info = hns_ae_get_mac_info,
.adjust_link = hns_ae_adjust_link,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index cef9d12..f49246d 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1200,7 +1200,7 @@ static int hns_nic_net_up(struct net_device *ndev)
 {
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_handle *h = priv->ae_handle;
-   int i, j, k;
+   int i, j;
int ret;
 
ret = hns_nic_init_irq(priv);
@@ -1215,9 +1215,6 @@ static int hns_nic_net_up(struct net_device *ndev)
goto out_has_some_queues;
}
 
-   for (k = 0; k < h->q_num; k++)
-   h->dev->ops->toggle_queue_status(h->qs[k], 1);
-
ret = h->dev->ops->set_mac_addr(h, ndev->dev_addr);
if (ret)
goto out_set_mac_addr_err;
@@ -1237,8 +1234,6 @@ static int hns_nic_net_up(struct 

[PATCH net-next 00/19] net: hns: fix some bugs in hns driver

2016-06-20 Thread Yisen Zhuang
This series includes some bugs fixed. All these patches needs to be
applied after the patchset about ACPI support, so this series is 
floated to net-next list.

The patches are:
 > from Daode, fixes about pfc pause frame, getting coaslesce, led 
control logic, TSO on|off and tcam table configuration.

 > from Jun He, fix the potential leak to port unavailable

 > from Kejian, fix bug of loopback and failing to test ping6

 > from Qianqian, fix the several typo in hns driver

For more details, please see individual patches.

MBR.

Daode Huang (9):
  net: hns: bugfix about pfc pause frame statistics
  net: hns: add spin lock for tcam table operation
  net: hns: fix bug of getting the wrong tcam data
  net: hns: add get_coalesce_range api for hns
  net: hns: delete redundancy ring enable operations
  net: hns: bug fix about led control logic when link down
  net: hns: fix sbm default parameters config error
  net: hns: change the default coalesce usecs
  net: hns: bug fix about TSO on|off when there is traffic

Jun He (1):
  net: hns: fix bug that alloc skb fail lead to port unavailable

Kejian Yan (3):
  net: hns: add skb_reset_mac_header() after skb being alloc
  net: hns: select Hilink before serdes loopback for HNS V2
  net: hns: fix ethtool loopback fail bug

Qianqian Xie (6):
  net: hns: bug fix of ge reset sequence
  net: hns: fix hns dsaf v1 dont support tx_pause close
  net: hns: typo fix of annotation info for hns_nic_reset_subtask()
  net: hns: Remove unnecessary device resource free
  net: hns: fix the error info when dma_set_mask_and_coherent fail
  net: hns: fix the wrong speed for bond

 drivers/net/ethernet/hisilicon/hns/hnae.c  |   1 -
 drivers/net/ethernet/hisilicon/hns/hnae.h  |   6 +-
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c  |  53 --
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 190 ++---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h |  12 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c |  44 +++--
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c  |   2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h  |   2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h  |  21 ++-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c  |  68 
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c   |  47 ++---
 11 files changed, 291 insertions(+), 155 deletions(-)

-- 
1.9.1



[PATCH net-next 10/19] net: hns: bugfix about pfc pause frame statistics

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

For SoC hip06, PFC pause handled in dsaf, while hip05 in XGMAC,
so change the statistics of pfc pause in dsaf and remove the old
pfc pause frame statistics.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c  |  6 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 72 +++---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 10 ++-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h  |  5 ++
 4 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index d37b778..b97cc75 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -587,6 +587,7 @@ void hns_ae_get_strings(struct hnae_handle *handle,
int idx;
struct hns_mac_cb *mac_cb;
struct hns_ppe_cb *ppe_cb;
+   struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
u8 *p = data;
struct  hnae_vf_cb *vf_cb;
 
@@ -609,13 +610,14 @@ void hns_ae_get_strings(struct hnae_handle *handle,
p += ETH_GSTRING_LEN * hns_mac_get_sset_count(mac_cb, stringset);
 
if (mac_cb->mac_type == HNAE_PORT_SERVICE)
-   hns_dsaf_get_strings(stringset, p, port);
+   hns_dsaf_get_strings(stringset, p, port, dsaf_dev);
 }
 
 int hns_ae_get_sset_count(struct hnae_handle *handle, int stringset)
 {
u32 sset_count = 0;
struct hns_mac_cb *mac_cb;
+   struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
 
assert(handle);
 
@@ -626,7 +628,7 @@ int hns_ae_get_sset_count(struct hnae_handle *handle, int 
stringset)
sset_count += hns_mac_get_sset_count(mac_cb, stringset);
 
if (mac_cb->mac_type == HNAE_PORT_SERVICE)
-   sset_count += hns_dsaf_get_sset_count(stringset);
+   sset_count += hns_dsaf_get_sset_count(dsaf_dev, stringset);
 
return sset_count;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index b8b2ff9..0edea9c 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -2096,11 +2096,24 @@ void hns_dsaf_fix_mac_mode(struct hns_mac_cb *mac_cb)
hns_dsaf_port_work_rate_cfg(dsaf_dev, mac_id, mode);
 }
 
+static u32 hns_dsaf_get_inode_prio_reg(int index)
+{
+   int base_index, offset;
+   u32 base_addr = DSAF_INODE_IN_PRIO_PAUSE_BASE_REG;
+
+   base_index = (index + 1) / DSAF_REG_PER_ZONE;
+   offset = (index + 1) % DSAF_REG_PER_ZONE;
+
+   return base_addr + DSAF_INODE_IN_PRIO_PAUSE_BASE_OFFSET * base_index +
+   DSAF_INODE_IN_PRIO_PAUSE_OFFSET * offset;
+}
+
 void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num)
 {
struct dsaf_hw_stats *hw_stats
= _dev->hw_stats[node_num];
bool is_ver1 = AE_IS_VER1(dsaf_dev->dsaf_ver);
+   int i;
u32 reg_tmp;
 
hw_stats->pad_drop += dsaf_read_dev(dsaf_dev,
@@ -2135,6 +2148,18 @@ void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, 
u32 node_num)
hw_stats->stp_drop += dsaf_read_dev(dsaf_dev,
DSAF_INODE_IN_DATA_STP_DISC_0_REG + 0x80 * (u64)node_num);
 
+   /* pfc pause frame statistics stored in dsaf inode*/
+   if ((node_num < DSAF_SERVICE_NW_NUM) && !is_ver1) {
+   for (i = 0; i < DSAF_PRIO_NR; i++) {
+   reg_tmp = hns_dsaf_get_inode_prio_reg(i);
+   hw_stats->rx_pfc[i] += dsaf_read_dev(dsaf_dev,
+   reg_tmp + 0x4 * (u64)node_num);
+   hw_stats->tx_pfc[i] += dsaf_read_dev(dsaf_dev,
+   DSAF_XOD_XGE_PFC_PRIO_CNT_BASE_REG +
+   DSAF_XOD_XGE_PFC_PRIO_CNT_OFFSET * i +
+   0xF0 * (u64)node_num);
+   }
+   }
hw_stats->tx_pkts += dsaf_read_dev(dsaf_dev,
DSAF_XOD_RCVPKT_CNT_0_REG + 0x90 * (u64)node_num);
 }
@@ -2472,9 +2497,12 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 
port, void *data)
p[i] = 0x;
 }
 
-static char *hns_dsaf_get_node_stats_strings(char *data, int node)
+static char *hns_dsaf_get_node_stats_strings(char *data, int node,
+struct dsaf_device *dsaf_dev)
 {
char *buff = data;
+   int i;
+   bool is_ver1 = AE_IS_VER1(dsaf_dev->dsaf_ver);
 
snprintf(buff, ETH_GSTRING_LEN, "innod%d_pad_drop_pkts", node);
buff = buff + ETH_GSTRING_LEN;
@@ -2502,6 +2530,18 @@ static char *hns_dsaf_get_node_stats_strings(char *data, 
int node)
buff = buff + ETH_GSTRING_LEN;
snprintf(buff, ETH_GSTRING_LEN, 

[PATCH net-next 13/19] net: hns: add get_coalesce_range api for hns

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

This patch adds get_coalesce_range api for hns, it shows
range of coalesce usecs and frames that can be set on
this interface.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hnae.h |  5 +
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 25 +++
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c  | 10 +
 3 files changed, 40 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h 
b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 529cb13..962e445 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -473,6 +473,11 @@ struct hnae_ae_ops {
int (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout);
int (*set_coalesce_frames)(struct hnae_handle *handle,
   u32 coalesce_frames);
+   void (*get_coalesce_range)(struct hnae_handle *handle,
+  u32 *tx_frames_low, u32 *rx_frames_low,
+  u32 *tx_frames_high, u32 *rx_frames_high,
+  u32 *tx_usecs_low, u32 *rx_usecs_low,
+  u32 *tx_usecs_high, u32 *rx_usecs_high);
void (*set_promisc_mode)(struct hnae_handle *handle, u32 en);
int (*get_mac_addr)(struct hnae_handle *handle, void **p);
int (*set_mac_addr)(struct hnae_handle *handle, void *p);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index b97cc75..6b3796f 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -465,6 +465,30 @@ static int  hns_ae_set_coalesce_frames(struct hnae_handle 
*handle,
ring_pair->port_id_in_comm, coalesce_frames);
 }
 
+static void hns_ae_get_coalesce_range(struct hnae_handle *handle,
+ u32 *tx_frames_low, u32 *rx_frames_low,
+ u32 *tx_frames_high, u32 *rx_frames_high,
+ u32 *tx_usecs_low, u32 *rx_usecs_low,
+ u32 *tx_usecs_high, u32 *rx_usecs_high)
+{
+   struct dsaf_device *dsaf_dev;
+
+   dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
+
+   *tx_frames_low  = HNS_RCB_MIN_COALESCED_FRAMES;
+   *rx_frames_low  = HNS_RCB_MIN_COALESCED_FRAMES;
+   *tx_frames_high =
+   (dsaf_dev->desc_num - 1 > HNS_RCB_MAX_COALESCED_FRAMES) ?
+   HNS_RCB_MAX_COALESCED_FRAMES : dsaf_dev->desc_num - 1;
+   *rx_frames_high =
+   (dsaf_dev->desc_num - 1 > HNS_RCB_MAX_COALESCED_FRAMES) ?
+HNS_RCB_MAX_COALESCED_FRAMES : dsaf_dev->desc_num - 1;
+   *tx_usecs_low   = 0;
+   *rx_usecs_low   = 0;
+   *tx_usecs_high  = HNS_RCB_MAX_COALESCED_USECS;
+   *rx_usecs_high  = HNS_RCB_MAX_COALESCED_USECS;
+}
+
 void hns_ae_update_stats(struct hnae_handle *handle,
 struct net_device_stats *net_stats)
 {
@@ -798,6 +822,7 @@ static struct hnae_ae_ops hns_dsaf_ops = {
.get_rx_max_coalesced_frames = hns_ae_get_rx_max_coalesced_frames,
.set_coalesce_usecs = hns_ae_set_coalesce_usecs,
.set_coalesce_frames = hns_ae_set_coalesce_frames,
+   .get_coalesce_range = hns_ae_get_coalesce_range,
.set_promisc_mode = hns_ae_set_promisc_mode,
.set_mac_addr = hns_ae_set_mac_address,
.set_mc_addr = hns_ae_set_multicast_one,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 564ae1e..a395ca1 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -751,6 +751,16 @@ static int hns_get_coalesce(struct net_device *net_dev,
>tx_max_coalesced_frames,
>rx_max_coalesced_frames);
 
+   ops->get_coalesce_range(priv->ae_handle,
+   >tx_max_coalesced_frames_low,
+   >rx_max_coalesced_frames_low,
+   >tx_max_coalesced_frames_high,
+   >rx_max_coalesced_frames_high,
+   >tx_coalesce_usecs_low,
+   >rx_coalesce_usecs_low,
+   >tx_coalesce_usecs_high,
+   >rx_coalesce_usecs_high);
+
return 0;
 }
 
-- 
1.9.1



[PATCH net-next 09/19] net: hns: fix the wrong speed for bond

2016-06-20 Thread Yisen Zhuang
From: Qianqian Xie 

For debug-ports,there are two non-synchronized processes:
Speed-Auto-Negotiation and Link-Update-Status. The two
processes are towed by two different state machines.
Bond reads the speed when link up, but the speed maybe
not update the right value at that time.That make for bond's
wrong speed. Thus only one state machine should be used and
if phy_state_machine is used, it does not need to do
hns_nic_update_link_status().

Signed-off-by: Qianqian Xie 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c| 43 +---
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c |  2 +-
 2 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 00e529f..cef9d12 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -991,8 +991,26 @@ static void hns_nic_adjust_link(struct net_device *ndev)
 {
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_handle *h = priv->ae_handle;
+   int state = 1;
+
+   if (priv->phy) {
+   h->dev->ops->adjust_link(h, ndev->phydev->speed,
+ndev->phydev->duplex);
+   state = priv->phy->link;
+   }
+   state = state && h->dev->ops->get_status(h);
 
-   h->dev->ops->adjust_link(h, ndev->phydev->speed, ndev->phydev->duplex);
+   if (state != priv->link) {
+   if (state) {
+   netif_carrier_on(ndev);
+   netif_tx_wake_all_queues(ndev);
+   netdev_info(ndev, "link up\n");
+   } else {
+   netif_carrier_off(ndev);
+   netdev_info(ndev, "link down\n");
+   }
+   priv->link = state;
+   }
 }
 
 /**
@@ -1577,27 +1595,14 @@ static void hns_nic_update_link_status(struct 
net_device *netdev)
struct hns_nic_priv *priv = netdev_priv(netdev);
 
struct hnae_handle *h = priv->ae_handle;
-   int state = 1;
 
-   if (priv->phy) {
-   if (!genphy_update_link(priv->phy))
-   state = priv->phy->link;
-   else
-   state = 0;
-   }
-   state = state && h->dev->ops->get_status(h);
+   if (h->phy_dev) {
+   if (h->phy_if != PHY_INTERFACE_MODE_XGMII)
+   return;
 
-   if (state != priv->link) {
-   if (state) {
-   netif_carrier_on(netdev);
-   netif_tx_wake_all_queues(netdev);
-   netdev_info(netdev, "link up\n");
-   } else {
-   netif_carrier_off(netdev);
-   netdev_info(netdev, "link down\n");
-   }
-   priv->link = state;
+   (void)genphy_read_status(h->phy_dev);
}
+   hns_nic_adjust_link(netdev);
 }
 
 /* for dumping key regs*/
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 5b3dccb..564ae1e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -49,7 +49,7 @@ static u32 hns_nic_get_link(struct net_device *net_dev)
h = priv->ae_handle;
 
if (priv->phy) {
-   if (!genphy_update_link(priv->phy))
+   if (!genphy_read_status(priv->phy))
link_stat = priv->phy->link;
else
link_stat = 0;
-- 
1.9.1



[PATCH net-next 18/19] net: hns: change the default coalesce usecs

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

The default coalesce timeout is 3us, which is will cause CPU
usage is too high. This patch change it to 50us in order to reduce
CPU usage and the value makes sure network latency also meets requirement.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index 3ce2409..ef11077 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -540,7 +540,7 @@ int hns_rcb_set_coalesce_usecs(
}
if (timeout > HNS_RCB_MAX_COALESCED_USECS) {
dev_err(rcb_common->dsaf_dev->dev,
-   "error: not support coalesce %dus!\n", timeout);
+   "error: coalesce_usecs setting supports 0~1023us\n");
return -EINVAL;
}
hns_rcb_set_port_timeout(rcb_common, port_idx, timeout);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
index bd54dac..99b4e1b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
@@ -40,7 +40,7 @@ struct rcb_common_cb;
 #define HNS_RCB_DEF_COALESCED_FRAMES   50
 #define HNS_RCB_CLK_FREQ_MHZ   350
 #define HNS_RCB_MAX_COALESCED_USECS0x3ff
-#define HNS_RCB_DEF_COALESCED_USECS3
+#define HNS_RCB_DEF_COALESCED_USECS50
 
 #define HNS_RCB_COMMON_ENDIAN  1
 
-- 
1.9.1



[PATCH net-next 01/19] net: hns: bug fix of ge reset sequence

2016-06-20 Thread Yisen Zhuang
From: Qianqian Xie 

The bit fileds of PPE reset register are different between HNS v1 and
HNS v2, but the current procedure just only match HNS v1. Here is a
patch to fix it.

Signed-off-by: Kejian Yan 
Signed-off-by: Qianqian Xie 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index 96cb628..09e60d6 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -271,7 +271,11 @@ static void hns_dsaf_ge_srst_by_port(struct dsaf_device 
*dsaf_dev, u32 port,
}
} else {
reg_val_1 = 0x15540 << dsaf_dev->reset_offset;
-   reg_val_2 = 0x100 << dsaf_dev->reset_offset;
+
+   if (AE_IS_VER1(dsaf_dev->dsaf_ver))
+   reg_val_2 = 0x100 << dsaf_dev->reset_offset;
+   else
+   reg_val_2 = 0x40 << dsaf_dev->reset_offset;
 
if (!dereset) {
dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG,
-- 
1.9.1



[PATCH net-next 11/19] net: hns: add spin lock for tcam table operation

2016-06-20 Thread Yisen Zhuang
From: Daode Huang 

This patch adds spin lock for tcam table operation,
there maybe a race condition happens when more than
one thread try to change the tcam talbe entries.

Signed-off-by: Daode Huang 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 25 ++
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 0edea9c..0958ceb 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -860,6 +860,8 @@ static void hns_dsaf_single_line_tbl_cfg(
struct dsaf_device *dsaf_dev,
u32 address, struct dsaf_tbl_line_cfg *ptbl_line)
 {
+   spin_lock_bh(_dev->tcam_lock);
+
/*Write Addr*/
hns_dsaf_tbl_line_addr_cfg(dsaf_dev, address);
 
@@ -868,6 +870,8 @@ static void hns_dsaf_single_line_tbl_cfg(
 
/*Write Plus*/
hns_dsaf_tbl_line_pul(dsaf_dev);
+
+   spin_unlock_bh(_dev->tcam_lock);
 }
 
 /**
@@ -881,6 +885,8 @@ static void hns_dsaf_tcam_uc_cfg(
struct dsaf_tbl_tcam_data *ptbl_tcam_data,
struct dsaf_tbl_tcam_ucast_cfg *ptbl_tcam_ucast)
 {
+   spin_lock_bh(_dev->tcam_lock);
+
/*Write Addr*/
hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
/*Write Tcam Data*/
@@ -889,6 +895,8 @@ static void hns_dsaf_tcam_uc_cfg(
hns_dsaf_tbl_tcam_ucast_cfg(dsaf_dev, ptbl_tcam_ucast);
/*Write Plus*/
hns_dsaf_tbl_tcam_data_ucast_pul(dsaf_dev);
+
+   spin_unlock_bh(_dev->tcam_lock);
 }
 
 /**
@@ -903,6 +911,8 @@ static void hns_dsaf_tcam_mc_cfg(
struct dsaf_tbl_tcam_data *ptbl_tcam_data,
struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast)
 {
+   spin_lock_bh(_dev->tcam_lock);
+
/*Write Addr*/
hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
/*Write Tcam Data*/
@@ -911,6 +921,8 @@ static void hns_dsaf_tcam_mc_cfg(
hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, ptbl_tcam_mcast);
/*Write Plus*/
hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev);
+
+   spin_unlock_bh(_dev->tcam_lock);
 }
 
 /**
@@ -920,6 +932,8 @@ static void hns_dsaf_tcam_mc_cfg(
  */
 static void hns_dsaf_tcam_mc_invld(struct dsaf_device *dsaf_dev, u32 address)
 {
+   spin_lock_bh(_dev->tcam_lock);
+
/*Write Addr*/
hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
 
@@ -932,6 +946,8 @@ static void hns_dsaf_tcam_mc_invld(struct dsaf_device 
*dsaf_dev, u32 address)
 
/*Write Plus*/
hns_dsaf_tbl_tcam_mcast_pul(dsaf_dev);
+
+   spin_unlock_bh(_dev->tcam_lock);
 }
 
 /**
@@ -949,6 +965,8 @@ static void hns_dsaf_tcam_uc_get(
u32 tcam_read_data0;
u32 tcam_read_data4;
 
+   spin_lock_bh(_dev->tcam_lock);
+
/*Write Addr*/
hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
 
@@ -981,6 +999,8 @@ static void hns_dsaf_tcam_uc_get(
 DSAF_TBL_UCAST_CFG1_OUT_PORT_S);
ptbl_tcam_ucast->tbl_ucast_dvc
= dsaf_get_bit(tcam_read_data0, DSAF_TBL_UCAST_CFG1_DVC_S);
+
+   spin_unlock_bh(_dev->tcam_lock);
 }
 
 /**
@@ -997,6 +1017,8 @@ static void hns_dsaf_tcam_mc_get(
 {
u32 data_tmp;
 
+   spin_lock_bh(_dev->tcam_lock);
+
/*Write Addr*/
hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
 
@@ -1027,6 +1049,8 @@ static void hns_dsaf_tcam_mc_get(
ptbl_tcam_mcast->tbl_mcast_port_msk[4] =
dsaf_get_field(data_tmp, DSAF_TBL_MCAST_CFG4_VM128_112_M,
   DSAF_TBL_MCAST_CFG4_VM128_112_S);
+
+   spin_unlock_bh(_dev->tcam_lock);
 }
 
 /**
@@ -1351,6 +1375,7 @@ static int hns_dsaf_init(struct dsaf_device *dsaf_dev)
if (HNS_DSAF_IS_DEBUG(dsaf_dev))
return 0;
 
+   spin_lock_init(_dev->tcam_lock);
ret = hns_dsaf_init_hw(dsaf_dev);
if (ret)
return ret;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index 00a13de..1daf018 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -322,6 +322,8 @@ struct dsaf_device {
 
struct dsaf_hw_stats hw_stats[DSAF_NODE_NUM];
struct dsaf_int_stat int_stat;
+   /* make sure tcam table config spinlock */
+   spinlock_t tcam_lock;
 };
 
 static inline void *hns_dsaf_dev_priv(const struct dsaf_device *dsaf_dev)
-- 
1.9.1



[PATCH net-next 07/19] net: hns: select Hilink before serdes loopback for HNS V2

2016-06-20 Thread Yisen Zhuang
From: Kejian Yan 

As Hilink3 and Hilink4 use the same xge training and xge u adaptor for
HNSv2, it needs to select which Hilink to be set before relative serdes
being configed. The hilink_access_sel is the register to do that.

Signed-off-by: Kejian Yan 
Signed-off-by: Yisen Zhuang 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 26 +-
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index 09e60d6..aff9d77 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -435,11 +435,6 @@ int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int 
*sfp_prsnt)
  */
 static int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, bool en)
 {
-   /* port 0-3 hilink4 base is serdes_vaddr + 0x0028
-* port 4-7 hilink3 base is serdes_vaddr + 0x0020
-*/
-   u8 *base_addr = (u8 *)mac_cb->serdes_vaddr +
-  (mac_cb->mac_id <= 3 ? 0x0028 : 0x0020);
const u8 lane_id[] = {
0,  /* mac 0 -> lane 0 */
1,  /* mac 1 -> lane 1 */
@@ -465,11 +460,30 @@ static int hns_mac_config_sds_loopback(struct hns_mac_cb 
*mac_cb, bool en)
}
 
if (mac_cb->serdes_ctrl) {
-   u32 origin = dsaf_read_syscon(mac_cb->serdes_ctrl, reg_offset);
+   u32 origin;
+
+   if (!AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver)) {
+#define HILINK_ACCESS_SEL_CFG  0x40008
+   /* hilink4 & hilink3 use the same xge training and
+* xge u adaptor. There is a hilink access sel cfg
+* register to select which one to be configed
+*/
+   if ((!HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) &&
+   (mac_cb->mac_id <= 3))
+   dsaf_write_syscon(mac_cb->serdes_ctrl,
+ HILINK_ACCESS_SEL_CFG, 0);
+   else
+   dsaf_write_syscon(mac_cb->serdes_ctrl,
+ HILINK_ACCESS_SEL_CFG, 3);
+   }
+
+   origin = dsaf_read_syscon(mac_cb->serdes_ctrl, reg_offset);
 
dsaf_set_field(origin, 1ull << 10, 10, en);
dsaf_write_syscon(mac_cb->serdes_ctrl, reg_offset, origin);
} else {
+   u8 *base_addr = (u8 *)mac_cb->serdes_vaddr +
+   (mac_cb->mac_id <= 3 ? 0x0028 : 0x0020);
dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, en);
}
 
-- 
1.9.1



Re: r8169 regression: UDP packets dropped intermittantly

2016-06-20 Thread Jonathan Woithe
Hi all

On Wed, Jun 01, 2016 at 10:01:23AM +0930, Jonathan Woithe wrote:
> On Wed, May 18, 2016 at 04:21:37PM +0930, Jonathan Woithe wrote:
> > On Thu, Apr 07, 2016 at 12:14:18PM +0930, Jonathan Woithe wrote:
> > > On Mon, Feb 08, 2016 at 01:03:19PM +1030, Jonathan Woithe wrote:
> > > > On Wed, Dec 02, 2015 at 12:58:52AM +0100, Francois Romieu wrote:
> > > > > Jonathan Woithe  :
> > > > > [...]
> > > > > > Any thoughts or progress at this stage?  Are there further tests 
> > > > > > you need me
> > > > > > to do ?
> > > > > 
> > > > > Yes but you should expect two more days without signal.
> > > > 
> > > > FYI I am now back from annual leave and linux.conf.au.  This means I am 
> > > > in
> > > > a position to test possible solutions to this problem once you are able 
> > > > to
> > > > make them available.
> > > 
> > > Has there been any further progress on this problem?  I still have access 
> > > to
> > > the hardware and systems if further tests are required.
> > 
> > To assist in picking up this issue I thought I'd summarise where things are
> > at from my perspective.
> > 
> > The problem is that small low-speed UDP packets are being dropped by the
> > r8169-based network card in our systems.  Git bisect showed that the
> > regression started with commit da78dbff2e05630921c551dbbc70a4b7981a8fff.
> > :
> 
> FYI I have just tested the kernel.org 4.6 kernel and unsurprisingly it still
> exhibits the regression.

Is there any chance that this regression can be resolved?  It's been 6
months since the last contact was received from the list in relation to this
issue.  If the r8169 driver is to remain broken with respect to UDP traffic
then we will have no choice but to factor in a change in our standard
hardware for future systems.  Unfortunately this also means that dozens of
systems in the field cannot be upgraded to recent kernels since doing so
will trigger the regression.[1]

I would very much like to see the r8169 regression fixed and remain ready to
run more tests as needed.  I still have the test rig in place to recreate
the situation which triggers it, although it's likely the hardware will be
redeployed in the next few months.

If the decision has been made to leave the regression unfixed, please let me
know.  A least we will then understand the situation and we will stop waiting
for a solution which will never appear and start looking at changing our
standard hardware build.  For various reasons this is a significant
undertaking which we would rather not do and it has implications for ongoing
support of existing systems.  Obviously though if there's a bug in the r8169
kernel driver which will never be fixed then this is the approach we will
regrettably have to take.

Regards
  jonathan

[1] Exchanging network cards in existing systems just to avoid a kernel
regression is not a viable option because there are commercial software
licences node locked to the existing cards.  Finding a non-r8169 PCI card
for these systems may also prove to be a challenge.


Re: [PATCH 1/2] ARM: imx6: disable deeper idle states when FEC is active w/o HW workaround

2016-06-20 Thread Shawn Guo
On Thu, Jun 16, 2016 at 05:47:26PM +0200, Arnd Bergmann wrote:
> On Wednesday, June 1, 2016 5:29:42 PM CEST Lucas Stach wrote:
> > +/*
> > + * i.MX6 Q/DL has an erratum (ERR006687) that prevents the FEC from waking 
> > the
> > + * CPUs when they are in wait(unclocked) state. As the hardware workaround 
> > isn't
> > + * applicable to all boards, disable the deeper idle state when the 
> > workaround
> > + * isn't present and the FEC is in use.
> > + */
> > +void imx6q_cpuidle_fec_irqs_used(void)
> > +{
> > +   imx6q_cpuidle_driver.states[1].disabled = true;
> > +}
> > +
> > +void imx6q_cpuidle_fec_irqs_unused(void)
> > +{
> > +   imx6q_cpuidle_driver.states[1].disabled = false;
> > +}
> > +
> 
> These functions need to be exported, I just saw a build error in
> an allmodconfig test:
> 
> ERROR: "imx6q_cpuidle_fec_irqs_unused" 
> [drivers/net/ethernet/freescale/fec.ko] undefined!
> ERROR: "imx6q_cpuidle_fec_irqs_used" [drivers/net/ethernet/freescale/fec.ko] 
> undefined!

Thanks for the report, Arnd.  Just sent a fix for it.

Shawn


Re: [very-RFC 0/8] TSN driver for the kernel

2016-06-20 Thread Takashi Sakamoto

On 2016年06月20日 18:06, Henrik Austad wrote:

On Sun, Jun 19, 2016 at 11:45:47PM +0900, Takashi Sakamoto wrote:

(remove C.C. to lkml. This is not so major feature.)

On Jun 19 2916 07:45, Henrik Austad wrote:

snip

802.1Q gives you low latency through the network, but more importantly, no
dropped frames. gPTP gives you a central reference to time.


When such a long message is required, it means that we don't have
enough premises for this discussion.


Isn't a discussion part of how information is conveyed and finding parts
that require more knowledge?


You have just interests in gPTP and transferring AVTPDUs, while no
interests in the others such as "what the basic ideas of TSN come
from" and "the reason that IEEE 1722 refers to IEC 61883 series
which is originally designed for IEEE 1394 bus" and "the reason that
I was motivated to join in this discussion even though not a netdev
developer".


I'm sorry, I'm not sure I follow you here. What do you mean I don't have
any interest in where TSN comes from? or the reason why 1722 use IEC 61883?
What about "they picked 61883 because it made sense?"

gPTP itself is *not* about transffering audio-data, it is about agreeing on
a common time so that when you *do* transfer audio-data, the samplerate
actually means something.

Let me ask you this; if you have 2 sound-cards in your computer and you
want to attach a mic to one and speakers to the other, how do you solve
streaming of audio from the mic to the speaker If you answer does not
contain something akin to "different timing-domain issues", I'd be very
surprised.

If you are interested in TSN for transferring *anything*, _including_
audio, you *have* to take gPTP into consideration. Just as you have to
think about stream reservation, compliant hardware and all the different
subsystems you are going to run into, either via kernel or via userspace.


Here, could I ask you a question? Do you know a role of cycle start
packet of IEEE Std 1394?


No, I do not.

I have only passing knowledge of the firewire standard, I've looked at the
encoding described in 1722 and added that to the alsa shim as an example of
how to use TSN. As I stated, this was a *very* early version and I would
like to use TSN for audio - and more work is needed.


If you think it's not related to this discussion, please tell it to
me. Then I'll drop out from this thread.


There are tons of details left and right, and as I said, I'm not  all to
familiar with firewire. I know that one of the authors behind the firewire
standard happened to be part of 1722 standard.

I am currently working my way through the firewire-stak paper you've
written, and I have gotten a lot of pointers to other areas I need to dig
into so I should be busy for a while.

That being said, Richard's point about a way to find sample-rate of a
hardware device and ways to influence that, is important for AVB/TSN.


History Repeats itself.


?


OK. Bye.


Takashi Sakamoto


Re: [PATCH net-next v10 2/5] openvswitch: set skb protocol and mac_len when receiving on internal device

2016-06-20 Thread Simon Horman
[Cc Jiri Benc]

On Sat, Jun 18, 2016 at 06:38:54PM -0700, pravin shelar wrote:
> On Thu, Jun 16, 2016 at 10:53 PM, Simon Horman
>  wrote:
> > On Tue, Jun 07, 2016 at 03:45:27PM -0700, pravin shelar wrote:
> >> On Mon, Jun 6, 2016 at 8:08 PM, Simon Horman  
> >> wrote:
> >> > On Thu, Jun 02, 2016 at 03:01:47PM -0700, pravin shelar wrote:
> >> >> On Wed, Jun 1, 2016 at 11:24 PM, Simon Horman
> >> >>  wrote:
> >> >> > * Set skb protocol based on contents of packet. I have observed this 
> >> >> > is
> >> >> >   necessary to get actual protocol of a packet when it is injected 
> >> >> > into an
> >> >> >   internal device e.g. by libnet in which case skb protocol will be 
> >> >> > set to
> >> >> >   ETH_ALL.
> 
> 
> >> > eth_type = eth_type_trans(skb, skb->dev);
> >> > skb->mac_len = skb->data - skb_mac_header(skb);
> >> > __skb_push(skb, skb->mac_len);
> >> >
> >> > if (eth_type == htons(ETH_P_8021Q))
> >> > skb->mac_len += VLAN_HLEN;
> >> >
> >> > Perhaps that logic ought to be in a helper used by both 
> >> > internal_dev_xmit()
> >> > and netdev_port_receive(). Or somehow centralised in ovs_vport_receive().
> >>
> >> This does looks bit complex. Can we use other skb metadata like
> >> skb_mac_header_was_set()?
> >
> > Yes, I think that can be made to work if skb->mac_header is unset
> > for l3 packets in netdev_port_receive(). The following is an incremental
> > patch on the entire series. Is this the kind of thing you had in mind?
> >
> > diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
> > index 86f2cfb19de3..42587d5bf894 100644
> > --- a/net/openvswitch/flow.c
> > +++ b/net/openvswitch/flow.c
> > @@ -729,7 +729,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info 
> > *tun_info,
> > key->phy.skb_mark = skb->mark;
> > ovs_ct_fill_key(skb, key);
> > key->ovs_flow_hash = 0;
> > -   key->phy.is_layer3 = skb->mac_len == 0;
> > +   key->phy.is_layer3 = skb_mac_header_was_set(skb) == 0;
> > key->recirc_id = 0;
> >
> > err = key_extract(skb, key);
> > diff --git a/net/openvswitch/vport-internal_dev.c 
> > b/net/openvswitch/vport-internal_dev.c
> > index 484ba529c682..8973d4db509b 100644
> > --- a/net/openvswitch/vport-internal_dev.c
> > +++ b/net/openvswitch/vport-internal_dev.c
> > @@ -50,7 +50,6 @@ static int internal_dev_xmit(struct sk_buff *skb, struct 
> > net_device *netdev)
> >
> > skb->protocol = eth_type_trans(skb, netdev);
> > skb_push(skb, ETH_HLEN);
> > -   skb_reset_mac_len(skb);
> >
> > len = skb->len;
> > rcu_read_lock();
> > diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
> > index 3df36df62ee9..4cf3f12ffc99 100644
> > --- a/net/openvswitch/vport-netdev.c
> > +++ b/net/openvswitch/vport-netdev.c
> > @@ -60,22 +60,9 @@ static void netdev_port_receive(struct sk_buff *skb)
> > if (vport->dev->type == ARPHRD_ETHER) {
> > skb_push(skb, ETH_HLEN);
> > skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
> > -   } else if (vport->dev->type == ARPHRD_NONE) {
> > -   if (skb->protocol == htons(ETH_P_TEB)) {
> > -   __be16 eth_type;
> > -
> > -   if (unlikely(skb->len < ETH_HLEN))
> > -   goto error;
> > -
> > -   eth_type = eth_type_trans(skb, skb->dev);
> > -   skb->mac_len = skb->data - skb_mac_header(skb);
> > -   __skb_push(skb, skb->mac_len);
> > -
> > -   if (eth_type == htons(ETH_P_8021Q))
> > -   skb->mac_len += VLAN_HLEN;
> > -   } else {
> > -   skb->mac_len = 0;
> > -   }
> > +   } else if (vport->dev->type == ARPHRD_NONE &&
> > +  skb->protocol != htons(ETH_P_TEB)) {
> > +   skb->mac_header = (typeof(skb->mac_header))~0U;
> > }
> >
> > ovs_vport_receive(vport, skb, skb_tunnel_info(skb));
> 
> This certainly looks better. I was wondering if we can unset the mac
> header offset in L3 tunnel devices itself. So there is no need to have
> this check here.

I think that might be possible for GRE by modifying the following in
__ipgre_rcv().

if (tunnel->dev->type != ARPHRD_NONE)
skb_pop_mac_header(skb);
else
skb_reset_mac_header(skb);

But I am unsure what side effects this might have on other users of the
code.

Jiri, do you have any thoughts on this?


Re: [PATCH net-next 12/18] IB/mlx5: Add kernel offload flow-tag

2016-06-20 Thread Alexei Starovoitov
On Sat, Jun 18, 2016 at 01:31:26AM +0300, Saeed Mahameed wrote:
> 
> We simply want to selectively be able to see RoCE/RDMA ETH standard
> traffic in tcpdump, for diagnostic purposes.
> so in order to not overwhelm the kernel TCP/IP stack with this
> traffic, this patch in particular
> configures ConnectX4 hardware to tag those packets, so in downstream
> patches mlx5 netdevice will mark the SKBs of those packets
> to skip the TCP/IP stack and go only to tcpdump.

such 'feature' doesn't make sense to me.
'not overwhelming' kernel, but to 'overwhelm' userspace tcpdump?
Kernel can drop packets way faster than userspace, so such bypass
scheme has no prartical usage other than building a first step towards
complete dpdk-like bypass.



Re: [PATCH net-next] net: dsa: b53: Fix statistics readings

2016-06-20 Thread Andrew Lunn
On Mon, Jun 20, 2016 at 06:26:53PM -0700, Florian Fainelli wrote:
> Due to a typo we would always be using the MIB counter width of the
> first element of the counter array instead of the current element, and
> we would always be accessing the register statistics with a 64-bits
> read, while some could be 32-bits. This got unnoticed in testing with
> MDIO and SRAB which tolerate doing this, but testing with the SPI bus
> revealed bogus values being returned. Fix this by using the proper
> iterator here.
> 
> Fixes: 967dd82ffc52 ("net: dsa: b53: Add support for Broadcom RoboSwitch")
> Reported-by: Jonas Gorski 
> Signed-off-by: Florian Fainelli 

Reviewed-by: Andrew Lunn 

Andrew


[PATCH net-next] openvswitch: Only set mark and labels when commiting a connection.

2016-06-20 Thread Jarno Rajahalme
Only allow setting conntrack mark or labels when the commit flag is
specified.  This makes sure we can not set them before the connection
has been persisted, as in that case the mark and labels would be lost
in an event of an userspace upcall.

OVS userspace already requires the commit flag to accept setting
ct_mark and/or ct_labels.  Validate for this on the kernel API.

Finally, set conntrack mark and labels right before committing so that
the initial conntrack NEW event has the mark and labels.

Signed-off-by: Jarno Rajahalme 
---
 net/openvswitch/conntrack.c | 72 ++---
 1 file changed, 48 insertions(+), 24 deletions(-)

diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 3d5feed..f1612f5 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -824,6 +824,17 @@ static int ovs_ct_lookup(struct net *net, struct 
sw_flow_key *key,
return 0;
 }
 
+static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
+{
+   size_t i;
+
+   for (i = 0; i < sizeof(*labels); i++)
+   if (labels->ct_labels[i])
+   return true;
+
+   return false;
+}
+
 /* Lookup connection and confirm if unconfirmed. */
 static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
 const struct ovs_conntrack_info *info,
@@ -834,24 +845,35 @@ static int ovs_ct_commit(struct net *net, struct 
sw_flow_key *key,
err = __ovs_ct_lookup(net, key, info, skb);
if (err)
return err;
-   /* This is a no-op if the connection has already been confirmed. */
+
+   /* As any changes to an unconfirmed connection may be lost due
+* to an upcall, we require the presence of the 'commit' flag
+* for setting mask and/or labels.  Perform the changes before
+* confirming the connection so that the initial mark and label
+* values are present in the initial CT NEW netlink event.
+*/
+   if (info->mark.mask) {
+   err = ovs_ct_set_mark(skb, key, info->mark.value,
+ info->mark.mask);
+   if (err)
+   return err;
+   }
+   if (labels_nonzero(>labels.mask)) {
+   err = ovs_ct_set_labels(skb, key, >labels.value,
+   >labels.mask);
+   if (err)
+   return err;
+   }
+
+   /* Will take care of sending queued events even if the connection is
+* already confirmed.
+*/
if (nf_conntrack_confirm(skb) != NF_ACCEPT)
return -EINVAL;
 
return 0;
 }
 
-static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
-{
-   size_t i;
-
-   for (i = 0; i < sizeof(*labels); i++)
-   if (labels->ct_labels[i])
-   return true;
-
-   return false;
-}
-
 /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
  * value if 'skb' is freed.
  */
@@ -876,19 +898,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
err = ovs_ct_commit(net, key, info, skb);
else
err = ovs_ct_lookup(net, key, info, skb);
-   if (err)
-   goto err;
 
-   if (info->mark.mask) {
-   err = ovs_ct_set_mark(skb, key, info->mark.value,
- info->mark.mask);
-   if (err)
-   goto err;
-   }
-   if (labels_nonzero(>labels.mask))
-   err = ovs_ct_set_labels(skb, key, >labels.value,
-   >labels.mask);
-err:
skb_push(skb, nh_ofs);
if (err)
kfree_skb(skb);
@@ -1145,6 +1155,20 @@ static int parse_ct(const struct nlattr *attr, struct 
ovs_conntrack_info *info,
}
}
 
+#ifdef CONFIG_NF_CONNTRACK_MARK
+   if (!info->commit && info->mark.mask) {
+   OVS_NLERR(log,
+ "Setting conntrack mark requires 'commit' flag.");
+   return -EINVAL;
+   }
+#endif
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+   if (!info->commit && labels_nonzero(>labels.mask)) {
+   OVS_NLERR(log,
+ "Setting conntrack labels requires 'commit' flag.");
+   return -EINVAL;
+   }
+#endif
if (rem > 0) {
OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
return -EINVAL;
-- 
2.1.4



Re: [PATCH net-next] of_mdio: Enable fixed PHY support if driver is a module

2016-06-20 Thread Florian Fainelli
Le 20/06/2016 17:17, Ben Hutchings a écrit :
> The fixed_phy driver doesn't have to be built-in, and it's
> important that of_mdio supports it even if it's a module.
> 
> Signed-off-by: Ben Hutchings 

Acked-by: Florian Fainelli 
-- 
Florian


linux-next: manual merge of the net-next tree with the arm-soc tree

2016-06-20 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the net-next tree got conflicts in:

  arch/arm64/boot/dts/broadcom/ns2-svk.dts
  arch/arm64/boot/dts/broadcom/ns2.dtsi

between commits:

  97b1504a30b3 ("arm64: dts: enable pinctrl for Broadcom NS2 SoC")
  5dcc9c7618df ("arm64: dts: NS2: Add CCI-400 PMU support")

from the arm-soc tree and commit:

  5f1a067bfa0a ("dt: mdio-mux: Add mdio multiplexer driver node")

from the net-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc arch/arm64/boot/dts/broadcom/ns2-svk.dts
index b062a44a39c7,ea5603fd106a..
--- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
@@@ -161,11 -141,10 +169,19 @@@
};
  };
  
 + {
 +  pinctrl-names = "default";
 +  pinctrl-0 = <_sel>;
 +  nand_sel: nand_sel {
 +  function = "nand";
 +  groups = "nand_grp";
 +  };
 +};
++
+ _mux_iproc {
+   mdio@10 {
+   gphy0: eth-phy@10 {
+   reg = <0x10>;
+   };
+   };
+ };
diff --cc arch/arm64/boot/dts/broadcom/ns2.dtsi
index d1dc812daaab,46b78fa89f4c..
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@@ -279,26 -263,45 +279,65 @@@
  IRQ_TYPE_LEVEL_HIGH)>;
};
  
 +  cci@6559 {
 +  compatible = "arm,cci-400";
 +  #address-cells = <1>;
 +  #size-cells = <1>;
 +  reg = <0x6559 0x1000>;
 +  ranges = <0 0x6559 0x1>;
 +
 +  pmu@9000 {
 +  compatible = "arm,cci-400-pmu,r1",
 +   "arm,cci-400-pmu";
 +  reg = <0x9000 0x4000>;
 +  interrupts = ,
 +   ,
 +   ,
 +   ,
 +   ,
 +   ;
 +  };
 +  };
 +
+   mdio_mux_iproc: mdio-mux@6602023c {
+   compatible = "brcm,mdio-mux-iproc";
+   reg = <0x6602023c 0x14>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+ 
+   mdio@0 {
+   reg = <0x0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+ 
+   pci_phy0: pci-phy@0 {
+   compatible = "brcm,ns2-pcie-phy";
+   reg = <0x0>;
+   #phy-cells = <0>;
+   status = "disabled";
+   };
+   };
+ 
+   mdio@7 {
+   reg = <0x7>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+ 
+   pci_phy1: pci-phy@0 {
+   compatible = "brcm,ns2-pcie-phy";
+   reg = <0x0>;
+   #phy-cells = <0>;
+   status = "disabled";
+   };
+   };
+ 
+   mdio@10 {
+   reg = <0x10>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   };
+   };
+ 
timer0: timer@6603 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x6603 0x1000>;


[PATCH net-next] net: dsa: b53: Fix statistics readings

2016-06-20 Thread Florian Fainelli
Due to a typo we would always be using the MIB counter width of the
first element of the counter array instead of the current element, and
we would always be accessing the register statistics with a 64-bits
read, while some could be 32-bits. This got unnoticed in testing with
MDIO and SRAB which tolerate doing this, but testing with the SPI bus
revealed bogus values being returned. Fix this by using the proper
iterator here.

Fixes: 967dd82ffc52 ("net: dsa: b53: Add support for Broadcom RoboSwitch")
Reported-by: Jonas Gorski 
Signed-off-by: Florian Fainelli 
---
 drivers/net/dsa/b53/b53_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 668d329b3e72..48fc63c22b6a 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -679,7 +679,7 @@ static void b53_get_ethtool_stats(struct dsa_switch *ds, 
int port,
for (i = 0; i < mib_size; i++) {
s = [i];
 
-   if (mibs->size == 8) {
+   if (s->size == 8) {
b53_read64(dev, B53_MIB_PAGE(port), s->offset, );
} else {
u32 val32;
-- 
2.7.4



Re: [PATCH net-next] openvswitch: Only set mark and labels when commiting a connection.

2016-06-20 Thread Jarno Rajahalme
The title should have been:

openvswitch: Only set mark and labels with a commit flag.

This reflects the fact that modifying the mark and/or labels of an existing 
connection is allowed. The commit flag is still required to do that, though.

  Jarno

> On Jun 20, 2016, at 5:19 PM, Jarno Rajahalme  wrote:
> 
> Only allow setting conntrack mark or labels when the commit flag is
> specified.  This makes sure we can not set them before the connection
> has been persisted, as in that case the mark and labels would be lost
> in an event of an userspace upcall.
> 
> OVS userspace already requires the commit flag to accept setting
> ct_mark and/or ct_labels.  Validate for this on the kernel API.
> 
> Finally, set conntrack mark and labels right before committing so that
> the initial conntrack NEW event has the mark and labels.
> 
> Signed-off-by: Jarno Rajahalme 
> ---
> net/openvswitch/conntrack.c | 72 ++---
> 1 file changed, 48 insertions(+), 24 deletions(-)
> 
> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> index 3d5feed..f1612f5 100644
> --- a/net/openvswitch/conntrack.c
> +++ b/net/openvswitch/conntrack.c
> @@ -824,6 +824,17 @@ static int ovs_ct_lookup(struct net *net, struct 
> sw_flow_key *key,
>   return 0;
> }
> 
> +static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
> +{
> + size_t i;
> +
> + for (i = 0; i < sizeof(*labels); i++)
> + if (labels->ct_labels[i])
> + return true;
> +
> + return false;
> +}
> +
> /* Lookup connection and confirm if unconfirmed. */
> static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
>const struct ovs_conntrack_info *info,
> @@ -834,24 +845,35 @@ static int ovs_ct_commit(struct net *net, struct 
> sw_flow_key *key,
>   err = __ovs_ct_lookup(net, key, info, skb);
>   if (err)
>   return err;
> - /* This is a no-op if the connection has already been confirmed. */
> +
> + /* As any changes to an unconfirmed connection may be lost due
> +  * to an upcall, we require the presence of the 'commit' flag
> +  * for setting mask and/or labels.  Perform the changes before
> +  * confirming the connection so that the initial mark and label
> +  * values are present in the initial CT NEW netlink event.
> +  */
> + if (info->mark.mask) {
> + err = ovs_ct_set_mark(skb, key, info->mark.value,
> +   info->mark.mask);
> + if (err)
> + return err;
> + }
> + if (labels_nonzero(>labels.mask)) {
> + err = ovs_ct_set_labels(skb, key, >labels.value,
> + >labels.mask);
> + if (err)
> + return err;
> + }
> +
> + /* Will take care of sending queued events even if the connection is
> +  * already confirmed.
> +  */
>   if (nf_conntrack_confirm(skb) != NF_ACCEPT)
>   return -EINVAL;
> 
>   return 0;
> }
> 
> -static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
> -{
> - size_t i;
> -
> - for (i = 0; i < sizeof(*labels); i++)
> - if (labels->ct_labels[i])
> - return true;
> -
> - return false;
> -}
> -
> /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
>  * value if 'skb' is freed.
>  */
> @@ -876,19 +898,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
>   err = ovs_ct_commit(net, key, info, skb);
>   else
>   err = ovs_ct_lookup(net, key, info, skb);
> - if (err)
> - goto err;
> 
> - if (info->mark.mask) {
> - err = ovs_ct_set_mark(skb, key, info->mark.value,
> -   info->mark.mask);
> - if (err)
> - goto err;
> - }
> - if (labels_nonzero(>labels.mask))
> - err = ovs_ct_set_labels(skb, key, >labels.value,
> - >labels.mask);
> -err:
>   skb_push(skb, nh_ofs);
>   if (err)
>   kfree_skb(skb);
> @@ -1145,6 +1155,20 @@ static int parse_ct(const struct nlattr *attr, struct 
> ovs_conntrack_info *info,
>   }
>   }
> 
> +#ifdef CONFIG_NF_CONNTRACK_MARK
> + if (!info->commit && info->mark.mask) {
> + OVS_NLERR(log,
> +   "Setting conntrack mark requires 'commit' flag.");
> + return -EINVAL;
> + }
> +#endif
> +#ifdef CONFIG_NF_CONNTRACK_LABELS
> + if (!info->commit && labels_nonzero(>labels.mask)) {
> + OVS_NLERR(log,
> +   "Setting conntrack labels requires 'commit' flag.");
> + return -EINVAL;
> + }
> +#endif
>   if (rem > 0) {
>   OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
>   return -EINVAL;
> -- 
> 2.1.4
> 



[patch net-next 08/23] mlxsw: spectrum: Centralize VLAN-aware bridge ref counting

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

We hold a reference count on the number of ports member in the
VLAN-aware bridge, as we only support one.

Instead of always incrementing / decrementing the reference count after
joining / leaving the bridge, simply do this accounting in the join /
leave functions.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 58 +-
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index cd85316..b999802 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2651,7 +2651,28 @@ static bool mlxsw_sp_port_dev_check(const struct 
net_device *dev)
return dev->netdev_ops == _sp_port_netdev_ops;
 }
 
-static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port)
+static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
+struct net_device *br_dev)
+{
+   return !mlxsw_sp->master_bridge.dev ||
+  mlxsw_sp->master_bridge.dev == br_dev;
+}
+
+static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
+  struct net_device *br_dev)
+{
+   mlxsw_sp->master_bridge.dev = br_dev;
+   mlxsw_sp->master_bridge.ref_count++;
+}
+
+static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
+{
+   if (--mlxsw_sp->master_bridge.ref_count == 0)
+   mlxsw_sp->master_bridge.dev = NULL;
+}
+
+static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
+struct net_device *br_dev)
 {
struct net_device *dev = mlxsw_sp_port->dev;
int err;
@@ -2665,6 +2686,8 @@ static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port 
*mlxsw_sp_port)
if (err)
return err;
 
+   mlxsw_sp_master_bridge_inc(mlxsw_sp_port->mlxsw_sp, br_dev);
+
mlxsw_sp_port->learning = 1;
mlxsw_sp_port->learning_sync = 1;
mlxsw_sp_port->uc_flood = 1;
@@ -2683,6 +2706,8 @@ static void mlxsw_sp_port_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_port,
 
mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
 
+   mlxsw_sp_master_bridge_dec(mlxsw_sp_port->mlxsw_sp);
+
mlxsw_sp_port->learning = 0;
mlxsw_sp_port->learning_sync = 0;
mlxsw_sp_port->uc_flood = 0;
@@ -2694,26 +2719,6 @@ static void mlxsw_sp_port_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port_add_vid(dev, 0, 1);
 }
 
-static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
-struct net_device *br_dev)
-{
-   return !mlxsw_sp->master_bridge.dev ||
-  mlxsw_sp->master_bridge.dev == br_dev;
-}
-
-static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
-  struct net_device *br_dev)
-{
-   mlxsw_sp->master_bridge.dev = br_dev;
-   mlxsw_sp->master_bridge.ref_count++;
-}
-
-static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
-{
-   if (--mlxsw_sp->master_bridge.ref_count == 0)
-   mlxsw_sp->master_bridge.dev = NULL;
-}
-
 static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
 {
char sldr_pl[MLXSW_REG_SLDR_LEN];
@@ -2910,7 +2915,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port 
*mlxsw_sp_port,
if (mlxsw_sp_port->bridged) {
mlxsw_sp_port_active_vlans_del(mlxsw_sp_port);
mlxsw_sp_port_bridge_leave(mlxsw_sp_port, false);
-   mlxsw_sp_master_bridge_dec(mlxsw_sp);
}
 
if (lag->ref_count == 1) {
@@ -3049,13 +3053,11 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
 mlxsw_sp_port_vlan_unlink(mlxsw_sp_port,
   upper_dev);
} else if (netif_is_bridge_master(upper_dev)) {
-   if (info->linking) {
-   err = mlxsw_sp_port_bridge_join(mlxsw_sp_port);
-   mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev);
-   } else {
+   if (info->linking)
+   err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
+   upper_dev);
+   else
mlxsw_sp_port_bridge_leave(mlxsw_sp_port, true);
-   mlxsw_sp_master_bridge_dec(mlxsw_sp);
-   }
} else if (netif_is_lag_master(upper_dev)) {
if (info->linking)
err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
-- 
2.5.5



Re: [PATCH 0/3] *** Mesh Path Selection Metric Calculation ***

2016-06-20 Thread Peter Oh
where is 2/3 ?
On 06/20/2016 06:00 AM, Maxim Altshul wrote:
> Hi All,
> This patch series focuses on metric calculation that
> occurs during the path selection phase of a mesh network.
>
> During the path selection phase, the mesh hwmp module
> performs metric calculations, that take as parameters
> the last TX rate that was used for a specific link,
> and the packet error rate.
>
> These parameters should be reported by the FW to the driver
> constantly for the mechanism to work properly.
>
> In case that a vendor offloads the rate control mechanism
> to the FW, these parameters will be rarely updated,
> or updated incorrectly.
>
> This situation causes the mesh hwmp module to calculate incorrect
> metrics and as a consequence, not to choose the best paths possible.
>
>
> This patch series is divided to three patches and does the following:
>
> 1. Modifies mesh hwmp module and allows vendors that offload the
> rate control mechanism to their FW, to report last TX rates and PER
> to the mesh hwmp module by using an existing op called
> get_expected_throughput.
> In case that a vendor does not implement the op, all previous
> functionality still applies.
>
> 2. Implements the opcode and the mechanism that reports the rates
> in TI driver.
>
> Maxim Altshul (3):
>   wlcore/wl18xx: Add functionality to accept TX rate per link
>   wlcore: Add support for get_expected_throughput opcode
>   mac80211: mesh: Add support for HW RC implementation
>
>  drivers/net/wireless/ti/wl18xx/main.c |  4 
>  drivers/net/wireless/ti/wl18xx/tx.c   | 22 ++
>  drivers/net/wireless/ti/wl18xx/wl18xx.h   |  6 +-
>  drivers/net/wireless/ti/wlcore/main.c | 16 
>  drivers/net/wireless/ti/wlcore/rx.c   |  7 +++
>  drivers/net/wireless/ti/wlcore/wlcore_i.h | 13 +
>  net/mac80211/mesh_hwmp.c  | 23 +++
>  7 files changed, 78 insertions(+), 13 deletions(-)
>



[PATCH net-next] of_mdio: Enable fixed PHY support if driver is a module

2016-06-20 Thread Ben Hutchings
The fixed_phy driver doesn't have to be built-in, and it's
important that of_mdio supports it even if it's a module.

Signed-off-by: Ben Hutchings 
---
Re-sending with the proper subject prefix.

Ben.

--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -274,7 +274,7 @@ struct phy_device *of_phy_attach(struct
 }
 EXPORT_SYMBOL(of_phy_attach);
 
-#if defined(CONFIG_FIXED_PHY)
+#if IS_ENABLED(CONFIG_FIXED_PHY)
 /*
  * of_phy_is_fixed_link() and of_phy_register_fixed_link() must
  * support two DT bindings:
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -69,7 +69,7 @@ static inline int of_mdio_parse_addr(str
 }
 #endif /* CONFIG_OF */
 
-#if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY)
+#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_FIXED_PHY)
 extern int of_phy_register_fixed_link(struct device_node *np);
 extern bool of_phy_is_fixed_link(struct device_node *np);
 #else


-- 
Ben Hutchings
Software Developer, Codethink Ltd.




[PATCH net-next] ti_cpsw: Check for disabled child nodes

2016-06-20 Thread Ben Hutchings
Dual MAC devices don't necessarily have both MACs wired up, so ignore
those that are disabled.

Signed-off-by: Ben Hutchings 
---
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2023,7 +2023,7 @@ static int cpsw_probe_dt(struct cpsw_pri
if (ret)
dev_warn(>dev, "Doesn't have any child node\n");
 
-   for_each_child_of_node(node, slave_node) {
+   for_each_available_child_of_node(node, slave_node) {
struct cpsw_slave_data *slave_data = data->slave_data + i;
const void *mac_addr = NULL;
int lenp;

-- 
Ben Hutchings
Software Developer, Codethink Ltd.




of_mdio: Enable fixed PHY support if driver is a module

2016-06-20 Thread Ben Hutchings
The fixed_phy driver doesn't have to be built-in, and it's
important that of_mdio supports it even if it's a module.

Signed-off-by: Ben Hutchings 
---
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -274,7 +274,7 @@ struct phy_device *of_phy_attach(struct
 }
 EXPORT_SYMBOL(of_phy_attach);
 
-#if defined(CONFIG_FIXED_PHY)
+#if IS_ENABLED(CONFIG_FIXED_PHY)
 /*
  * of_phy_is_fixed_link() and of_phy_register_fixed_link() must
  * support two DT bindings:
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -69,7 +69,7 @@ static inline int of_mdio_parse_addr(str
 }
 #endif /* CONFIG_OF */
 
-#if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY)
+#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_FIXED_PHY)
 extern int of_phy_register_fixed_link(struct device_node *np);
 extern bool of_phy_is_fixed_link(struct device_node *np);
 #else

-- 
Ben Hutchings
Software Developer, Codethink Ltd.




Re: [6/6] ppc: ebpf/jit: Implement JIT compiler for extended BPF

2016-06-20 Thread Michael Ellerman
On Sun, 2016-06-19 at 23:06 +0530, Naveen N. Rao wrote:
> On 2016/06/17 10:53PM, Michael Ellerman wrote:
> > On Tue, 2016-07-06 at 13:32:23 UTC, "Naveen N. Rao" wrote:
> > > diff --git a/arch/powerpc/net/bpf_jit_comp64.c 
> > > b/arch/powerpc/net/bpf_jit_comp64.c
> > > new file mode 100644
> > > index 000..954ff53
> > > --- /dev/null
> > > +++ b/arch/powerpc/net/bpf_jit_comp64.c
> > > @@ -0,0 +1,956 @@
> > ...

> > > +
> > > +static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
> > > +{
> > > + int *p = area;
> > > +
> > > + /* Fill whole space with trap instructions */
> > > + while (p < (int *)((char *)area + size))
> > > + *p++ = BREAKPOINT_INSTRUCTION;
> > > +}
> > 
> > This breaks the build for some configs, presumably you're missing a header:
> > 
> >   arch/powerpc/net/bpf_jit_comp64.c:30:10: error: 'BREAKPOINT_INSTRUCTION' 
> > undeclared (first use in this function)
> > 
> > http://kisskb.ellerman.id.au/kisskb/buildresult/12720611/
> 
> Oops. Yes, I should have caught that. I need to add:
> 
> #include 
> 
> in bpf_jit_comp64.c
> 
> Can you please check if it resolves the build error?

Can you? :D

cheers



[PATCH net] netem: fix a use after free

2016-06-20 Thread Eric Dumazet
From: Eric Dumazet 

If the packet was dropped by lower qdisc, then we must not
access it later.

Save qdisc_pkt_len(skb) in a temp variable.

Fixes: 2f5fb43f ("net_sched: update hierarchical backlog too")
Signed-off-by: Eric Dumazet 
Cc: WANG Cong 
Cc: Jamal Hadi Salim 
Cc: Stephen Hemminger 
---
 net/sched/sch_netem.c |   12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 205bed00dd34..178f1630a036 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -650,14 +650,14 @@ deliver:
 #endif
 
if (q->qdisc) {
+   unsigned int pkt_len = qdisc_pkt_len(skb);
int err = qdisc_enqueue(skb, q->qdisc);
 
-   if (unlikely(err != NET_XMIT_SUCCESS)) {
-   if (net_xmit_drop_count(err)) {
-   qdisc_qstats_drop(sch);
-   qdisc_tree_reduce_backlog(sch, 
1,
- 
qdisc_pkt_len(skb));
-   }
+   if (err != NET_XMIT_SUCCESS &&
+   net_xmit_drop_count(err)) {
+   qdisc_qstats_drop(sch);
+   qdisc_tree_reduce_backlog(sch, 1,
+ pkt_len);
}
goto tfifo_dequeue;
}




Re: [PATCH net] netem: fix a use after free

2016-06-20 Thread Cong Wang
On Mon, Jun 20, 2016 at 3:00 PM, Eric Dumazet  wrote:
> From: Eric Dumazet 
>
> If the packet was dropped by lower qdisc, then we must not
> access it later.
>
> Save qdisc_pkt_len(skb) in a temp variable.
>
> Fixes: 2f5fb43f ("net_sched: update hierarchical backlog too")
> Signed-off-by: Eric Dumazet 
> Cc: WANG Cong 
> Cc: Jamal Hadi Salim 
> Cc: Stephen Hemminger 


Acked-by: Cong Wang 


[patch net-next 00/23] mlxsw: Preparation for IPv4 router

2016-06-20 Thread Jiri Pirko
From: Jiri Pirko 

Ido says:

This series prepares the driver for IPv4 router support. The router follow-up
patches are available at: 
https://github.com/jpirko/linux_mlxsw/tree/net-next_queue

Patches 1-9 simplify the netdevice notification block and also add several
checks during PRECHANGEUPPER events against topologies that aren't supported by
the device. This will ensure L3 interfaces are only configured on top of
valid netdevs.

Patches 10-13 contain trivial changes required for the introduction of a generic
FID struct - currently only used for vFIDs - in patch 14. Making the FID
struct generic will allow us to easily associate the underlying FIDs with
their L3-counterparts - Router interfaces (RIFs):

FID Type| Used by | RIF Type

FID | The VLAN-aware bridge   | VLAN
vFID| VLAN-unaware bridges| FID
rFID| non-bridged netdevs (follow-up) | Sub-port

Obligatory ASCII art to visualize the above:

   A.B.C.D
  +
  | FID RIF
  +
 br0E.F.G.H
  ++
  || VLAN RIF
+-+-+  +
|   |br1.W
| vFID  |  +
|   |  |
 vPort+-+-+   +-+-++
swXpY.Z   |   |   |   |   br1
  +-+-+   +-+-++
|   | FID=W|
|   | +++
|   | | |
+---+---+   +---+-+-+   +---+---+
|   |   |   |   |   |
|   |   |   |   |   |
|   |   |   |   |   |
+---+   +---+   +---+
  swXpY

Patches 15-16 further generalize the struct by exploiting the fact that the
FID is a shared resource among ports. Each FID type is assigned a 'leave'
function that is invoked based on CHANGEUPPER events and takes care of the
necessary clean-up.

Patches 17-22 build upon the previous patches and use the FID struct for the
VLAN-aware bridge and take care of cleaning up FID resources in the 'leave'
functions. For now, these are only FDB records, but later on we'll have to
remove the RIFs associated with these FIDs, which will in turn take care of
routes and neighbours clean-up.

The last patch adds debug prints that proved very useful during the
development of this series.

Tested with the existing L2 recipes:
https://github.com/jpirko/lnst/tree/master/recipes/switchdev

Ido Schimmel (23):
  mlxsw: spectrum: Use notifier_from_errno() in notifier block
  mlxsw: spectrum: Sanitize port netdev upper devices
  mlxsw: spectrum: Forbid LAG slave from having VLAN uppers
  mlxsw: spectrum: Remove unnecessary checks from event processing
  mlxsw: spectrum: Use WARN_ON() return value
  mlxsw: spectrum: Make unlinking functions return void
  mlxsw: spectrum: Remove unnecessary function argument
  mlxsw: spectrum: Centralize VLAN-aware bridge ref counting
  mlxsw: spectrum: Use DECLARE_BITMAP() macro
  mlxsw: spectrum: Remove redundant function argument
  mlxsw: spectrum: Use only one function to create vFIDs
  mlxsw: spectrum: Create a function to map vPort's FID
  mlxsw: spectrum: Use FID instead of vFID to setup flooding
  mlxsw: spectrum: Make vFID struct generic
  mlxsw: spectrum: Use join / leave functions for vFID operations
  mlxsw: spectrum: Remove unused function argument
  mlxsw: spectrum: Use per-FID struct for the VLAN-aware bridge
  mlxsw: spectrum: Check if port is vPort using its VID
  mlxsw: spectrum: Add FID get / set functions
  mlxsw: spectrum: Don't count on FID being present
  mlxsw: spectrum: Refactor FDB flushing logic
  mlxsw: spectrum: Free resources upon vPort destruction
  mlxsw: spectrum: Add debug prints

 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 852 -
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  62 +-
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 362 +
 3 files changed, 592 insertions(+), 684 deletions(-)

-- 
2.5.5



Re: [PATCH net-next] net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)

2016-06-20 Thread Francois Romieu
Netanel Belgazal  :
[...]
> > diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h 
> > b/drivers/net/ethernet/amazon/ena/ena_com.h
> > new file mode 100644
> > index 000..e49ba43
> > --- /dev/null
> > [...]
> > +static inline void ena_com_update_intr_reg(struct ena_eth_io_intr_reg 
> > *intr_reg,
> > +  u32 rx_delay_interval,
> > +  u32 tx_delay_interval,
> > +  bool unmask)
> > +{
> > +   intr_reg->intr_control = 0;
> > +   intr_reg->intr_control |= rx_delay_interval &
> > +   ENA_ETH_IO_INTR_REG_RX_INTR_DELAY_MASK;
> > +
> > +   intr_reg->intr_control |=
> > +   (tx_delay_interval << ENA_ETH_IO_INTR_REG_TX_INTR_DELAY_SHIFT)
> > +   & ENA_ETH_IO_INTR_REG_RX_INTR_DELAY_MASK;
> >   ^^ TX ?
> >
> > Extra: you should not return NETDEV_TX_BUSY in the xmit handler while
> > queueing is still enabled. Please drop packet and return NETDEV_TX_OK.
> Ack.
> 
> Thanks for your review.

Ack/nack regarding use of ..._RX_INTR_DELAY_MASK with ..._TX_INTR_DELAY_SHIFT ?

-- 
Ueimor


[Patch net 1/2] act_ife: only acquire tcf_lock for existing actions

2016-06-20 Thread Cong Wang
Alexey reported that we have GFP_KERNEL allocation when
holding the spinlock tcf_lock. Actually we don't have
to take that spinlock for all the cases, especially
for the new one we just create. To modify the existing
actions, we still need this spinlock to make sure
the whole update is atomic.

For net-next, we can get rid of this spinlock because
we already hold the RTNL lock on slow path, and on fast
path we can use RCU to protect the metalist.

Joint work with Jamal.

Reported-by: Alexey Khoroshilov 
Cc: Jamal Hadi Salim 
Signed-off-by: Cong Wang 
---
 include/net/tc_act/tc_ife.h |  6 ++---
 net/sched/act_ife.c | 55 +
 2 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/include/net/tc_act/tc_ife.h b/include/net/tc_act/tc_ife.h
index dc9a09a..c55facd 100644
--- a/include/net/tc_act/tc_ife.h
+++ b/include/net/tc_act/tc_ife.h
@@ -36,7 +36,7 @@ struct tcf_meta_ops {
int (*encode)(struct sk_buff *, void *, struct tcf_meta_info *);
int (*decode)(struct sk_buff *, void *, u16 len);
int (*get)(struct sk_buff *skb, struct tcf_meta_info *mi);
-   int (*alloc)(struct tcf_meta_info *, void *);
+   int (*alloc)(struct tcf_meta_info *, void *, gfp_t);
void(*release)(struct tcf_meta_info *);
int (*validate)(void *val, int len);
struct module   *owner;
@@ -48,8 +48,8 @@ int ife_get_meta_u32(struct sk_buff *skb, struct 
tcf_meta_info *mi);
 int ife_get_meta_u16(struct sk_buff *skb, struct tcf_meta_info *mi);
 int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval);
-int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval);
-int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval);
+int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval, gfp_t gfp);
+int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval, gfp_t gfp);
 int ife_check_meta_u32(u32 metaval, struct tcf_meta_info *mi);
 int ife_encode_meta_u32(u32 metaval, void *skbdata, struct tcf_meta_info *mi);
 int ife_validate_meta_u32(void *val, int len);
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 658046d..e407659 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -106,9 +106,9 @@ int ife_get_meta_u16(struct sk_buff *skb, struct 
tcf_meta_info *mi)
 }
 EXPORT_SYMBOL_GPL(ife_get_meta_u16);
 
-int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval)
+int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval, gfp_t gfp)
 {
-   mi->metaval = kmemdup(metaval, sizeof(u32), GFP_KERNEL);
+   mi->metaval = kmemdup(metaval, sizeof(u32), gfp);
if (!mi->metaval)
return -ENOMEM;
 
@@ -116,9 +116,9 @@ int ife_alloc_meta_u32(struct tcf_meta_info *mi, void 
*metaval)
 }
 EXPORT_SYMBOL_GPL(ife_alloc_meta_u32);
 
-int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval)
+int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval, gfp_t gfp)
 {
-   mi->metaval = kmemdup(metaval, sizeof(u16), GFP_KERNEL);
+   mi->metaval = kmemdup(metaval, sizeof(u16), gfp);
if (!mi->metaval)
return -ENOMEM;
 
@@ -240,10 +240,10 @@ static int ife_validate_metatype(struct tcf_meta_ops 
*ops, void *val, int len)
 }
 
 /* called when adding new meta information
- * under ife->tcf_lock
+ * under ife->tcf_lock for existing action
 */
 static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
-   void *val, int len)
+   void *val, int len, bool exists)
 {
struct tcf_meta_ops *ops = find_ife_oplist(metaid);
int ret = 0;
@@ -251,11 +251,13 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, 
u32 metaid,
if (!ops) {
ret = -ENOENT;
 #ifdef CONFIG_MODULES
-   spin_unlock_bh(>tcf_lock);
+   if (exists)
+   spin_unlock_bh(>tcf_lock);
rtnl_unlock();
request_module("ifemeta%u", metaid);
rtnl_lock();
-   spin_lock_bh(>tcf_lock);
+   if (exists)
+   spin_lock_bh(>tcf_lock);
ops = find_ife_oplist(metaid);
 #endif
}
@@ -272,10 +274,10 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, 
u32 metaid,
 }
 
 /* called when adding new meta information
- * under ife->tcf_lock
+ * under ife->tcf_lock for existing action
 */
 static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
-   int len)
+   int len, bool exists)
 {
struct tcf_meta_info *mi = NULL;
struct tcf_meta_ops *ops = find_ife_oplist(metaid);
@@ -284,7 +286,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 
metaid, void *metaval,
if (!ops)
return -ENOENT;
 
-   mi = 

Re: [PATCH net-next] tcp: reduce cpu usage when SO_SNDBUF is set

2016-06-20 Thread Eric Dumazet
On Mon, 2016-06-20 at 17:23 -0400, Jason Baron wrote:
> From: Jason Baron 
> 
> When SO_SNDBUF is set and we are under tcp memory pressure, the effective
> write buffer space can be much lower than what was set using SO_SNDBUF. For
> example, we may have set the buffer to 100kb, but we may only be able to
> write 10kb. In this scenario poll()/select()/epoll(), are going to
> continuously return POLLOUT, followed by -EAGAIN from write(), and thus
> result in a tight loop. Note that epoll in edge-triggered does not have
> this issue since it only triggers once data has been ack'd. There is no
> issue here when SO_SNDBUF is not set, since the tcp layer will auto tune
> the sk->sndbuf.
> 
> Introduce a new socket flag, SOCK_SHORT_WRITE, such that we can mark the
> socket when we have a short write due to memory pressure. By then testing
> for SOCK_SHORT_WRITE in tcp_poll(), we hold off the POLLOUT until a
> non-zero amount of data has been ack'd. In a previous approach:
> http://marc.info/?l=linux-netdev=143930393211782=2, I had introduced a
> new field in 'struct sock' to solve this issue, but its undesirable to add
> bloat to 'struct sock'. We also could address this issue, by waiting for
> the buffer to become completely empty, but that may reduce throughput since
> the write buffer would be empty while waiting for subsequent writes. This
> change brings us in line with the current epoll edge-trigger behavior for
> the poll()/select() and epoll level-trigger.
> 
> We guarantee that SOCK_SHORT_WRITE will eventually clear, since when we set
> SOCK_SHORT_WRITE, we make sure that sk_wmem_queued is non-zero and
> SOCK_NOSPACE is set as well (in sk_stream_wait_memory()).
> 
> I tested this patch using 10,000 sockets, and setting SO_SNDBUF on the
> server side, to induce tcp memory pressure. A single server thread reduced
> its cpu usage from 100% to 19%, while maintaining the same level of
> throughput.
> 
> Signed-off-by: Jason Baron 
> ---


When this bug was added, and by which commit ?

This looks serious, but your patch looks way too complex.

This SOCK_SHORT_WRITE bit constantly cleared in sk_stream_write_space()
is expensive, because it dirties sk_flags which is not supposed to
written often. This field is located in a read mostly cache line.

I believe my suggestion was not to add a per socket bit,
but have a global state like tcp_memory_pressure. (or reuse it)

Ie , when under global memory pressure, tcp_poll() should apply a
strategy to give POLLOUT only on sockets having less than 4K
(tcp_wmem[0]) of memory consumed in their write queue.






Re: [PATCH 1/2] NET: PHY: Add PHY LED control binding.

2016-06-20 Thread Hauke Mehrtens
On 06/09/2016 10:13 PM, Hauke Mehrtens wrote:
> On 06/09/2016 08:12 AM, John Crispin wrote:
>>
>>
>> On 09/06/2016 08:06, Alexander Stein wrote:
>>> On Wednesday 08 June 2016 14:30:08, Rob Herring wrote:
> diff --git a/Documentation/devicetree/bindings/phy/phy-leds.txt
> b/Documentation/devicetree/bindings/phy/phy-leds.txt new file mode 100644
> index 000..1a35e3d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/phy-leds.txt
> @@ -0,0 +1,52 @@
> +LED configuration for Ethernet phys
> +
> +All these properties are optional, not all properties are supported by
> +all PHYs. When more then one property name is define for one LED the
> +order they get applied is device depended.
> +Property names:
> + led-const-on: conditions the LED should be constant on
> + led-pulse: condition the LED should be pulsed on
> + led-blink-slow: condition the LED should slowly blink

 How slow is slow?
>>>
>>> This depends on the MMD.INTERNAL.LEDCH.SBF setting which is 2 Hz by default.
>>>
> + led-blink-fast: condition the LED should fast blink

 How fast is fast?
>>>
>>> This depends on the MMD.INTERNAL.LEDCH.FBF setting which is 16 Hz by 
>>> default.
>>>
>>> Both can be set independently to 2, 4, 8 or 16 Hz.
>>>
>>
>> and both are intel/lantiq implementation specific and hence should not
>> be part of a generic led-phy binding.
> 
> Ok, I can remove them, I think the constant on and the pulse are used by
> many Ethernet PHYs.
> 
>> imho these leds should be exposed via a led driver and the configurtion
>> should be exposed via a led driver specific trigger, in the same manner
>> in which wireless macs do it.
> 
> Where is a good example on how this is done?
> Is this then also triggered by the hardware or does the software has to
> trigger it?
> 
> Hauke
> 

I looked into ath9k and could only find a normal LED device which gets
triggered by the software here:
http://lxr.free-electrons.com/source/drivers/net/wireless/ath/ath9k/gpio.c#L45
This also registers a LED trigger in mac80211, but that also looks like
it triggers it by software:
http://lxr.free-electrons.com/source/net/mac80211/led.c#L286

In the PHY use case using software to trigger the LEDs is not so good
because the PHYs could on a hardware switch and it could be that the
traffic is not seen by the CPU.

Hauke


[patch net-next 17/23] mlxsw: spectrum: Use per-FID struct for the VLAN-aware bridge

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

In a very similar way to the vFIDs, make the first 4K FIDs - used in the
VLAN-aware bridge - use the new FID struct.

Upon first use of the FID by any of the ports do the following:

1) Create the FID
2) Setup a matching flooding entry
3) Create a mapping for the FID

Unlike vFIDs, upon creation of a FID we always create a global
VID-to-FID mapping, so that ports without upper vPorts can use it
instead of creating an explicit {Port, VID} to FID mapping.

When a port leaves a FID the reverse is performed. Whenever the FID's
reference count reaches zero the FID is deleted along with the global
mapping.

The per-FID struct will later allow us to configure L3 interfaces on top
of the VLAN-aware bridge.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |   2 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |   2 +-
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 316 +
 3 files changed, 195 insertions(+), 125 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 4869392..08f3f51 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2396,6 +2396,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 
mlxsw_sp->core = mlxsw_core;
mlxsw_sp->bus_info = mlxsw_bus_info;
+   INIT_LIST_HEAD(_sp->fids);
INIT_LIST_HEAD(_sp->port_vfids.list);
INIT_LIST_HEAD(_sp->br_vfids.list);
INIT_LIST_HEAD(_sp->br_mids.list);
@@ -2472,6 +2473,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_traps_fini(mlxsw_sp);
mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
mlxsw_sp_ports_remove(mlxsw_sp);
+   WARN_ON(!list_empty(_sp->fids));
 }
 
 static struct mlxsw_config_profile mlxsw_sp_config_profile = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index c973ab5..d6cf6de 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -165,7 +165,7 @@ struct mlxsw_sp {
struct list_head list;
DECLARE_BITMAP(mapped, MLXSW_SP_MID_MAX);
} br_mids;
-   DECLARE_BITMAP(active_fids, VLAN_N_VID);
+   struct list_head fids;  /* VLAN-aware bridge FIDs */
struct mlxsw_sp_port **ports;
struct mlxsw_core *core;
const struct mlxsw_bus_info *bus_info;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 3e9ba58..6713769 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -384,6 +384,192 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
return err;
 }
 
+static struct mlxsw_sp_fid *mlxsw_sp_fid_find(struct mlxsw_sp *mlxsw_sp,
+ u16 fid)
+{
+   struct mlxsw_sp_fid *f;
+
+   list_for_each_entry(f, _sp->fids, list)
+   if (f->fid == fid)
+   return f;
+
+   return NULL;
+}
+
+static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid, bool create)
+{
+   char sfmr_pl[MLXSW_REG_SFMR_LEN];
+
+   mlxsw_reg_sfmr_pack(sfmr_pl, !create, fid, fid);
+   return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
+}
+
+static int mlxsw_sp_fid_map(struct mlxsw_sp *mlxsw_sp, u16 fid, bool valid)
+{
+   enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
+   char svfa_pl[MLXSW_REG_SVFA_LEN];
+
+   mlxsw_reg_svfa_pack(svfa_pl, 0, mt, valid, fid, fid);
+   return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
+}
+
+static struct mlxsw_sp_fid *mlxsw_sp_fid_alloc(u16 fid)
+{
+   struct mlxsw_sp_fid *f;
+
+   f = kzalloc(sizeof(*f), GFP_KERNEL);
+   if (!f)
+   return NULL;
+
+   f->fid = fid;
+
+   return f;
+}
+
+static struct mlxsw_sp_fid *mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp,
+   u16 fid)
+{
+   struct mlxsw_sp_fid *f;
+   int err;
+
+   err = mlxsw_sp_fid_op(mlxsw_sp, fid, true);
+   if (err)
+   return ERR_PTR(err);
+
+   /* Although all the ports member in the FID might be using a
+* {Port, VID} to FID mapping, we create a global VID-to-FID
+* mapping. This allows a port to transition to VLAN mode,
+* knowing the global mapping exists.
+*/
+   err = mlxsw_sp_fid_map(mlxsw_sp, fid, true);
+   if (err)
+   goto err_fid_map;
+
+   f = mlxsw_sp_fid_alloc(fid);
+   if (!f) {
+   err = -ENOMEM;
+   goto err_allocate_fid;
+   }
+
+   list_add(>list, 

[patch net-next 06/23] mlxsw: spectrum: Make unlinking functions return void

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

When responding to unlinking CHANGEUPPER notifications we shouldn't
return any value, as it's not checked by upper layers.

In addition, there's nothing the driver can do in case of failure, so it
should simply continue and try to free as much resources as possible and
not stop on first error.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 68 +++---
 1 file changed, 28 insertions(+), 40 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index f297b10..3500a72 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2673,8 +2673,8 @@ static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port 
*mlxsw_sp_port)
return 0;
 }
 
-static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
- bool flush_fdb)
+static void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
+  bool flush_fdb)
 {
struct net_device *dev = mlxsw_sp_port->dev;
 
@@ -2691,7 +2691,7 @@ static int mlxsw_sp_port_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_port,
/* Add implicit VLAN interface in the device, so that untagged
 * packets will be classified to the default vFID.
 */
-   return mlxsw_sp_port_add_vid(dev, 0, 1);
+   mlxsw_sp_port_add_vid(dev, 0, 1);
 }
 
 static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
@@ -2873,30 +2873,25 @@ err_col_port_add:
return err;
 }
 
-static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
-  struct net_device *br_dev,
-  bool flush_fdb);
+static void mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
+   struct net_device *br_dev,
+   bool flush_fdb);
 
-static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
-  struct net_device *lag_dev)
+static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
+   struct net_device *lag_dev)
 {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_port *mlxsw_sp_vport;
struct mlxsw_sp_upper *lag;
u16 lag_id = mlxsw_sp_port->lag_id;
-   int err;
 
if (!mlxsw_sp_port->lagged)
-   return 0;
+   return;
lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
WARN_ON(lag->ref_count == 0);
 
-   err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id);
-   if (err)
-   return err;
-   err = mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
-   if (err)
-   return err;
+   mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id);
+   mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 
/* In case we leave a LAG device that has bridges built on top,
 * then their teardown sequence is never issued and we need to
@@ -2922,16 +2917,13 @@ static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port 
*mlxsw_sp_port,
if (lag->ref_count == 1) {
if (mlxsw_sp_port_fdb_flush_by_lag_id(mlxsw_sp_port))
netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n");
-   err = mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
-   if (err)
-   return err;
+   mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
}
 
mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
 mlxsw_sp_port->local_port);
mlxsw_sp_port->lagged = 0;
lag->ref_count--;
-   return 0;
 }
 
 static int mlxsw_sp_lag_dist_port_add(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -2988,15 +2980,15 @@ static int mlxsw_sp_port_vlan_link(struct mlxsw_sp_port 
*mlxsw_sp_port,
return 0;
 }
 
-static int mlxsw_sp_port_vlan_unlink(struct mlxsw_sp_port *mlxsw_sp_port,
-struct net_device *vlan_dev)
+static void mlxsw_sp_port_vlan_unlink(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *vlan_dev)
 {
struct mlxsw_sp_port *mlxsw_sp_vport;
u16 vid = vlan_dev_vlan_id(vlan_dev);
 
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
if (WARN_ON(!mlxsw_sp_vport))
-   return -EINVAL;
+   return;
 
/* When removing a VLAN device while still bridged we should first
 * remove it from the bridge, as we receive the bridge's notification
@@ -3010,8 +3002,6 @@ static int mlxsw_sp_port_vlan_unlink(struct mlxsw_sp_port 
*mlxsw_sp_port,
}
 

[PATCH net] netem: fix a use after free

2016-06-20 Thread Eric Dumazet
From: Eric Dumazet 

If the packet was dropped by lower qdisc, then we must not
access it later.

Save qdisc_pkt_len(skb) in a temp variable.

Fixes: 2f5fb43f ("net_sched: update hierarchical backlog too")
Signed-off-by: Eric Dumazet 
Cc: WANG Cong 
Cc: Jamal Hadi Salim 
Cc: Stephen Hemminger 
---
 net/sched/sch_netem.c |   12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)





[patch net-next 11/23] mlxsw: spectrum: Use only one function to create vFIDs

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Simplify the code and use only one function for vFID creation /
destruction.

Unlike before, the function receives a FID index as its argument and not
a vFID index. Instead of passing 0, now one would need to pass 4K, which
is the first vFID.

This is the first step in creating a generic FID struct that will be
used for all three types of FIDs.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 79 --
 1 file changed, 37 insertions(+), 42 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 90cf6c5..4f53dd2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -652,68 +652,61 @@ static u16 mlxsw_sp_avail_vfid_get(const struct mlxsw_sp 
*mlxsw_sp)
   MLXSW_SP_VFID_PORT_MAX);
 }
 
-static int __mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp, u16 vfid)
+static int mlxsw_sp_vfid_op(struct mlxsw_sp *mlxsw_sp, u16 fid, bool create)
 {
-   u16 fid = mlxsw_sp_vfid_to_fid(vfid);
char sfmr_pl[MLXSW_REG_SFMR_LEN];
 
-   mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid, 0);
+   mlxsw_reg_sfmr_pack(sfmr_pl, !create, fid, 0);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
 }
 
-static void __mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp, u16 vfid)
-{
-   u16 fid = mlxsw_sp_vfid_to_fid(vfid);
-   char sfmr_pl[MLXSW_REG_SFMR_LEN];
-
-   mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_DESTROY_FID, fid, 0);
-   mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
-}
-
 static struct mlxsw_sp_vfid *mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp,
  u16 vid)
 {
struct device *dev = mlxsw_sp->bus_info->dev;
-   struct mlxsw_sp_vfid *vfid;
-   u16 n_vfid;
+   struct mlxsw_sp_vfid *f;
+   u16 vfid, fid;
int err;
 
-   n_vfid = mlxsw_sp_avail_vfid_get(mlxsw_sp);
-   if (n_vfid == MLXSW_SP_VFID_PORT_MAX) {
+   vfid = mlxsw_sp_avail_vfid_get(mlxsw_sp);
+   if (vfid == MLXSW_SP_VFID_PORT_MAX) {
dev_err(dev, "No available vFIDs\n");
return ERR_PTR(-ERANGE);
}
 
-   err = __mlxsw_sp_vfid_create(mlxsw_sp, n_vfid);
+   fid = mlxsw_sp_vfid_to_fid(vfid);
+   err = mlxsw_sp_vfid_op(mlxsw_sp, fid, true);
if (err) {
-   dev_err(dev, "Failed to create vFID=%d\n", n_vfid);
+   dev_err(dev, "Failed to create FID=%d\n", fid);
return ERR_PTR(err);
}
 
-   vfid = kzalloc(sizeof(*vfid), GFP_KERNEL);
-   if (!vfid)
+   f = kzalloc(sizeof(*f), GFP_KERNEL);
+   if (!f)
goto err_allocate_vfid;
 
-   vfid->vfid = n_vfid;
-   vfid->vid = vid;
+   f->vfid = vfid;
+   f->vid = vid;
 
-   list_add(>list, _sp->port_vfids.list);
-   set_bit(n_vfid, mlxsw_sp->port_vfids.mapped);
+   list_add(>list, _sp->port_vfids.list);
+   set_bit(vfid, mlxsw_sp->port_vfids.mapped);
 
-   return vfid;
+   return f;
 
 err_allocate_vfid:
-   __mlxsw_sp_vfid_destroy(mlxsw_sp, n_vfid);
+   mlxsw_sp_vfid_op(mlxsw_sp, fid, false);
return ERR_PTR(-ENOMEM);
 }
 
 static void mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp,
  struct mlxsw_sp_vfid *vfid)
 {
+   u16 fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
+
clear_bit(vfid->vfid, mlxsw_sp->port_vfids.mapped);
list_del(>list);
 
-   __mlxsw_sp_vfid_destroy(mlxsw_sp, vfid->vfid);
+   mlxsw_sp_vfid_op(mlxsw_sp, fid, false);
 
kfree(vfid);
 }
@@ -3164,36 +3157,37 @@ static struct mlxsw_sp_vfid 
*mlxsw_sp_br_vfid_create(struct mlxsw_sp *mlxsw_sp,
 struct net_device *br_dev)
 {
struct device *dev = mlxsw_sp->bus_info->dev;
-   struct mlxsw_sp_vfid *vfid;
-   u16 n_vfid;
+   struct mlxsw_sp_vfid *f;
+   u16 vfid, fid;
int err;
 
-   n_vfid = mlxsw_sp_br_vfid_to_vfid(mlxsw_sp_avail_br_vfid_get(mlxsw_sp));
-   if (n_vfid == MLXSW_SP_VFID_MAX) {
+   vfid = mlxsw_sp_br_vfid_to_vfid(mlxsw_sp_avail_br_vfid_get(mlxsw_sp));
+   if (vfid == MLXSW_SP_VFID_MAX) {
dev_err(dev, "No available vFIDs\n");
return ERR_PTR(-ERANGE);
}
 
-   err = __mlxsw_sp_vfid_create(mlxsw_sp, n_vfid);
+   fid = mlxsw_sp_vfid_to_fid(vfid);
+   err = mlxsw_sp_vfid_op(mlxsw_sp, fid, true);
if (err) {
-   dev_err(dev, "Failed to create vFID=%d\n", n_vfid);
+   dev_err(dev, "Failed to create FID=%d\n", fid);
return ERR_PTR(err);
}
 
-   vfid = kzalloc(sizeof(*vfid), GFP_KERNEL);
-   if (!vfid)
+   f 

Re: [net-next PATCH v3 00/17] Future-proof tunnel offload handlers

2016-06-20 Thread Hannes Frederic Sowa
On 20.06.2016 12:27, Tom Herbert wrote:
>> Do we?
>>
>> We look up the socket in a proper way, inclusive the namespace belonging
>> to the device we received the packet on. That said, I don't see a
>> problem with that right now. But maybe I miss something?
>>
> When we so the socket lookup in udp_rcv this is done after IP layer
> and packet has been determined to be loacally addressed. The packet is
> for the host, and if a UDP socket is matched, even if just based on
> destination port, the socket is matched and received functions are
> called. There is no ambiguity.
> 
> When the lookup is performed in GRO this is before we processed IP and
> determined that the packet is local. So a packet with any address
> (local or not) will match a listener socket with the same UDP port.
> The GRO can be performed an packet is subsequently forwarded maybe
> having been modified. If this packet turns out to not be the protocol
> we thought it was (e.g. VXLAN) then we have now potentially silently
> corrupted someone else's packets. Grant it, there's probably a lot of
> things that are required to make corruption happen, but it does allow
> the possibly of systematic data corruption and we haven't discounted
> this to become a security vulnerability.

Agreed.

Maybe we must switch to always use connected sockets for unicast+UDP+GRO?

Bye,
Hannes




Re: [net-next PATCH v3 00/17] Future-proof tunnel offload handlers

2016-06-20 Thread Tom Herbert
On Mon, Jun 20, 2016 at 2:36 PM, Hannes Frederic Sowa
 wrote:
> On 20.06.2016 12:27, Tom Herbert wrote:
>>> Do we?
>>>
>>> We look up the socket in a proper way, inclusive the namespace belonging
>>> to the device we received the packet on. That said, I don't see a
>>> problem with that right now. But maybe I miss something?
>>>
>> When we so the socket lookup in udp_rcv this is done after IP layer
>> and packet has been determined to be loacally addressed. The packet is
>> for the host, and if a UDP socket is matched, even if just based on
>> destination port, the socket is matched and received functions are
>> called. There is no ambiguity.
>>
>> When the lookup is performed in GRO this is before we processed IP and
>> determined that the packet is local. So a packet with any address
>> (local or not) will match a listener socket with the same UDP port.
>> The GRO can be performed an packet is subsequently forwarded maybe
>> having been modified. If this packet turns out to not be the protocol
>> we thought it was (e.g. VXLAN) then we have now potentially silently
>> corrupted someone else's packets. Grant it, there's probably a lot of
>> things that are required to make corruption happen, but it does allow
>> the possibly of systematic data corruption and we haven't discounted
>> this to become a security vulnerability.
>
> Agreed.
>
> Maybe we must switch to always use connected sockets for unicast+UDP+GRO?
>
No, I don't think we need to go that far. We should be able to enable
GRO on pretty much any sort of UDP socket--the other reason to move
GRO into udp_rcv is this will be a more suitable environment for user
programmable GRO which seems to be on the horizon now.

Tom

> Bye,
> Hannes
>
>


[Patch net 2/2] act_ife: acquire ife_mod_lock before reading ifeoplist

2016-06-20 Thread Cong Wang
Cc: Jamal Hadi Salim 
Signed-off-by: Cong Wang 
---
 net/sched/act_ife.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index e407659..ea4a2fe 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -277,7 +277,7 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, 
u32 metaid,
  * under ife->tcf_lock for existing action
 */
 static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
-   int len, bool exists)
+   int len, bool atomic)
 {
struct tcf_meta_info *mi = NULL;
struct tcf_meta_ops *ops = find_ife_oplist(metaid);
@@ -286,7 +286,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 
metaid, void *metaval,
if (!ops)
return -ENOENT;
 
-   mi = kzalloc(sizeof(*mi), exists ? GFP_ATOMIC : GFP_KERNEL);
+   mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL);
if (!mi) {
/*put back what find_ife_oplist took */
module_put(ops->owner);
@@ -296,7 +296,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 
metaid, void *metaval,
mi->metaid = metaid;
mi->ops = ops;
if (len > 0) {
-   ret = ops->alloc(mi, metaval, exists ? GFP_ATOMIC : GFP_KERNEL);
+   ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL);
if (ret != 0) {
kfree(mi);
module_put(ops->owner);
@@ -309,17 +309,19 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 
metaid, void *metaval,
return ret;
 }
 
-static int use_all_metadata(struct tcf_ife_info *ife, bool exists)
+static int use_all_metadata(struct tcf_ife_info *ife)
 {
struct tcf_meta_ops *o;
int rc = 0;
int installed = 0;
 
+   read_lock(_mod_lock);
list_for_each_entry(o, , list) {
-   rc = add_metainfo(ife, o->metaid, NULL, 0, exists);
+   rc = add_metainfo(ife, o->metaid, NULL, 0, true);
if (rc == 0)
installed += 1;
}
+   read_unlock(_mod_lock);
 
if (installed)
return 0;
@@ -523,7 +525,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
 * as we can. You better have at least one else we are
 * going to bail out
 */
-   err = use_all_metadata(ife, exists);
+   err = use_all_metadata(ife);
if (err) {
if (ret == ACT_P_CREATED)
_tcf_ife_cleanup(a, bind);
-- 
2.1.0



[PATCH net-next] tcp: reduce cpu usage when SO_SNDBUF is set

2016-06-20 Thread Jason Baron
From: Jason Baron 

When SO_SNDBUF is set and we are under tcp memory pressure, the effective
write buffer space can be much lower than what was set using SO_SNDBUF. For
example, we may have set the buffer to 100kb, but we may only be able to
write 10kb. In this scenario poll()/select()/epoll(), are going to
continuously return POLLOUT, followed by -EAGAIN from write(), and thus
result in a tight loop. Note that epoll in edge-triggered does not have
this issue since it only triggers once data has been ack'd. There is no
issue here when SO_SNDBUF is not set, since the tcp layer will auto tune
the sk->sndbuf.

Introduce a new socket flag, SOCK_SHORT_WRITE, such that we can mark the
socket when we have a short write due to memory pressure. By then testing
for SOCK_SHORT_WRITE in tcp_poll(), we hold off the POLLOUT until a
non-zero amount of data has been ack'd. In a previous approach:
http://marc.info/?l=linux-netdev=143930393211782=2, I had introduced a
new field in 'struct sock' to solve this issue, but its undesirable to add
bloat to 'struct sock'. We also could address this issue, by waiting for
the buffer to become completely empty, but that may reduce throughput since
the write buffer would be empty while waiting for subsequent writes. This
change brings us in line with the current epoll edge-trigger behavior for
the poll()/select() and epoll level-trigger.

We guarantee that SOCK_SHORT_WRITE will eventually clear, since when we set
SOCK_SHORT_WRITE, we make sure that sk_wmem_queued is non-zero and
SOCK_NOSPACE is set as well (in sk_stream_wait_memory()).

I tested this patch using 10,000 sockets, and setting SO_SNDBUF on the
server side, to induce tcp memory pressure. A single server thread reduced
its cpu usage from 100% to 19%, while maintaining the same level of
throughput.

Signed-off-by: Jason Baron 
---
 include/net/sock.h |  6 ++
 net/core/stream.c  |  1 +
 net/ipv4/tcp.c | 26 +++---
 3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 649d2a8c17fc..616e8e1a5d5d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -741,6 +741,7 @@ enum sock_flags {
SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */
SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
+   SOCK_SHORT_WRITE, /* Couldn't fill sndbuf due to memory pressure */
 };
 
 #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << 
SOCK_TIMESTAMPING_RX_SOFTWARE))
@@ -1114,6 +1115,11 @@ static inline bool sk_stream_is_writeable(const struct 
sock *sk)
   sk_stream_memory_free(sk);
 }
 
+static inline void sk_set_short_write(struct sock *sk)
+{
+   if (sk->sk_wmem_queued > 0 && sk_stream_is_writeable(sk))
+   sock_set_flag(sk, SOCK_SHORT_WRITE);
+}
 
 static inline bool sk_has_memory_pressure(const struct sock *sk)
 {
diff --git a/net/core/stream.c b/net/core/stream.c
index 159516a11b7e..ead768b1e95d 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -32,6 +32,7 @@ void sk_stream_write_space(struct sock *sk)
 
if (sk_stream_is_writeable(sk) && sock) {
clear_bit(SOCK_NOSPACE, >flags);
+   sock_reset_flag(sk, SOCK_SHORT_WRITE);
 
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 5c7ed147449c..254c7bb6d3d5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -517,7 +517,8 @@ unsigned int tcp_poll(struct file *file, struct socket 
*sock, poll_table *wait)
mask |= POLLIN | POLLRDNORM;
 
if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
-   if (sk_stream_is_writeable(sk)) {
+   if (!sock_flag(sk, SOCK_SHORT_WRITE) &&
+   sk_stream_is_writeable(sk)) {
mask |= POLLOUT | POLLWRNORM;
} else {  /* send SIGIO later */
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
@@ -529,7 +530,8 @@ unsigned int tcp_poll(struct file *file, struct socket 
*sock, poll_table *wait)
 * pairs with the input side.
 */
smp_mb__after_atomic();
-   if (sk_stream_is_writeable(sk))
+   if (!sock_flag(sk, SOCK_SHORT_WRITE) &&
+   sk_stream_is_writeable(sk))
mask |= POLLOUT | POLLWRNORM;
}
} else
@@ -917,8 +919,10 @@ new_segment:
 
skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation,
  
skb_queue_empty(>sk_write_queue));
-   if (!skb)
+   if (!skb) {
+ 

[patch net-next 05/23] mlxsw: spectrum: Use WARN_ON() return value

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Instead of checking for a condition and then issue the warning, just do
it in one go and simplify the code.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 16 
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index e55c685..f297b10 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2980,10 +2980,8 @@ static int mlxsw_sp_port_vlan_link(struct mlxsw_sp_port 
*mlxsw_sp_port,
u16 vid = vlan_dev_vlan_id(vlan_dev);
 
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
-   if (!mlxsw_sp_vport) {
-   WARN_ON(!mlxsw_sp_vport);
+   if (WARN_ON(!mlxsw_sp_vport))
return -EINVAL;
-   }
 
mlxsw_sp_vport->dev = vlan_dev;
 
@@ -2997,10 +2995,8 @@ static int mlxsw_sp_port_vlan_unlink(struct 
mlxsw_sp_port *mlxsw_sp_port,
u16 vid = vlan_dev_vlan_id(vlan_dev);
 
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
-   if (!mlxsw_sp_vport) {
-   WARN_ON(!mlxsw_sp_vport);
+   if (WARN_ON(!mlxsw_sp_vport))
return -EINVAL;
-   }
 
/* When removing a VLAN device while still bridged we should first
 * remove it from the bridge, as we receive the bridge's notification
@@ -3236,10 +3232,8 @@ static int mlxsw_sp_vport_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_vport,
int err;
 
vfid = mlxsw_sp_br_vfid_find(mlxsw_sp, br_dev);
-   if (!vfid) {
-   WARN_ON(!vfid);
+   if (WARN_ON(!vfid))
return -EINVAL;
-   }
 
/* We need a vFID to go back to after leaving the bridge's vFID. */
new_vfid = mlxsw_sp_vfid_find(mlxsw_sp, vid);
@@ -3454,10 +3448,8 @@ static int mlxsw_sp_netdevice_vport_event(struct 
net_device *dev,
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
if (info->linking) {
-   if (!mlxsw_sp_vport) {
-   WARN_ON(!mlxsw_sp_vport);
+   if (WARN_ON(!mlxsw_sp_vport))
return -EINVAL;
-   }
err = mlxsw_sp_vport_bridge_join(mlxsw_sp_vport,
 upper_dev);
} else {
-- 
2.5.5



[patch net-next 22/23] mlxsw: spectrum: Free resources upon vPort destruction

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

There are situations in which a vPort is destroyed while still holding
references to device's resources such as FIDs and FDB records. This can
happen, for example, when a VLAN device is deleted while still being
bridged.

Instead of trying to make sure vPort destruction is invoked when it no
longer uses device's resources, just free them upon destruction. This
simplifies the code, as we no longer need to take different situations
into account when events are received - cleanup is taken care of in one
place.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 49 --
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  1 +
 2 files changed, 15 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 2b1748d..9f48ec5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -660,6 +660,8 @@ static int mlxsw_sp_vfid_op(struct mlxsw_sp *mlxsw_sp, u16 
fid, bool create)
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
 }
 
+static void mlxsw_sp_vport_vfid_leave(struct mlxsw_sp_port *mlxsw_sp_vport);
+
 static struct mlxsw_sp_fid *mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp,
 u16 vid)
 {
@@ -685,6 +687,7 @@ static struct mlxsw_sp_fid *mlxsw_sp_vfid_create(struct 
mlxsw_sp *mlxsw_sp,
if (!f)
goto err_allocate_vfid;
 
+   f->leave = mlxsw_sp_vport_vfid_leave;
f->fid = fid;
f->vid = vid;
 
@@ -887,6 +890,7 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
 {
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp_port *mlxsw_sp_vport;
+   struct mlxsw_sp_fid *f;
int err;
 
/* VLAN 0 is removed from HW filter when device goes down, but
@@ -921,7 +925,12 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
return err;
}
 
-   mlxsw_sp_vport_vfid_leave(mlxsw_sp_vport);
+   /* Drop FID reference. If this was the last reference the
+* resources will be freed.
+*/
+   f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
+   if (f && !WARN_ON(!f->leave))
+   f->leave(mlxsw_sp_vport);
 
/* When removing the last VLAN interface on a bridged port we need to
 * transition all active 802.1Q bridge VLANs to use VID to FID
@@ -2836,15 +2845,12 @@ err_col_port_add:
return err;
 }
 
-static void mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport);
-
 static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *lag_dev)
 {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-   struct mlxsw_sp_port *mlxsw_sp_vport;
-   struct mlxsw_sp_upper *lag;
u16 lag_id = mlxsw_sp_port->lag_id;
+   struct mlxsw_sp_upper *lag;
 
if (!mlxsw_sp_port->lagged)
return;
@@ -2854,21 +2860,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port 
*mlxsw_sp_port,
mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id);
mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 
-   /* In case we leave a LAG device that has bridges built on top,
-* then their teardown sequence is never issued and we need to
-* invoke the necessary cleanup routines ourselves.
-*/
-   list_for_each_entry(mlxsw_sp_vport, _sp_port->vports_list,
-   vport.list) {
-   struct net_device *br_dev;
-
-   if (!mlxsw_sp_vport->bridged)
-   continue;
-
-   br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
-   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport);
-   }
-
if (mlxsw_sp_port->bridged) {
mlxsw_sp_port_active_vlans_del(mlxsw_sp_port);
mlxsw_sp_port_bridge_leave(mlxsw_sp_port);
@@ -2947,17 +2938,6 @@ static void mlxsw_sp_port_vlan_unlink(struct 
mlxsw_sp_port *mlxsw_sp_port,
if (WARN_ON(!mlxsw_sp_vport))
return;
 
-   /* When removing a VLAN device while still bridged we should first
-* remove it from the bridge, as we receive the bridge's notification
-* when the vPort is already gone.
-*/
-   if (mlxsw_sp_vport->bridged) {
-   struct net_device *br_dev;
-
-   br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
-   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport);
-   }
-
mlxsw_sp_vport->dev = mlxsw_sp_port->dev;
 }
 
@@ -3115,6 +3095,8 @@ static u16 mlxsw_sp_avail_br_vfid_get(const struct 
mlxsw_sp *mlxsw_sp)
   MLXSW_SP_VFID_BR_MAX);
 }
 
+static void mlxsw_sp_vport_br_vfid_leave(struct 

[patch net-next 21/23] mlxsw: spectrum: Refactor FDB flushing logic

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

FDB entries are learned using {Port / LAG ID, FID} and therefore should
be flushed whenever a port (vPort) leaves its FID (vFID).

However, when the bridge port is a LAG device (or a VLAN device on top),
then FDB flushing is conditional. Ports removed from such LAG
configurations must not trigger flushing, as other ports might still be
members in the LAG and therefore the bridge port is still active.

The decision whether to flush or not was previously computed in the
netdevice notification block, but in order to flush the entries when a
port leaves its FID this decision should be computed there.

Strip the notification block from this logic and instead move it to one
FDB flushing function that is invoked from both the FID / vFID leave
functions.

When port isn't member in LAG, FDB flushing should always occur.
Otherwise, it should occur only when the last port (vPort) member in the
LAG leaves the FID (vFID).

This will allow us - in the next patch - to simplify the cleanup code
paths that are hit whenever the topology above the port netdevs changes.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 133 +++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |   1 +
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |   2 +
 3 files changed, 47 insertions(+), 89 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 0c42515..2b1748d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2535,16 +2535,37 @@ static struct mlxsw_driver mlxsw_sp_driver = {
.profile= _sp_config_profile,
 };
 
-static int
-mlxsw_sp_port_fdb_flush_by_port(const struct mlxsw_sp_port *mlxsw_sp_port)
+static bool mlxsw_sp_lag_port_fid_member(struct mlxsw_sp_port *lag_port,
+u16 fid)
+{
+   if (mlxsw_sp_fid_is_vfid(fid))
+   return mlxsw_sp_port_vport_find_by_fid(lag_port, fid);
+   else
+   return test_bit(fid, lag_port->active_vlans);
+}
+
+static bool mlxsw_sp_port_fdb_should_flush(struct mlxsw_sp_port *mlxsw_sp_port,
+  u16 fid)
 {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-   char sfdf_pl[MLXSW_REG_SFDF_LEN];
+   u8 local_port = mlxsw_sp_port->local_port;
+   u16 lag_id = mlxsw_sp_port->lag_id;
+   int i, count = 0;
 
-   mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_PORT);
-   mlxsw_reg_sfdf_system_port_set(sfdf_pl, mlxsw_sp_port->local_port);
+   if (!mlxsw_sp_port->lagged)
+   return true;
 
-   return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
+   for (i = 0; i < MLXSW_SP_PORT_PER_LAG_MAX; i++) {
+   struct mlxsw_sp_port *lag_port;
+
+   lag_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
+   if (!lag_port || lag_port->local_port == local_port)
+   continue;
+   if (mlxsw_sp_lag_port_fid_member(lag_port, fid))
+   count++;
+   }
+
+   return !count;
 }
 
 static int
@@ -2563,18 +2584,6 @@ mlxsw_sp_port_fdb_flush_by_port_fid(const struct 
mlxsw_sp_port *mlxsw_sp_port,
 }
 
 static int
-mlxsw_sp_port_fdb_flush_by_lag_id(const struct mlxsw_sp_port *mlxsw_sp_port)
-{
-   struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-   char sfdf_pl[MLXSW_REG_SFDF_LEN];
-
-   mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_LAG);
-   mlxsw_reg_sfdf_lag_id_set(sfdf_pl, mlxsw_sp_port->lag_id);
-
-   return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
-}
-
-static int
 mlxsw_sp_port_fdb_flush_by_lag_id_fid(const struct mlxsw_sp_port 
*mlxsw_sp_port,
  u16 fid)
 {
@@ -2588,59 +2597,16 @@ mlxsw_sp_port_fdb_flush_by_lag_id_fid(const struct 
mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
 }
 
-static int
-__mlxsw_sp_port_fdb_flush(const struct mlxsw_sp_port *mlxsw_sp_port)
-{
-   int err, last_err = 0;
-   u16 vid;
-
-   for (vid = 1; vid < VLAN_N_VID - 1; vid++) {
-   err = mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_port, vid);
-   if (err)
-   last_err = err;
-   }
-
-   return last_err;
-}
-
-static int
-__mlxsw_sp_port_fdb_flush_lagged(const struct mlxsw_sp_port *mlxsw_sp_port)
+int mlxsw_sp_port_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
 {
-   int err, last_err = 0;
-   u16 vid;
-
-   for (vid = 1; vid < VLAN_N_VID - 1; vid++) {
-   err = mlxsw_sp_port_fdb_flush_by_lag_id_fid(mlxsw_sp_port, vid);
-   if (err)
-   last_err = err;
-   }
-
-   

[patch net-next 19/23] mlxsw: spectrum: Add FID get / set functions

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

As previously explained, not all vPorts will be assigned FIDs, so instead
of returning the FID index of a vPort, return a pointer to its FID
struct. This will allow us to know whether it's legal to access the
vPort's FID parameters such as index and device.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 17 ++---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 28 +++---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  8 +++
 3 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 08f3f51..ea007f0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -776,7 +776,7 @@ static int mlxsw_sp_vport_vfid_join(struct mlxsw_sp_port 
*mlxsw_sp_vport)
if (err)
goto err_vport_fid_map;
 
-   mlxsw_sp_vport->vport.f = f;
+   mlxsw_sp_vport_fid_set(mlxsw_sp_vport, f);
f->ref_count++;
 
return 0;
@@ -792,9 +792,9 @@ err_vport_flood_set:
 
 static void mlxsw_sp_vport_vfid_leave(struct mlxsw_sp_port *mlxsw_sp_vport)
 {
-   struct mlxsw_sp_fid *f = mlxsw_sp_vport->vport.f;
+   struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
 
-   mlxsw_sp_vport->vport.f = NULL;
+   mlxsw_sp_vport_fid_set(mlxsw_sp_vport, NULL);
 
mlxsw_sp_vport_fid_map(mlxsw_sp_vport, f->fid, false);
 
@@ -2639,7 +2639,8 @@ static int mlxsw_sp_vport_fdb_flush(struct mlxsw_sp_port 
*mlxsw_sp_vport,
return mlxsw_sp_port_fdb_flush_by_lag_id_fid(mlxsw_sp_vport,
 fid);
else
-   return mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_vport, fid);
+   return mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_vport,
+  fid);
 }
 
 static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
@@ -3229,7 +3230,7 @@ static int mlxsw_sp_vport_br_vfid_join(struct 
mlxsw_sp_port *mlxsw_sp_vport,
if (err)
goto err_vport_fid_map;
 
-   mlxsw_sp_vport->vport.f = f;
+   mlxsw_sp_vport_fid_set(mlxsw_sp_vport, f);
f->ref_count++;
 
return 0;
@@ -3244,13 +3245,13 @@ err_vport_flood_set:
 
 static void mlxsw_sp_vport_br_vfid_leave(struct mlxsw_sp_port *mlxsw_sp_vport)
 {
-   struct mlxsw_sp_fid *f = mlxsw_sp_vport->vport.f;
+   struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
 
mlxsw_sp_vport_fid_map(mlxsw_sp_vport, f->fid, false);
 
mlxsw_sp_vport_flood_set(mlxsw_sp_vport, f->fid, false);
 
-   mlxsw_sp_vport->vport.f = NULL;
+   mlxsw_sp_vport_fid_set(mlxsw_sp_vport, NULL);
if (--f->ref_count == 0)
mlxsw_sp_br_vfid_destroy(mlxsw_sp_vport->mlxsw_sp, f);
 }
@@ -3293,8 +3294,8 @@ err_vport_br_vfid_join:
 static void mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
bool flush_fdb)
 {
+   u16 fid = mlxsw_sp_vport_fid_get(mlxsw_sp_vport)->fid;
u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
-   u16 fid = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
 
mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 1d34419..a6dd295 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -259,12 +259,6 @@ mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 
lag_id, u8 port_index)
return mlxsw_sp_port && mlxsw_sp_port->lagged ? mlxsw_sp_port : NULL;
 }
 
-static inline struct net_device *
-mlxsw_sp_vport_br_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
-{
-   return mlxsw_sp_vport->vport.f->dev;
-}
-
 static inline u16
 mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
 {
@@ -279,10 +273,24 @@ mlxsw_sp_port_is_vport(const struct mlxsw_sp_port 
*mlxsw_sp_port)
return vid != 0;
 }
 
-static inline u16
+static inline void mlxsw_sp_vport_fid_set(struct mlxsw_sp_port *mlxsw_sp_vport,
+ struct mlxsw_sp_fid *f)
+{
+   mlxsw_sp_vport->vport.f = f;
+}
+
+static inline struct mlxsw_sp_fid *
 mlxsw_sp_vport_fid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
 {
-   return mlxsw_sp_vport->vport.f->fid;
+   return mlxsw_sp_vport->vport.f;
+}
+
+static inline struct net_device *
+mlxsw_sp_vport_br_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
+{
+   struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
+
+   return f->dev;
 }
 
 static inline struct mlxsw_sp_port *
@@ -307,7 +315,9 @@ mlxsw_sp_port_vport_find_by_fid(const 

[patch net-next 10/23] mlxsw: spectrum: Remove redundant function argument

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

In all call sites 'only_uc' is set to false, so strip it.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c   | 12 +---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h   |  2 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  4 ++--
 3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index b999802..90cf6c5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -791,7 +791,7 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
 
if (!vfid->nr_vports) {
err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid,
-  true, false);
+  true);
if (err) {
netdev_err(dev, "Failed to setup flooding for 
vFID=%d\n",
   vfid->vfid);
@@ -859,8 +859,7 @@ err_port_vid_to_fid_set:
mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
 err_port_vp_mode_trans:
if (!vfid->nr_vports)
-   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false,
-false);
+   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false);
 err_vport_flood_set:
mlxsw_sp_port_vport_destroy(mlxsw_sp_vport);
 err_port_vport_create:
@@ -3267,8 +3266,7 @@ static void mlxsw_sp_vport_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_vport,
goto err_port_vid_learning_set;
}
 
-   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false,
-  false);
+   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false);
if (err) {
netdev_err(dev, "Failed clear to clear flooding\n");
goto err_vport_flood_set;
@@ -3327,7 +3325,7 @@ static int mlxsw_sp_vport_bridge_join(struct 
mlxsw_sp_port *mlxsw_sp_vport,
}
}
 
-   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, true, false);
+   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, true);
if (err) {
netdev_err(dev, "Failed to setup flooding for vFID=%d\n",
   vfid->vfid);
@@ -3386,7 +3384,7 @@ err_port_vid_to_fid_validate:
 err_port_vid_to_fid_invalidate:
mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
 err_port_vid_learning_set:
-   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false, false);
+   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false);
 err_port_flood_set:
if (!vfid->nr_vports)
mlxsw_sp_br_vfid_destroy(mlxsw_sp, vfid);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 5da98b4..58a2a5d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -367,7 +367,7 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
 int mlxsw_sp_port_kill_vid(struct net_device *dev,
   __be16 __always_unused proto, u16 vid);
 int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
-bool set, bool only_uc);
+bool set);
 void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
 int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
 int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 3710f19..02c126c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -261,13 +261,13 @@ err_port_flood_set:
 }
 
 int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
-bool set, bool only_uc)
+bool set)
 {
/* In case of vFIDs, index into the flooding table is relative to
 * the start of the vFIDs range.
 */
return __mlxsw_sp_port_flood_set(mlxsw_sp_vport, vfid, vfid, set,
-only_uc);
+false);
 }
 
 static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
-- 
2.5.5



[patch net-next 20/23] mlxsw: spectrum: Don't count on FID being present

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Not all vPorts will have FIDs assigned to them, so make sure functions
first test for FID presence.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c   |  4 +++-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h   |  4 ++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 11 ++-
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index ea007f0..0c42515 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3323,7 +3323,9 @@ mlxsw_sp_port_master_bridge_check(const struct 
mlxsw_sp_port *mlxsw_sp_port,
 
list_for_each_entry(mlxsw_sp_vport, _sp_port->vports_list,
vport.list) {
-   if (mlxsw_sp_vport_br_get(mlxsw_sp_vport) == br_dev)
+   struct net_device *dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
+
+   if (dev && dev == br_dev)
return false;
}
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index a6dd295..f419535 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -290,7 +290,7 @@ mlxsw_sp_vport_br_get(const struct mlxsw_sp_port 
*mlxsw_sp_vport)
 {
struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
 
-   return f->dev;
+   return f ? f->dev : NULL;
 }
 
 static inline struct mlxsw_sp_port *
@@ -317,7 +317,7 @@ mlxsw_sp_port_vport_find_by_fid(const struct mlxsw_sp_port 
*mlxsw_sp_port,
vport.list) {
struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
 
-   if (f->fid == fid)
+   if (f && f->fid == fid)
return mlxsw_sp_vport;
}
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index b31b2ce..fc34c46 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -55,10 +55,10 @@
 static u16 mlxsw_sp_port_vid_to_fid_get(struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid)
 {
+   struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_port);
u16 fid = vid;
 
-   if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
-   fid = mlxsw_sp_vport_fid_get(mlxsw_sp_port)->fid;
+   fid = f ? f->fid : fid;
 
if (!fid)
fid = mlxsw_sp_port->pvid;
@@ -1196,7 +1196,8 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port 
*mlxsw_sp_port,
 {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_port *tmp;
-   u16 vport_fid = 0;
+   struct mlxsw_sp_fid *f;
+   u16 vport_fid;
char *sfd_pl;
char mac[ETH_ALEN];
u16 fid;
@@ -1211,8 +1212,8 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port 
*mlxsw_sp_port,
if (!sfd_pl)
return -ENOMEM;
 
-   if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
-   vport_fid = mlxsw_sp_vport_fid_get(mlxsw_sp_port)->fid;
+   f = mlxsw_sp_vport_fid_get(mlxsw_sp_port);
+   vport_fid = f ? f->fid : 0;
 
mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
do {
-- 
2.5.5



[patch net-next 16/23] mlxsw: spectrum: Remove unused function argument

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index ad8e447..4869392 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2872,7 +2872,6 @@ err_col_port_add:
 }
 
 static void mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
-   struct net_device *br_dev,
bool flush_fdb);
 
 static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -2903,7 +2902,7 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port 
*mlxsw_sp_port,
continue;
 
br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
-   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev, false);
+   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, false);
}
 
if (mlxsw_sp_port->bridged) {
@@ -2995,7 +2994,7 @@ static void mlxsw_sp_port_vlan_unlink(struct 
mlxsw_sp_port *mlxsw_sp_port,
struct net_device *br_dev;
 
br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
-   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev, true);
+   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, true);
}
 
mlxsw_sp_vport->dev = mlxsw_sp_port->dev;
@@ -3290,7 +3289,6 @@ err_vport_br_vfid_join:
 }
 
 static void mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
-   struct net_device *br_dev,
bool flush_fdb)
 {
u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
@@ -3369,8 +3367,7 @@ static int mlxsw_sp_netdevice_vport_event(struct 
net_device *dev,
 */
if (!mlxsw_sp_vport)
return 0;
-   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, upper_dev,
-   true);
+   mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, true);
}
}
 
-- 
2.5.5



[patch net-next 07/23] mlxsw: spectrum: Remove unnecessary function argument

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

The argument 'br_dev' is never used, so remove it.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3500a72..cd85316 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2708,8 +2708,7 @@ static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp 
*mlxsw_sp,
mlxsw_sp->master_bridge.ref_count++;
 }
 
-static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp,
-  struct net_device *br_dev)
+static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
 {
if (--mlxsw_sp->master_bridge.ref_count == 0)
mlxsw_sp->master_bridge.dev = NULL;
@@ -2911,7 +2910,7 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port 
*mlxsw_sp_port,
if (mlxsw_sp_port->bridged) {
mlxsw_sp_port_active_vlans_del(mlxsw_sp_port);
mlxsw_sp_port_bridge_leave(mlxsw_sp_port, false);
-   mlxsw_sp_master_bridge_dec(mlxsw_sp, NULL);
+   mlxsw_sp_master_bridge_dec(mlxsw_sp);
}
 
if (lag->ref_count == 1) {
@@ -3055,7 +3054,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev);
} else {
mlxsw_sp_port_bridge_leave(mlxsw_sp_port, true);
-   mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev);
+   mlxsw_sp_master_bridge_dec(mlxsw_sp);
}
} else if (netif_is_lag_master(upper_dev)) {
if (info->linking)
-- 
2.5.5



[patch net-next 09/23] mlxsw: spectrum: Use DECLARE_BITMAP() macro

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

There is a macro to do this kind of declarations, so use it.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 13b30ea..5da98b4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -155,17 +155,17 @@ struct mlxsw_sp_sb {
 struct mlxsw_sp {
struct {
struct list_head list;
-   unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_PORT_MAX)];
+   DECLARE_BITMAP(mapped, MLXSW_SP_VFID_PORT_MAX);
} port_vfids;
struct {
struct list_head list;
-   unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_BR_MAX)];
+   DECLARE_BITMAP(mapped, MLXSW_SP_VFID_BR_MAX);
} br_vfids;
struct {
struct list_head list;
-   unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_MID_MAX)];
+   DECLARE_BITMAP(mapped, MLXSW_SP_MID_MAX);
} br_mids;
-   unsigned long active_fids[BITS_TO_LONGS(VLAN_N_VID)];
+   DECLARE_BITMAP(active_fids, VLAN_N_VID);
struct mlxsw_sp_port **ports;
struct mlxsw_core *core;
const struct mlxsw_bus_info *bus_info;
-- 
2.5.5



[patch net-next 12/23] mlxsw: spectrum: Create a function to map vPort's FID

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

A FID used by a vPort (vFID, but also rFID later in the series) is
always mapped using {Port, VID} and not only VID as with the 4K FIDs of
the VLAN-aware bridge.

Instead of specifying all the arguments each time, just wrap this
operation using a dedicated function and simplify the code.

As before, the function takes FID as its argument in preparation for a
generic FID struct.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 84 --
 1 file changed, 38 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 4f53dd2..6df944b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -745,6 +745,16 @@ static void mlxsw_sp_port_vport_destroy(struct 
mlxsw_sp_port *mlxsw_sp_vport)
kfree(mlxsw_sp_vport);
 }
 
+static int mlxsw_sp_vport_fid_map(struct mlxsw_sp_port *mlxsw_sp_vport, u16 
fid,
+ bool valid)
+{
+   enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
+   u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
+
+   return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_vport, mt, valid, fid,
+   vid);
+}
+
 int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
  u16 vid)
 {
@@ -752,6 +762,7 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_port *mlxsw_sp_vport;
struct mlxsw_sp_vfid *vfid;
+   u16 fid;
int err;
 
/* VLAN 0 is added to HW filter when device goes up, but it is
@@ -804,15 +815,12 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
}
}
 
-   err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_vport,
-  MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
-  true,
-  mlxsw_sp_vfid_to_fid(vfid->vfid),
-  vid);
+   fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
+   err = mlxsw_sp_vport_fid_map(mlxsw_sp_vport, fid, true);
if (err) {
netdev_err(dev, "Failed to map {Port, VID=%d} to vFID=%d\n",
   vid, vfid->vfid);
-   goto err_port_vid_to_fid_set;
+   goto err_vport_fid_map;
}
 
err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
@@ -844,10 +852,8 @@ err_port_stp_state_set:
 err_port_add_vid:
mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
 err_port_vid_learning_set:
-   mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_vport,
-MLXSW_REG_SVFA_MT_PORT_VID_TO_FID, false,
-mlxsw_sp_vfid_to_fid(vfid->vfid), vid);
-err_port_vid_to_fid_set:
+   mlxsw_sp_vport_fid_map(mlxsw_sp_vport, fid, false);
+err_vport_fid_map:
if (list_is_singular(_sp_port->vports_list))
mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
 err_port_vp_mode_trans:
@@ -867,6 +873,7 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp_port *mlxsw_sp_vport;
struct mlxsw_sp_vfid *vfid;
+   u16 fid;
int err;
 
/* VLAN 0 is removed from HW filter when device goes down, but
@@ -903,11 +910,8 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
return err;
}
 
-   err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_vport,
-  MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
-  false,
-  mlxsw_sp_vfid_to_fid(vfid->vfid),
-  vid);
+   fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
+   err = mlxsw_sp_vport_fid_map(mlxsw_sp_vport, fid, false);
if (err) {
netdev_err(dev, "Failed to invalidate {Port, VID=%d} to vFID=%d 
mapping\n",
   vid, vfid->vfid);
@@ -3213,6 +3217,7 @@ static void mlxsw_sp_vport_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_vport,
u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
struct net_device *dev = mlxsw_sp_vport->dev;
struct mlxsw_sp_vfid *vfid, *new_vfid;
+   u16 fid, new_fid;
int err;
 
vfid = mlxsw_sp_br_vfid_find(mlxsw_sp, br_dev);
@@ -3233,26 +3238,20 @@ static void mlxsw_sp_vport_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_vport,
/* Invalidate existing {Port, VID} to vFID mapping and create a new
 * one for the new vFID.
 */
-  

[patch net-next 01/23] mlxsw: spectrum: Use notifier_from_errno() in notifier block

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Instead of checking the error value and returning NOTIFY_BAD, just use
notifier_from_errno() and simplify the code.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 92 --
 1 file changed, 29 insertions(+), 63 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 6f9e3dd..3d57008 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -49,6 +49,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3024,7 +3025,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
struct mlxsw_sp_port *mlxsw_sp_port;
struct net_device *upper_dev;
struct mlxsw_sp *mlxsw_sp;
-   int err;
+   int err = 0;
 
mlxsw_sp_port = netdev_priv(dev);
mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
@@ -3038,68 +3039,42 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
/* HW limitation forbids to put ports to multiple bridges. */
if (netif_is_bridge_master(upper_dev) &&
!mlxsw_sp_master_bridge_check(mlxsw_sp, upper_dev))
-   return NOTIFY_BAD;
+   return -EINVAL;
if (netif_is_lag_master(upper_dev) &&
!mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev,
   info->upper_info))
-   return NOTIFY_BAD;
+   return -EINVAL;
break;
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
if (is_vlan_dev(upper_dev)) {
-   if (info->linking) {
+   if (info->linking)
err = mlxsw_sp_port_vlan_link(mlxsw_sp_port,
  upper_dev);
-   if (err) {
-   netdev_err(dev, "Failed to link VLAN 
device\n");
-   return NOTIFY_BAD;
-   }
-   } else {
+   else
err = mlxsw_sp_port_vlan_unlink(mlxsw_sp_port,
upper_dev);
-   if (err) {
-   netdev_err(dev, "Failed to unlink VLAN 
device\n");
-   return NOTIFY_BAD;
-   }
-   }
} else if (netif_is_bridge_master(upper_dev)) {
if (info->linking) {
err = mlxsw_sp_port_bridge_join(mlxsw_sp_port);
-   if (err) {
-   netdev_err(dev, "Failed to join 
bridge\n");
-   return NOTIFY_BAD;
-   }
mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev);
} else {
err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
 true);
mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev);
-   if (err) {
-   netdev_err(dev, "Failed to leave 
bridge\n");
-   return NOTIFY_BAD;
-   }
}
} else if (netif_is_lag_master(upper_dev)) {
-   if (info->linking) {
+   if (info->linking)
err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
 upper_dev);
-   if (err) {
-   netdev_err(dev, "Failed to join link 
aggregation\n");
-   return NOTIFY_BAD;
-   }
-   } else {
+   else
err = mlxsw_sp_port_lag_leave(mlxsw_sp_port,
  upper_dev);
-   if (err) {
-   netdev_err(dev, "Failed to leave link 
aggregation\n");
-   return NOTIFY_BAD;
-   }
-   }
}
break;
}
 
-   return NOTIFY_DONE;
+   return err;
 }
 
 static int mlxsw_sp_netdevice_port_lower_event(struct net_device *dev,
@@ 

[patch net-next 02/23] mlxsw: spectrum: Sanitize port netdev upper devices

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

We currently only support the following upper devices for port netdevs:
1) Bridge
2) LAG (bond / team)
3) VLAN

Any other device is forbidden, so return an error.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3d57008..b47e3fb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3034,6 +3034,10 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
switch (event) {
case NETDEV_PRECHANGEUPPER:
upper_dev = info->upper_dev;
+   if (!is_vlan_dev(upper_dev) &&
+   !netif_is_lag_master(upper_dev) &&
+   !netif_is_bridge_master(upper_dev))
+   return -EINVAL;
if (!info->master || !info->linking)
break;
/* HW limitation forbids to put ports to multiple bridges. */
@@ -3070,6 +3074,9 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
else
err = mlxsw_sp_port_lag_leave(mlxsw_sp_port,
  upper_dev);
+   } else {
+   err = -EINVAL;
+   WARN_ON(1);
}
break;
}
-- 
2.5.5



[patch net-next 13/23] mlxsw: spectrum: Use FID instead of vFID to setup flooding

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Use a FID index instead of vFID and ease the transition towards a
generic FID struct.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c   | 15 +++
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h   |  2 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  5 -
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 6df944b..7a75a45 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -793,9 +793,9 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
goto err_port_vport_create;
}
 
+   fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
if (!vfid->nr_vports) {
-   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid,
-  true);
+   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, fid, true);
if (err) {
netdev_err(dev, "Failed to setup flooding for 
vFID=%d\n",
   vfid->vfid);
@@ -815,7 +815,6 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
}
}
 
-   fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
err = mlxsw_sp_vport_fid_map(mlxsw_sp_vport, fid, true);
if (err) {
netdev_err(dev, "Failed to map {Port, VID=%d} to vFID=%d\n",
@@ -858,7 +857,7 @@ err_vport_fid_map:
mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
 err_port_vp_mode_trans:
if (!vfid->nr_vports)
-   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false);
+   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, fid, false);
 err_vport_flood_set:
mlxsw_sp_port_vport_destroy(mlxsw_sp_vport);
 err_port_vport_create:
@@ -3260,7 +3259,7 @@ static void mlxsw_sp_vport_bridge_leave(struct 
mlxsw_sp_port *mlxsw_sp_vport,
goto err_port_vid_learning_set;
}
 
-   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false);
+   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, fid, false);
if (err) {
netdev_err(dev, "Failed clear to clear flooding\n");
goto err_vport_flood_set;
@@ -3320,7 +3319,8 @@ static int mlxsw_sp_vport_bridge_join(struct 
mlxsw_sp_port *mlxsw_sp_vport,
}
}
 
-   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, true);
+   fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
+   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, fid, true);
if (err) {
netdev_err(dev, "Failed to setup flooding for vFID=%d\n",
   vfid->vfid);
@@ -3344,7 +3344,6 @@ static int mlxsw_sp_vport_bridge_join(struct 
mlxsw_sp_port *mlxsw_sp_vport,
goto err_vport_fid_unmap;
}
 
-   fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
err = mlxsw_sp_vport_fid_map(mlxsw_sp_vport, fid, true);
if (err) {
netdev_err(dev, "Failed to map {Port, VID} to vFID=%d\n",
@@ -3371,7 +3370,7 @@ err_vport_fid_map:
 err_vport_fid_unmap:
mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
 err_port_vid_learning_set:
-   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, vfid->vfid, false);
+   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, fid, false);
 err_port_flood_set:
if (!vfid->nr_vports)
mlxsw_sp_br_vfid_destroy(mlxsw_sp, vfid);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 58a2a5d..0ae929e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -366,7 +366,7 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
  u16 vid);
 int mlxsw_sp_port_kill_vid(struct net_device *dev,
   __be16 __always_unused proto, u16 vid);
-int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
+int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
 bool set);
 void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
 int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 02c126c..76f53c2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -260,12 +260,15 @@ err_port_flood_set:
return err;
 }
 
-int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 

[patch net-next 23/23] mlxsw: spectrum: Add debug prints

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

For debug purposes, it's useful to know the order in which the driver
responds to changes in the topology of its upper devices.

Add debug prints to signal these events.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c   | 10 ++
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  4 
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 9f48ec5..d23948b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2589,6 +2589,9 @@ mlxsw_sp_port_fdb_flush_by_port_fid(const struct 
mlxsw_sp_port *mlxsw_sp_port,
mlxsw_reg_sfdf_port_fid_system_port_set(sfdf_pl,
mlxsw_sp_port->local_port);
 
+   netdev_dbg(mlxsw_sp_port->dev, "FDB flushed using Port=%d, FID=%d\n",
+  mlxsw_sp_port->local_port, fid);
+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
 }
 
@@ -2603,6 +2606,9 @@ mlxsw_sp_port_fdb_flush_by_lag_id_fid(const struct 
mlxsw_sp_port *mlxsw_sp_port,
mlxsw_reg_sfdf_fid_set(sfdf_pl, fid);
mlxsw_reg_sfdf_lag_fid_lag_id_set(sfdf_pl, mlxsw_sp_port->lag_id);
 
+   netdev_dbg(mlxsw_sp_port->dev, "FDB flushed using LAG ID=%d, FID=%d\n",
+  mlxsw_sp_port->lag_id, fid);
+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
 }
 
@@ -3174,6 +3180,8 @@ static int mlxsw_sp_vport_br_vfid_join(struct 
mlxsw_sp_port *mlxsw_sp_vport,
mlxsw_sp_vport_fid_set(mlxsw_sp_vport, f);
f->ref_count++;
 
+   netdev_dbg(mlxsw_sp_vport->dev, "Joined FID=%d\n", f->fid);
+
return 0;
 
 err_vport_fid_map:
@@ -3188,6 +3196,8 @@ static void mlxsw_sp_vport_br_vfid_leave(struct 
mlxsw_sp_port *mlxsw_sp_vport)
 {
struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
 
+   netdev_dbg(mlxsw_sp_vport->dev, "Left FID=%d\n", f->fid);
+
mlxsw_sp_vport_fid_map(mlxsw_sp_vport, f->fid, false);
 
mlxsw_sp_vport_flood_set(mlxsw_sp_vport, f->fid, false);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 7c2b0f8..a0c7376 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -488,6 +488,8 @@ static int __mlxsw_sp_port_fid_join(struct mlxsw_sp_port 
*mlxsw_sp_port,
 
f->ref_count++;
 
+   netdev_dbg(mlxsw_sp_port->dev, "Joined FID=%d\n", fid);
+
return 0;
 }
 
@@ -500,6 +502,8 @@ static void __mlxsw_sp_port_fid_leave(struct mlxsw_sp_port 
*mlxsw_sp_port,
if (WARN_ON(!f))
return;
 
+   netdev_dbg(mlxsw_sp_port->dev, "Left FID=%d\n", fid);
+
mlxsw_sp_port_fdb_flush(mlxsw_sp_port, fid);
 
if (--f->ref_count == 0)
-- 
2.5.5



[patch net-next 15/23] mlxsw: spectrum: Use join / leave functions for vFID operations

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

When a vPort is created or when it joins a bridge we always do the same
set of operations:

1) Create the vFID, if not already created
2) Setup flooding for the vFID
3) Map the {Port, VID} to the vFID

When a vPort is destroyed or when it leaves a bridge the reverse is
performed.

Encapsulate the above in join / leave functions and simplify the code.
FIDs and rFIDs will use a similar set of functions.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 304 ++---
 1 file changed, 126 insertions(+), 178 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 8ef8d0b..ad8e447 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -712,8 +712,7 @@ static void mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp,
 }
 
 static struct mlxsw_sp_port *
-mlxsw_sp_port_vport_create(struct mlxsw_sp_port *mlxsw_sp_port,
-  struct mlxsw_sp_fid *f)
+mlxsw_sp_port_vport_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
 {
struct mlxsw_sp_port *mlxsw_sp_vport;
 
@@ -731,8 +730,7 @@ mlxsw_sp_port_vport_create(struct mlxsw_sp_port 
*mlxsw_sp_port,
mlxsw_sp_vport->stp_state = BR_STATE_FORWARDING;
mlxsw_sp_vport->lagged = mlxsw_sp_port->lagged;
mlxsw_sp_vport->lag_id = mlxsw_sp_port->lag_id;
-   mlxsw_sp_vport->vport.f = f;
-   mlxsw_sp_vport->vport.vid = f->vid;
+   mlxsw_sp_vport->vport.vid = vid;
 
list_add(_sp_vport->vport.list, _sp_port->vports_list);
 
@@ -755,13 +753,62 @@ static int mlxsw_sp_vport_fid_map(struct mlxsw_sp_port 
*mlxsw_sp_vport, u16 fid,
vid);
 }
 
+static int mlxsw_sp_vport_vfid_join(struct mlxsw_sp_port *mlxsw_sp_vport)
+{
+   u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
+   struct mlxsw_sp_fid *f;
+   int err;
+
+   f = mlxsw_sp_vfid_find(mlxsw_sp_vport->mlxsw_sp, vid);
+   if (!f) {
+   f = mlxsw_sp_vfid_create(mlxsw_sp_vport->mlxsw_sp, vid);
+   if (IS_ERR(f))
+   return PTR_ERR(f);
+   }
+
+   if (!f->ref_count) {
+   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, f->fid, true);
+   if (err)
+   goto err_vport_flood_set;
+   }
+
+   err = mlxsw_sp_vport_fid_map(mlxsw_sp_vport, f->fid, true);
+   if (err)
+   goto err_vport_fid_map;
+
+   mlxsw_sp_vport->vport.f = f;
+   f->ref_count++;
+
+   return 0;
+
+err_vport_fid_map:
+   if (!f->ref_count)
+   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, f->fid, false);
+err_vport_flood_set:
+   if (!f->ref_count)
+   mlxsw_sp_vfid_destroy(mlxsw_sp_vport->mlxsw_sp, f);
+   return err;
+}
+
+static void mlxsw_sp_vport_vfid_leave(struct mlxsw_sp_port *mlxsw_sp_vport)
+{
+   struct mlxsw_sp_fid *f = mlxsw_sp_vport->vport.f;
+
+   mlxsw_sp_vport->vport.f = NULL;
+
+   mlxsw_sp_vport_fid_map(mlxsw_sp_vport, f->fid, false);
+
+   if (--f->ref_count == 0) {
+   mlxsw_sp_vport_flood_set(mlxsw_sp_vport, f->fid, false);
+   mlxsw_sp_vfid_destroy(mlxsw_sp_vport->mlxsw_sp, f);
+   }
+}
+
 int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
  u16 vid)
 {
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-   struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_port *mlxsw_sp_vport;
-   struct mlxsw_sp_fid *f;
int err;
 
/* VLAN 0 is added to HW filter when device goes up, but it is
@@ -775,30 +822,10 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
return 0;
}
 
-   f = mlxsw_sp_vfid_find(mlxsw_sp, vid);
-   if (!f) {
-   f = mlxsw_sp_vfid_create(mlxsw_sp, vid);
-   if (IS_ERR(f)) {
-   netdev_err(dev, "Failed to create vFID for VID=%d\n",
-  vid);
-   return PTR_ERR(f);
-   }
-   }
-
-   mlxsw_sp_vport = mlxsw_sp_port_vport_create(mlxsw_sp_port, f);
+   mlxsw_sp_vport = mlxsw_sp_port_vport_create(mlxsw_sp_port, vid);
if (!mlxsw_sp_vport) {
netdev_err(dev, "Failed to create vPort for VID=%d\n", vid);
-   err = -ENOMEM;
-   goto err_port_vport_create;
-   }
-
-   if (!f->ref_count) {
-   err = mlxsw_sp_vport_flood_set(mlxsw_sp_vport, f->fid, true);
-   if (err) {
-   netdev_err(dev, "Failed to setup flooding for FID=%d\n",
-  f->fid);
-   goto err_vport_flood_set;
-   }
+

[patch net-next 18/23] mlxsw: spectrum: Check if port is vPort using its VID

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

When L3 interfaces will be introduced a vPort won't necessarily have a
FID assigned to it. This can happen if it's not member in a bridge (in
which case it's assigned a vFID) or doesn't have an IP address (in which
case it's assigned an rFID).

Therefore, instead check the VID parameter to test whether a port is a
vPort or not.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index d6cf6de..1d34419 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -259,12 +259,6 @@ mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 
lag_id, u8 port_index)
return mlxsw_sp_port && mlxsw_sp_port->lagged ? mlxsw_sp_port : NULL;
 }
 
-static inline bool
-mlxsw_sp_port_is_vport(const struct mlxsw_sp_port *mlxsw_sp_port)
-{
-   return mlxsw_sp_port->vport.f;
-}
-
 static inline struct net_device *
 mlxsw_sp_vport_br_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
 {
@@ -277,6 +271,14 @@ mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port 
*mlxsw_sp_vport)
return mlxsw_sp_vport->vport.vid;
 }
 
+static inline bool
+mlxsw_sp_port_is_vport(const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+   u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+
+   return vid != 0;
+}
+
 static inline u16
 mlxsw_sp_vport_fid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
 {
-- 
2.5.5



[patch net-next 14/23] mlxsw: spectrum: Make vFID struct generic

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

Up until now we had a dedicated struct only for vFIDs, but before
introducing support for L3 interfaces we need to make it generic and
use it for all three types of FIDs:

1) FIDs - 0..4K-1, used for the VLAN-aware bridge
2) vFIDs - 4K..15K-1, used for VLAN-unaware bridges
3) rFIDs - 15K..16K-1, used to direct traffic to / from the router in
the device. Will be introduced later in the series.

The three types of L3 interfaces - Router InterFaces, RIFs - that will
be introduced correspond to the three types of FIDs and are configured
using them. Therefore, we'll need to store the links between them as
well as a reference count on the underlying FID, so that the
corresponding RIF will be destroyed when it reaches zero.

Note that the lower 0.5K vFIDs are currently used for for non-bridged
netdevs, so that traffic could be flooded to the CPU port. However, when
rFIDs will be introduced we'll no longer need these and they too will be
used for VLAN-unaware bridges.

Make the vFID struct generic by renaming it and some of its fields. FIDs
will be converted to use it later in the series.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 229 ++---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h |  24 +--
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  28 +--
 3 files changed, 131 insertions(+), 150 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 7a75a45..8ef8d0b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -633,14 +633,14 @@ static int mlxsw_sp_port_vlan_mode_trans(struct 
mlxsw_sp_port *mlxsw_sp_port)
return 0;
 }
 
-static struct mlxsw_sp_vfid *
+static struct mlxsw_sp_fid *
 mlxsw_sp_vfid_find(const struct mlxsw_sp *mlxsw_sp, u16 vid)
 {
-   struct mlxsw_sp_vfid *vfid;
+   struct mlxsw_sp_fid *f;
 
-   list_for_each_entry(vfid, _sp->port_vfids.list, list) {
-   if (vfid->vid == vid)
-   return vfid;
+   list_for_each_entry(f, _sp->port_vfids.list, list) {
+   if (f->vid == vid)
+   return f;
}
 
return NULL;
@@ -660,11 +660,11 @@ static int mlxsw_sp_vfid_op(struct mlxsw_sp *mlxsw_sp, 
u16 fid, bool create)
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
 }
 
-static struct mlxsw_sp_vfid *mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp,
- u16 vid)
+static struct mlxsw_sp_fid *mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp,
+u16 vid)
 {
struct device *dev = mlxsw_sp->bus_info->dev;
-   struct mlxsw_sp_vfid *f;
+   struct mlxsw_sp_fid *f;
u16 vfid, fid;
int err;
 
@@ -685,7 +685,7 @@ static struct mlxsw_sp_vfid *mlxsw_sp_vfid_create(struct 
mlxsw_sp *mlxsw_sp,
if (!f)
goto err_allocate_vfid;
 
-   f->vfid = vfid;
+   f->fid = fid;
f->vid = vid;
 
list_add(>list, _sp->port_vfids.list);
@@ -699,21 +699,21 @@ err_allocate_vfid:
 }
 
 static void mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_vfid *vfid)
+ struct mlxsw_sp_fid *f)
 {
-   u16 fid = mlxsw_sp_vfid_to_fid(vfid->vfid);
+   u16 vfid = mlxsw_sp_fid_to_vfid(f->fid);
 
-   clear_bit(vfid->vfid, mlxsw_sp->port_vfids.mapped);
-   list_del(>list);
+   clear_bit(vfid, mlxsw_sp->port_vfids.mapped);
+   list_del(>list);
 
-   mlxsw_sp_vfid_op(mlxsw_sp, fid, false);
+   mlxsw_sp_vfid_op(mlxsw_sp, f->fid, false);
 
-   kfree(vfid);
+   kfree(f);
 }
 
 static struct mlxsw_sp_port *
 mlxsw_sp_port_vport_create(struct mlxsw_sp_port *mlxsw_sp_port,
-  struct mlxsw_sp_vfid *vfid)
+  struct mlxsw_sp_fid *f)
 {
struct mlxsw_sp_port *mlxsw_sp_vport;
 
@@ -731,8 +731,8 @@ mlxsw_sp_port_vport_create(struct mlxsw_sp_port 
*mlxsw_sp_port,
mlxsw_sp_vport->stp_state = BR_STATE_FORWARDING;
mlxsw_sp_vport->lagged = mlxsw_sp_port->lagged;
mlxsw_sp_vport->lag_id = mlxsw_sp_port->lag_id;
-   mlxsw_sp_vport->vport.vfid = vfid;
-   mlxsw_sp_vport->vport.vid = vfid->vid;
+   mlxsw_sp_vport->vport.f = f;
+   mlxsw_sp_vport->vport.vid = f->vid;
 
list_add(_sp_vport->vport.list, _sp_port->vports_list);
 
@@ -761,8 +761,7 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 
__always_unused proto,
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_port *mlxsw_sp_vport;
-   struct mlxsw_sp_vfid *vfid;
-   u16 fid;
+   struct 

[patch net-next 04/23] mlxsw: spectrum: Remove unnecessary checks from event processing

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

When upper device of a VLAN device changes we already made sure it's
a bridge device in PRECHANGEUPPER, so no need to check it's a master
device in CHANGEUPPER.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 46c867f..e55c685 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3440,10 +3440,10 @@ static int mlxsw_sp_netdevice_vport_event(struct 
net_device *dev,
switch (event) {
case NETDEV_PRECHANGEUPPER:
upper_dev = info->upper_dev;
-   if (!info->master || !info->linking)
-   break;
if (!netif_is_bridge_master(upper_dev))
return -EINVAL;
+   if (!info->linking)
+   break;
/* We can't have multiple VLAN interfaces configured on
 * the same port and being members in the same bridge.
 */
@@ -3453,8 +3453,6 @@ static int mlxsw_sp_netdevice_vport_event(struct 
net_device *dev,
break;
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
-   if (!info->master)
-   break;
if (info->linking) {
if (!mlxsw_sp_vport) {
WARN_ON(!mlxsw_sp_vport);
-- 
2.5.5



[patch net-next 03/23] mlxsw: spectrum: Forbid LAG slave from having VLAN uppers

2016-06-20 Thread Jiri Pirko
From: Ido Schimmel 

When a port netdev is put under LAG it cannot have VLAN upper devices,
so forbid that. The LAG device itself can have VLAN upper devices.

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index b47e3fb..46c867f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3038,7 +3038,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
!netif_is_lag_master(upper_dev) &&
!netif_is_bridge_master(upper_dev))
return -EINVAL;
-   if (!info->master || !info->linking)
+   if (!info->linking)
break;
/* HW limitation forbids to put ports to multiple bridges. */
if (netif_is_bridge_master(upper_dev) &&
@@ -3048,6 +3048,11 @@ static int mlxsw_sp_netdevice_port_upper_event(struct 
net_device *dev,
!mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev,
   info->upper_info))
return -EINVAL;
+   if (netif_is_lag_master(upper_dev) && vlan_uses_dev(dev))
+   return -EINVAL;
+   if (netif_is_lag_port(dev) && is_vlan_dev(upper_dev) &&
+   !netif_is_lag_master(vlan_dev_real_dev(upper_dev)))
+   return -EINVAL;
break;
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
-- 
2.5.5



[Patch net 0/2] net_sched: bug fixes for ife action

2016-06-20 Thread Cong Wang
Cong Wang (2):
  act_ife: only acquire tcf_lock for existing actions
  act_ife: acquire ife_mod_lock before reading ifeoplist

 include/net/tc_act/tc_ife.h |  6 ++---
 net/sched/act_ife.c | 53 ++---
 2 files changed, 34 insertions(+), 25 deletions(-)

-- 
2.1.0



Re: [net-next,v4] openvswitch: Add packet len info to upcall.

2016-06-20 Thread pravin shelar
On Mon, Jun 20, 2016 at 7:26 AM, William Tu  wrote:
> The commit f2a4d086ed4c ("openvswitch: Add packet truncation support.")
> introduces packet truncation before sending to userspace upcall receiver.
> This patch passes up the skb->len before truncation so that the upcall
> receiver knows the original packet size. Potentially this will be used
> by sFlow, where OVS translates sFlow config header=N to a sample action,
> truncating packet to N byte in kernel datapath. Thus, only N bytes instead
> of full-packet size is copied from kernel to userspace, saving the
> kernel-to-userspace bandwidth.
>
> Signed-off-by: William Tu 
> Cc: Pravin Shelar 
> ---
> v3->v4:
> - Add OVS_PACKET_ATTR_LEN only when packet is truncated,
>   This avoid sending extra attribute in the case of miss flow.
> v2->v3:
> - Remove platform specific name.
> - Fix issue when receiving GSO packet
> - Remove skblen in struct dp_upcall_info
> v1->v2:
> - Pass skb->len to userspace instead of cutlen
> ---
Acked-by: Pravin B Shelar 

Thanks.


Re: rcu locking issue in mpls output code?

2016-06-20 Thread Stephen Hemminger

> ifconfig tons 172.16.20.20 netmask 255.255.255.0

Really, still using ifconfig?


Re: [net-next PATCH v3 00/17] Future-proof tunnel offload handlers

2016-06-20 Thread Tom Herbert
> Do we?
>
> We look up the socket in a proper way, inclusive the namespace belonging
> to the device we received the packet on. That said, I don't see a
> problem with that right now. But maybe I miss something?
>
When we so the socket lookup in udp_rcv this is done after IP layer
and packet has been determined to be loacally addressed. The packet is
for the host, and if a UDP socket is matched, even if just based on
destination port, the socket is matched and received functions are
called. There is no ambiguity.

When the lookup is performed in GRO this is before we processed IP and
determined that the packet is local. So a packet with any address
(local or not) will match a listener socket with the same UDP port.
The GRO can be performed an packet is subsequently forwarded maybe
having been modified. If this packet turns out to not be the protocol
we thought it was (e.g. VXLAN) then we have now potentially silently
corrupted someone else's packets. Grant it, there's probably a lot of
things that are required to make corruption happen, but it does allow
the possibly of systematic data corruption and we haven't discounted
this to become a security vulnerability.

Tom

> Thanks,
> Hannes
>


Re: [PATCH] ppc: Fix BPF JIT for ABIv2

2016-06-20 Thread Thadeu Lima de Souza Cascardo
On Sun, Jun 19, 2016 at 11:19:14PM +0530, Naveen N. Rao wrote:
> On 2016/06/17 10:00AM, Thadeu Lima de Souza Cascardo wrote:
> > On Fri, Jun 17, 2016 at 10:53:21PM +1000, Michael Ellerman wrote:
> > > On Tue, 2016-07-06 at 13:32:23 UTC, "Naveen N. Rao" wrote:
> > > > diff --git a/arch/powerpc/net/bpf_jit_comp64.c 
> > > > b/arch/powerpc/net/bpf_jit_comp64.c
> > > > new file mode 100644
> > > > index 000..954ff53
> > > > --- /dev/null
> > > > +++ b/arch/powerpc/net/bpf_jit_comp64.c
> > > > @@ -0,0 +1,956 @@
> > > ...
> > > > +
> > > > +static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
> > > > +{
> > > > +   int *p = area;
> > > > +
> > > > +   /* Fill whole space with trap instructions */
> > > > +   while (p < (int *)((char *)area + size))
> > > > +   *p++ = BREAKPOINT_INSTRUCTION;
> > > > +}
> > > 
> > > This breaks the build for some configs, presumably you're missing a 
> > > header:
> > > 
> > >   arch/powerpc/net/bpf_jit_comp64.c:30:10: error: 
> > > 'BREAKPOINT_INSTRUCTION' undeclared (first use in this function)
> > > 
> > > http://kisskb.ellerman.id.au/kisskb/buildresult/12720611/
> > > 
> > > cheers
> > 
> > Hi, Michael and Naveen.
> > 
> > I noticed independently that there is a problem with BPF JIT and ABIv2, and
> > worked out the patch below before I noticed Naveen's patchset and the latest
> > changes in ppc tree for a better way to check for ABI versions.
> > 
> > However, since the issue described below affect mainline and stable kernels,
> > would you consider applying it before merging your two patchsets, so that 
> > we can
> > more easily backport the fix?
> 
> Hi Cascardo,
> Given that this has been broken on ABIv2 since forever, I didn't bother 
> fixing it. But, I can see why this would be a good thing to have for 
> -stable and existing distros. However, while your patch below may fix 
> the crash you're seeing on ppc64le, it is not sufficient -- you'll need 
> changes in bpf_jit_asm.S as well.

Hi, Naveen.

Any tips on how to exercise possible issues there? Or what changes you think
would be sufficient?

I will see what I can find by myself, but would appreciate any help.

Regards.
Cascardo.

> 
> Regards,
> Naveen
> 


Re: [PATCH] [v5] net: emac: emac gigabit ethernet controller driver

2016-06-20 Thread Timur Tabi

Rob Herring wrote:

>+   interrupt-parent = <>;
>+   #interrupt-cells = <1>;
>+   interrupts = <0 1>;
>+   interrupt-map-mask = <0x>;
>+   interrupt-map = <0  0 76 0
>+1  0 80 0>;

Why? This looks unnecessary.


It may have made sense with an earlier version of the driver that had 
more complex interrupts.  I'll fix it in v6.


--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


Re: [PATCH v4 net-next v4 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses

2016-06-20 Thread kbuild test robot
Hi,

[auto build test WARNING on net-next/master]

url:
https://github.com/0day-ci/linux/commits/Vivien-Didelot/net-dsa-mv88e6xxx-probe-compatible/20160621-020115
config: m68k-allyesconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 4.9.0
reproduce:
wget 
https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
 -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=m68k 

All warnings (new ones prefixed by >>):

   In file included from include/linux/printk.h:289:0,
from include/linux/kernel.h:13,
from include/linux/delay.h:10,
from drivers/net/dsa/mv88e6xxx.c:16:
   drivers/net/dsa/mv88e6xxx.c: In function 'mv88e6xxx_read':
>> include/linux/dynamic_debug.h:64:16: warning: format '%x' expects argument 
>> of type 'unsigned int', but argument 6 has type 'u16 *' [-Wformat=]
 static struct _ddebug  __aligned(8)   \
   ^
   include/linux/dynamic_debug.h:84:2: note: in expansion of macro 
'DEFINE_DYNAMIC_DEBUG_METADATA'
 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);  \
 ^
   include/linux/device.h:1197:2: note: in expansion of macro 'dynamic_dev_dbg'
 dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
 ^
   drivers/net/dsa/mv88e6xxx.c:195:2: note: in expansion of macro 'dev_dbg'
 dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 ^

vim +64 include/linux/dynamic_debug.h

b48420c1 Jim Cromie  2012-04-27  48 const 
char *modname);
b48420c1 Jim Cromie  2012-04-27  49  
cbc46635 Joe Perches 2011-08-11  50  struct device;
cbc46635 Joe Perches 2011-08-11  51  
b9075fa9 Joe Perches 2011-10-31  52  extern __printf(3, 4)
906d2015 Joe Perches 2014-09-24  53  void __dynamic_dev_dbg(struct _ddebug 
*descriptor, const struct device *dev,
b9075fa9 Joe Perches 2011-10-31  54const char *fmt, ...);
cbc46635 Joe Perches 2011-08-11  55  
ffa10cb4 Jason Baron 2011-08-11  56  struct net_device;
ffa10cb4 Jason Baron 2011-08-11  57  
b9075fa9 Joe Perches 2011-10-31  58  extern __printf(3, 4)
906d2015 Joe Perches 2014-09-24  59  void __dynamic_netdev_dbg(struct _ddebug 
*descriptor,
ffa10cb4 Jason Baron 2011-08-11  60   const struct 
net_device *dev,
b9075fa9 Joe Perches 2011-10-31  61   const char *fmt, ...);
ffa10cb4 Jason Baron 2011-08-11  62  
07613b0b Jason Baron 2011-10-04  63  #define 
DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)   \
c0d2af63 Joe Perches 2012-10-18 @64 static struct _ddebug  __aligned(8) 
\
07613b0b Jason Baron 2011-10-04  65 __attribute__((section("__verbose"))) 
name = {  \
07613b0b Jason Baron 2011-10-04  66 .modname = KBUILD_MODNAME,  
\
07613b0b Jason Baron 2011-10-04  67 .function = __func__,   
\
07613b0b Jason Baron 2011-10-04  68 .filename = __FILE__,   
\
07613b0b Jason Baron 2011-10-04  69 .format = (fmt),
\
07613b0b Jason Baron 2011-10-04  70 .lineno = __LINE__, 
\
07613b0b Jason Baron 2011-10-04  71 .flags =  
_DPRINTK_FLAGS_DEFAULT,   \
07613b0b Jason Baron 2011-10-04  72 }

:: The code at line 64 was first introduced by commit
:: c0d2af637863940b1a4fb208224ca7acb905c39f dynamic_debug: Remove 
unnecessary __used

:: TO: Joe Perches 
:: CC: Greg Kroah-Hartman 

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


.config.gz
Description: Binary data


Re: [PATCH v4 net-next v4 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses

2016-06-20 Thread kbuild test robot
Hi,

[auto build test WARNING on net-next/master]

url:
https://github.com/0day-ci/linux/commits/Vivien-Didelot/net-dsa-mv88e6xxx-probe-compatible/20160621-020115
config: sparc64-allyesconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
wget 
https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
 -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/printk.h:289:0,
from include/linux/kernel.h:13,
from include/linux/delay.h:10,
from drivers/net/dsa/mv88e6xxx.c:16:
   drivers/net/dsa/mv88e6xxx.c: In function 'mv88e6xxx_read':
>> drivers/net/dsa/mv88e6xxx.c:195:19: warning: format '%x' expects argument of 
>> type 'unsigned int', but argument 6 has type 'u16 * {aka short unsigned int 
>> *}' [-Wformat=]
 dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
  ^
   include/linux/dynamic_debug.h:86:39: note: in definition of macro 
'dynamic_dev_dbg'
  __dynamic_dev_dbg(, dev, fmt, \
  ^
>> drivers/net/dsa/mv88e6xxx.c:195:2: note: in expansion of macro 'dev_dbg'
 dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 ^

vim +195 drivers/net/dsa/mv88e6xxx.c

10   * This program is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation; either version 2 of the License, or
13   * (at your option) any later version.
14   */
15  
  > 16  #include 
17  #include 
18  #include 
19  #include 
20  #include 
21  #include 
22  #include 
23  #include 
24  #include 
25  #include 
26  #include 
27  #include 
28  #include 
29  #include 
30  #include 
31  #include "mv88e6xxx.h"
32  
33  static void assert_reg_lock(struct mv88e6xxx_priv_state *ps)
34  {
35  if (unlikely(!mutex_is_locked(>reg_lock))) {
36  dev_err(ps->dev, "Switch registers lock not held!\n");
37  dump_stack();
38  }
39  }
40  
41  /* The switch ADDR[4:1] configuration pins define the chip SMI device 
address
42   * (ADDR[0] is always zero, thus only even SMI addresses can be 
strapped).
43   *
44   * When ADDR is all zero, the chip uses Single-chip Addressing Mode, 
assuming it
45   * is the only device connected to the SMI master. In this mode it 
responds to
46   * all 32 possible SMI addresses, and thus maps directly the internal 
devices.
47   *
48   * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, 
allowing
49   * multiple devices to share the SMI interface. In this mode it 
responds to only
50   * 2 registers, used to indirectly access the internal SMI devices.
51   */
52  
53  static int mv88e6xxx_smi_read(struct mv88e6xxx_priv_state *ps,
54int addr, int reg, u16 *val)
55  {
56  if (!ps->smi_ops)
57  return -EOPNOTSUPP;
58  
59  return ps->smi_ops->read(ps, addr, reg, val);
60  }
61  
62  static int mv88e6xxx_smi_write(struct mv88e6xxx_priv_state *ps,
63 int addr, int reg, u16 val)
64  {
65  if (!ps->smi_ops)
66  return -EOPNOTSUPP;
67  
68  return ps->smi_ops->write(ps, addr, reg, val);
69  }
70  
71  static int mv88e6xxx_smi_single_chip_read(struct mv88e6xxx_priv_state 
*ps,
72int addr, int reg, u16 *val)
73  {
74  int ret;
75  
76  ret = mdiobus_read_nested(ps->bus, addr, reg);
77  if (ret < 0)
78  return ret;
79  
80  *val = ret & 0x;
81  
82  return 0;
83  }
84  
85  static int mv88e6xxx_smi_single_chip_write(struct mv88e6xxx_priv_state 
*ps,
86 int addr, int reg, u16 val)
87  {
88  int ret;
89  
90  ret = mdiobus_write_nested(ps->bus, addr, reg, val);
91  if (ret < 0)
92  return ret;
93  
94  return 0;
95  }
96  
97  static const struct mv88e6xxx_ops mv88e6xxx_smi_single_chip_ops = {
98  .read = mv88e6xxx_smi_single_chip_read,
99  .write = mv88e6xxx_smi_single_chip_write,
   100  };
   101  
   102  static int mv88e6xxx_smi_multi_chip_wait(struct mv88e6xxx_priv_state 
*ps)
   103  {
   104  int ret;
   105  int i;
   106  
   107  for (i = 0; i < 16; i++) {
   

Re: rcu locking issue in mpls output code?

2016-06-20 Thread Lennert Buytenhek
On Mon, Jun 20, 2016 at 10:38:39AM -0600, David Ahern wrote:

> > OK, patch coming up.  Thanks!
> 
> can you build a kernel with rcu debugging enabled as well and run
> it through your tests?

git HEAD with CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y CONFIG_PROVE_RCU=y gives me a lockdep splat on the
machine under my desk when I cause mpls_output() to be called.

The script I use for that is this one -- it creates a namespace that
accepts MPLS tagged packets for one of its local IPs and then sends
an MPLS tagged packet into that namespace.  If you run the script on
an unpatched kernel with lock debugging enabled, you should be able
to see the issue as well, the lockdep splat happens on the very first
packet.

=
#!/bin/sh

ip link add tons type veth peer name tempitf

ifconfig tons 172.16.20.20 netmask 255.255.255.0

ip netns add ns1
ip netns exec ns1 ifconfig lo 127.0.0.1 up
ip link set tempitf netns ns1
ip netns exec ns1 ip link set tempitf name eth0
ip netns exec ns1 ifconfig eth0 172.16.20.21 netmask 255.255.255.0

modprobe mpls_iptunnel

ip route add 10.10.10.10/32 encap mpls 100 via inet 172.16.20.21

ip netns exec ns1 sysctl -w net.ipv4.conf.all.rp_filter=0
ip netns exec ns1 sysctl -w net.ipv4.conf.lo.rp_filter=0
ip netns exec ns1 sysctl -w net.mpls.conf.eth0.input=1
ip netns exec ns1 sysctl -w net.mpls.platform_labels=1000
ip netns exec ns1 ip addr add 10.10.10.10/32 dev lo
ip netns exec ns1 ip -f mpls route add 100 dev lo

ping -c 1 10.10.10.10
=

The patch below (which I'll submit shortly with a proper commit
message) makes this lockdep splat go away.

Enabling lock/rcu debugging gives you a lockdep splat on the first
packet going out through mpls_output(), but then makes the packet
loss / memory corruption issue stop appearing, both on my local
space heater and on much more serious hardware, probably due to
timing differences.

But, with lock/rcu debugging disabled and the patch below included,
I don't see packet loss anymore in a production environment during a
test that would fairly reliably show it before.



diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f18ae91..769cece 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2467,13 +2467,17 @@ int neigh_xmit(int index, struct net_device *dev,
tbl = neigh_tables[index];
if (!tbl)
goto out;
+   rcu_read_lock_bh();
neigh = __neigh_lookup_noref(tbl, addr, dev);
if (!neigh)
neigh = __neigh_create(tbl, addr, dev, false);
err = PTR_ERR(neigh);
-   if (IS_ERR(neigh))
+   if (IS_ERR(neigh)) {
+   rcu_read_unlock_bh();
goto out_kfree_skb;
+   }
err = neigh->output(neigh, skb);
+   rcu_read_unlock_bh();
}
else if (index == NEIGH_LINK_TABLE) {
err = dev_hard_header(skb, dev, ntohs(skb->protocol),


Re: [PATCH v4 net-next v4 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses

2016-06-20 Thread kbuild test robot
Hi,

[auto build test WARNING on net-next/master]

url:
https://github.com/0day-ci/linux/commits/Vivien-Didelot/net-dsa-mv88e6xxx-probe-compatible/20160621-020115
config: tile-allyesconfig (attached as .config)
compiler: tilegx-linux-gcc (GCC) 4.6.2
reproduce:
wget 
https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
 -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=tile 

All warnings (new ones prefixed by >>):

   drivers/net/dsa/mv88e6xxx.c: In function 'mv88e6xxx_read':
>> drivers/net/dsa/mv88e6xxx.c:195:2: warning: format '%x' expects argument of 
>> type 'unsigned int', but argument 6 has type 'u16 *' [-Wformat]

vim +195 drivers/net/dsa/mv88e6xxx.c

   179  static const struct mv88e6xxx_ops mv88e6xxx_smi_multi_chip_ops = {
   180  .read = mv88e6xxx_smi_multi_chip_read,
   181  .write = mv88e6xxx_smi_multi_chip_write,
   182  };
   183  
   184  static int mv88e6xxx_read(struct mv88e6xxx_priv_state *ps,
   185int addr, int reg, u16 *val)
   186  {
   187  int err;
   188  
   189  assert_reg_lock(ps);
   190  
   191  err = mv88e6xxx_smi_read(ps, addr, reg, val);
   192  if (err)
   193  return err;
   194  
 > 195  dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
   196  addr, reg, val);
   197  
   198  return 0;
   199  }
   200  
   201  static int mv88e6xxx_write(struct mv88e6xxx_priv_state *ps,
   202 int addr, int reg, u16 val)
   203  {

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


.config.gz
Description: Binary data


Re: [net-next PATCH v3 00/17] Future-proof tunnel offload handlers

2016-06-20 Thread Hannes Frederic Sowa
Hello,

On 20.06.2016 10:05, Tom Herbert wrote:
>> And finally, he added a big comment explaining that new tunnel types
>> should not be added to the tunnel type list, and those that exist
>> should only be used for RX.
>>
>> Therefore, this isn't openning the door for new random offloads, quite
>> the contrary.  Instead, if it making clearer what the existing
>> facilitites support, and putting an explicit cap on them.
>>
> We have no reason to believe there won't be more offloaded UDP
> protocols. There are plenty of other UDP encapsulations, transport
> protocols, and application layer protocols that could be offloaded and
> some of these may provide protocol specific features that have no
> generic analogue. The problem is that this interface is wrong.

Certainly not. And you have a hand in this as well. ;)

When we will see more and more offloads on networking cards we certainly
have to redesign this interface. New cards seem to be available which
offer new kinds of offloads but I think we should wait until we have 2-3
vendors supporting such interfaces and trying to come up with either a
new version/extension of this interface or move over to a new interface.
We simply don't know yet how and what we actually might need to support
and what abstraction is best to communicate with those drivers. I think
time will simply solve this problem. The Linux kernel is a living orgasm
anyway so it will find a way to deal with that.

> The interface and current NIC implementations are based on the
> assumption that UDP port number is sufficient to decode a UDP payload.
> This is incorrect, UDP port numbers do not have global meaning they
> can only be correctly interrupted by the endpoints in the
> communication (RFC7605).  Just because port number 4789 is assigned to
> VXLAN does not mean that any packet a device sees that has destination
> port 4789 is VXLAN, it may very well be something else completely
> different. This opens up the very real possibility that devices in the
> network, including NICs, misinterpret packets because they are looking
> only at port number. Furthermore, if a device modifies packets based
> on just port number, say like in GRO, this opens the door to silent
> data corruption. This will be a real problem with a router that is
> trying UDP offload packets just being forwarded, but even on just a
> host this can be an issue when using ns with ipvlan of macvlan.

The Linux kernel does it correctly: for every tunnel we open, we create
a UDP socket and wildcard bind it to the configured port number, so
nothing in the current namespace can bind to this port number at the
same time.

The problem is the actual hardware to date: Intel networking cards seem
to only configure the UDP port in use, not even the address family nor
the destination ip. Other networking cards seem to follow this schema.
We currently can't do anything else. If later NICs support better
filtering schemes, we can easily add it with Alex's series.

The only improvement I see right now is that we basically have to bind
to both IP protocol versions, because NICs don't care about the version.

> The design of a UDP offload interface should be predicated on the fact
> that we are offloading the receive path of a UDP socket. It follows
> that the requirement of the offload device is to match packets that
> will be received by the UDP socket. Generally, this means it needs to
> at least match by local addresses and port for an unconnected/unbound
> socket, the source address for an unconnected/bound socket, a the full
> 4-tuple for a connected socket. VLAN, macvlan, or anything else that
> could affect the selection of receive socket would also need to be
> taken in to account. The typical driver interface that provides for
> fine grained packet matching is n-tuple filtering.

Agreed. But I fear that we have to deal with the hardware at hand.

> To address the immediate problem with the current existing UDP HW
> offloads I suggest:
> 
> 1) Disallow UDP HW offload when forwarding is enabled. Applying
> offloads to UDP encapsulated packets that are only being forwarded is
> not correct.

Strictly speaking, this is the only correct way to do it right now. A
forwarding host can apply the wrong the optimizations to received UDP
packets if a tunnel is being created and the same host is used to act as
a router. Unfortunately this basically kills vxlan offloading for most,
if not all, virtualization cases and probably for most containers, too.

> 2) Open a socket for the encapsulation port in each created ns
> (similar to how RDS does this). This prevents a UDP port being used
> for encapsulation from being bound for other purposes in ns.

I am not sure if this is necessary. The devices actually having the
ndo-ops, used to configure offloading, should only be visible inside one
namespace. If those ndo-ops actually have side effects on other
namespaces, they violate the contract and should be removed from the
driver. :/

I would 

Re: [PATCH] [v5] net: emac: emac gigabit ethernet controller driver

2016-06-20 Thread Timur Tabi

Shanker Donthineni wrote:

 /* Set dma_mask and coherent_dma_mask to 64-bits,
  * if xHC supports 64-bit addressing */
 if (HCC_64BIT_ADDR(xhci->hcc_params) &&
 !dma_set_mask(dev, DMA_BIT_MASK(64))) {
 xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
 dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
 } else {
 /*
  * This is to avoid error in cases where a 32-bit USB
  * controller is used on a 64-bit capable system.
  */
 retval = dma_set_mask(dev, DMA_BIT_MASK(32));


I'm not sure this example is valid because HCC_64BIT_ADDR is part of the 
XCHI specification, so there's an architected way determine whether the 
platform is 64-bit capable or not.  The EMAC has nothing like that.


I can do this:

ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
if (ret)
dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32))

but this has always seemed wrong to me, because it doesn't make sense to 
me that DMA_BIT_MASK(64) could ever fail.  DMA_BIT_MASK(64) says that 
the device can handle any physical address, so the device does not 
impose any limitations.  How could that fail?  I have has this question 
multiple times, and I have never gotten a satisfactory answer.


Also, I don't know if I should be using dma_set_mask_and_coherent or 
dma_coerce_mask_and_coherent.  The comment for 
dma_coerce_mask_and_coherent says this:


/*
 * Similar to the above, except it deals with the case where the device
 * does not have dev->dma_mask appropriately setup.
 */

How can I know if the device has dev->dma_mask "appropriately setup"?

Remember, I need a solution that works for DT and ACPI.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


[PATCH] mpls: Add missing RCU-bh read side critical section locking in output path

2016-06-20 Thread Lennert Buytenhek
From: David Barroso 

When locally originated IP traffic hits a route that says to push
MPLS labels, we'll get a call chain dst_output() -> lwtunnel_output()
-> mpls_output() -> neigh_xmit() -> ___neigh_lookup_noref() where the
last function in this chain accesses a RCU-bh protected struct
neigh_table pointer without us ever having declared an RCU-bh read
side critical section.

As in case of locally originated IP traffic we'll be running in process
context, with softirqs enabled, we can be preempted by a softirq at any
time, and RCU-bh considers the completion of a softirq as signaling
the end of any pending read-side critical sections, so if we do get a
softirq here, we can end up with an unexpected RCU grace period and
all the nastiness that that comes with.

This patch makes neigh_xmit() take rcu_read_{,un}lock_bh() around the
code that expects to be treated as an RCU-bh read side critical section.

Signed-off-by: David Barroso 
Signed-off-by: Lennert Buytenhek 

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f18ae91..769cece 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2467,13 +2467,17 @@ int neigh_xmit(int index, struct net_device *dev,
tbl = neigh_tables[index];
if (!tbl)
goto out;
+   rcu_read_lock_bh();
neigh = __neigh_lookup_noref(tbl, addr, dev);
if (!neigh)
neigh = __neigh_create(tbl, addr, dev, false);
err = PTR_ERR(neigh);
-   if (IS_ERR(neigh))
+   if (IS_ERR(neigh)) {
+   rcu_read_unlock_bh();
goto out_kfree_skb;
+   }
err = neigh->output(neigh, skb);
+   rcu_read_unlock_bh();
}
else if (index == NEIGH_LINK_TABLE) {
err = dev_hard_header(skb, dev, ntohs(skb->protocol),


Re: [PATCH] mpls: Add missing RCU-bh read side critical section locking in output path

2016-06-20 Thread David Ahern

On 6/20/16 12:05 PM, Lennert Buytenhek wrote:

From: David Barroso 

When locally originated IP traffic hits a route that says to push
MPLS labels, we'll get a call chain dst_output() -> lwtunnel_output()
-> mpls_output() -> neigh_xmit() -> ___neigh_lookup_noref() where the
last function in this chain accesses a RCU-bh protected struct
neigh_table pointer without us ever having declared an RCU-bh read
side critical section.

As in case of locally originated IP traffic we'll be running in process
context, with softirqs enabled, we can be preempted by a softirq at any
time, and RCU-bh considers the completion of a softirq as signaling
the end of any pending read-side critical sections, so if we do get a
softirq here, we can end up with an unexpected RCU grace period and
all the nastiness that that comes with.

This patch makes neigh_xmit() take rcu_read_{,un}lock_bh() around the
code that expects to be treated as an RCU-bh read side critical section.



Fixes: 4fd3d7d9e868f ("neigh: Add helper function neigh_xmit")


Signed-off-by: David Barroso 
Signed-off-by: Lennert Buytenhek 

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f18ae91..769cece 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2467,13 +2467,17 @@ int neigh_xmit(int index, struct net_device *dev,
tbl = neigh_tables[index];
if (!tbl)
goto out;
+   rcu_read_lock_bh();
neigh = __neigh_lookup_noref(tbl, addr, dev);
if (!neigh)
neigh = __neigh_create(tbl, addr, dev, false);
err = PTR_ERR(neigh);
-   if (IS_ERR(neigh))
+   if (IS_ERR(neigh)) {
+   rcu_read_unlock_bh();
goto out_kfree_skb;
+   }
err = neigh->output(neigh, skb);
+   rcu_read_unlock_bh();
}
else if (index == NEIGH_LINK_TABLE) {
err = dev_hard_header(skb, dev, ntohs(skb->protocol),



LGTM.

Acked-by: David Ahern 


Re: [PATCH] [v5] net: emac: emac gigabit ethernet controller driver

2016-06-20 Thread Shanker Donthineni

Timur,

I think, the device driver is responsible for setting the right DMA_MASK 
based on the underlying hardware capability if your driver wants to 
support 64bit DMA.


Example code in drivers/usb/host/xhci.c:

/* Set dma_mask and coherent_dma_mask to 64-bits,
 * if xHC supports 64-bit addressing */
if (HCC_64BIT_ADDR(xhci->hcc_params) &&
!dma_set_mask(dev, DMA_BIT_MASK(64))) {
xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
} else {
/*
 * This is to avoid error in cases where a 32-bit USB
 * controller is used on a 64-bit capable system.
 */
retval = dma_set_mask(dev, DMA_BIT_MASK(32));



On 06/20/2016 12:41 PM, Timur Tabi wrote:

Rob Herring wrote:

>+dma-ranges = <0 0 0x>;

I believe dma-ranges is supposed to be in the bus (parent) node.


Maybe I'm just going to be perpetually confused by dma-ranges, but how 
can I specify that the emac has a different DMA range from another SOC 
device, if dma-ranges is in the parent node?


The EMAC itself is capable of 64-bit DMA internally (I should have 
included a dma_set_mask call with DMA_BIT_MASK(64) in the driver). 
However, the platform typically limits this range.  On FSM9900 and 
QDF2432, it's 32 bits.  On the next server chip, it'll be the full 64 
bits.  I need some way to handle that.




--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project



Re: [PATCH] [v5] net: emac: emac gigabit ethernet controller driver

2016-06-20 Thread Timur Tabi

Rob Herring wrote:

>+   dma-ranges = <0 0 0x>;

I believe dma-ranges is supposed to be in the bus (parent) node.


Maybe I'm just going to be perpetually confused by dma-ranges, but how 
can I specify that the emac has a different DMA range from another SOC 
device, if dma-ranges is in the parent node?


The EMAC itself is capable of 64-bit DMA internally (I should have 
included a dma_set_mask call with DMA_BIT_MASK(64) in the driver). 
However, the platform typically limits this range.  On FSM9900 and 
QDF2432, it's 32 bits.  On the next server chip, it'll be the full 64 
bits.  I need some way to handle that.


--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


[PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible

2016-06-20 Thread Vivien Didelot
This patchset factorizes the legacy and new SMI probing and abstracts
the switch register accesses. This simplifies adding support for new
chips or alternative register accesses.

This will allow us to use a compatible chip info to describe how to
access the SMI device and its switch ID register at probe time.

For the legacy probe, we fix the compatible info to 88E6085. For the
MDIO probe, we will use the compatible info from the device node data.

All patches are reviewed.

Changes since v4:

  - fix debug printing (was 'val' instead of '*val')

Changes since v3 [3]:

  - better register access abstraction using the chip structure

Changes since v2 [2]:

  - do not guess compatible model in legacy probe
  - add low level SMI API using a chip structure
  - allocate before probe and detection
  - add 3 cosmetic patches

Changes since v1 [1]:

  - merge style fix from Ben Dooks
  - add Acked-by/Reviewed-by tags
  - drop one compatible string per model
  - detect the SMI device based on the compatible info
  - add an SMI ops structure

[1] https://lkml.org/lkml/2016/6/8/1201
[2] https://lkml.org/lkml/2016/6/14/671
[3] https://lkml.org/lkml/2016/6/17/995

Vivien Didelot (14):
  net: dsa: mv88e6xxx: fix style issues
  net: dsa: mv88e6xxx: remove redundant assignments
  net: dsa: mv88e6xxx: use already declared variables
  net: dsa: mv88e6xxx: do not increment bus refcount
  net: dsa: mv88e6xxx: add switch register helpers
  net: dsa: mv88e6xxx: use gpio get optional variant
  net: dsa: mv88e6xxx: remove table args in info lookup
  net: dsa: mv88e6xxx: rename smi_mutex to reg_lock
  net: dsa: mv88e6xxx: add chip allocation helper
  net: dsa: mv88e6xxx: add SMI init helper
  net: dsa: mv88e6xxx: add detection helper
  net: dsa: mv88e6xxx: pass compatible info
  net: dsa: mv88e6xxx: add port base address to info
  net: dsa: mv88e6xxx: abstract switch registers accesses

 drivers/net/dsa/mv88e6xxx.c | 567 
 drivers/net/dsa/mv88e6xxx.h |  34 ++-
 2 files changed, 385 insertions(+), 216 deletions(-)

-- 
2.9.0



Re: [PATCH net-next] net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)

2016-06-20 Thread Netanel Belgazal


On 06/18/2016 12:11 AM, Francois Romieu wrote:
> Netanel Belgazal  :
> [...]
>
> More stuff below.
>
>> diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c 
>> b/drivers/net/ethernet/amazon/ena/ena_com.c
>> new file mode 100644
>> index 000..357e10f
>> --- /dev/null
>> +++ b/drivers/net/ethernet/amazon/ena/ena_com.c
> [...]
>> +static int ena_get_dev_stats(struct ena_com_dev *ena_dev,
>> + struct ena_admin_aq_get_stats_cmd *get_cmd,
>> + struct ena_admin_acq_get_stats_resp *get_resp,
> At first sight it should be possible avoid one pointer argument with:
>
> struct ena_something {
>   struct ena_admin_aq_get_stats_cmd cmd;
>   struct ena_admin_acq_get_stats_resp resp;
>   
> };
Ack
>
> [...]
>> +int ena_com_get_dev_extended_stats(struct ena_com_dev *ena_dev, char *buff,
>> +   u32 len)
> Where is it used ?
It is currently unused. I'll remove it from this patch and add it in a separate 
once we'll support it.
>
>> +{
>> +int ret = 0;
>> +struct ena_admin_aq_get_stats_cmd get_cmd;
>> +struct ena_admin_acq_get_stats_resp get_resp;
>> +void *virt_addr;
>   int rc = -ENOMEM;
>   char *str;
>
>> +dma_addr_t phys_addr;
>> +
>> +virt_addr = dma_alloc_coherent(ena_dev->dmadev,
>> +   len,
>> +   _addr,
>> +   GFP_KERNEL | __GFP_ZERO);
>> +if (!virt_addr) {
>> +ret = -ENOMEM;
>> +goto done;
>> +}
>> +memset(_cmd, 0x0, sizeof(get_cmd));
>> +ret = ena_com_mem_addr_set(ena_dev,
>> +   _cmd.u.control_buffer.address,
>> +   phys_addr);
>> +if (unlikely(ret)) {
>> +ena_trc_err("memory address set failed\n");
>> +return ret;
>> +}
>> +get_cmd.u.control_buffer.length = len;
>> +
>> +get_cmd.device_id = ena_dev->stats_func;
>> +get_cmd.queue_idx = ena_dev->stats_queue;
>> +
>> +ret = ena_get_dev_stats(ena_dev, _cmd, _resp,
>> +ENA_ADMIN_GET_STATS_TYPE_EXTENDED);
>> +if (ret < 0)
>> +goto free_ext_stats_mem;
>> +
>> +ret = snprintf(buff, len, "%s", (char *)virt_addr);
> So ENA_ADMIN_GET_STATS_TYPE_EXTENDED fills a buffer with bytes in the
> [0; 127] range, right ?

ENA_ADMIN_GET_STATS_TYPE_EXTENDED fills a buffer with 4K bytes.

>
>> +
>> +free_ext_stats_mem:
>> +dma_free_coherent(ena_dev->dmadev, len, virt_addr, phys_addr);
>> +done:
>> +return ret;
>> +}
>> +
>> +int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, int mtu)
>> +{
>> +struct ena_com_admin_queue *admin_queue;
>> +struct ena_admin_set_feat_cmd cmd;
>> +struct ena_admin_set_feat_resp resp;
>> +int ret = 0;
> Should be -ENODEV or left uninitialized.
I'll initialize it to -ENODEV
>
>> +
>> +if (unlikely(!ena_dev)) {
>> +ena_trc_err("%s : ena_dev is NULL\n", __func__);
>> +return -ENODEV;
>> +}
> Does it mean that ena_com_dev may go away while the net_device is in use ?
ena_com_dev can't go away while net_device is alive.
I'll remove this check.
>
>> +
>> +if (!ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_MTU)) {
>> +ena_trc_info("Feature %d isn't supported\n", ENA_ADMIN_MTU);
>> +return -EPERM;
>> +}
>   rc = ena_com_check_supported_feature_id(...
>   if (rc < 0) {
>   ena_trc_info(...
>   goto out;
>   }
>> +
>> +memset(, 0x0, sizeof(cmd));
>> +admin_queue = _dev->admin_queue;
>> +
>> +cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE;
>> +cmd.aq_common_descriptor.flags = 0;
>> +cmd.feat_common.feature_id = ENA_ADMIN_MTU;
>> +cmd.u.mtu.mtu = mtu;
>> +
>> +ret = ena_com_execute_admin_command(admin_queue,
>> +(struct ena_admin_aq_entry *),
>> +sizeof(cmd),
>> +(struct ena_admin_acq_entry *),
>> +sizeof(resp));
>> +
>> +if (unlikely(ret)) {
>> +ena_trc_err("Failed to set mtu %d. error: %d\n", mtu, ret);
>> +return -EINVAL;
> ena_com_execute_admin_command should return a proper status code.

ena_com_execute_admin_command already returns a proper status.
I'll remove the return value override.

>
> [...]
> diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h 
> b/drivers/net/ethernet/amazon/ena/ena_com.h
> new file mode 100644
> index 000..e49ba43
> --- /dev/null
> [...]
> +static inline void ena_com_update_intr_reg(struct ena_eth_io_intr_reg 
> *intr_reg,
> +u32 rx_delay_interval,
> +u32 tx_delay_interval,
> +bool unmask)
> +{
> + intr_reg->intr_control = 

[PATCH v5 net-next v5 01/14] net: dsa: mv88e6xxx: fix style issues

2016-06-20 Thread Vivien Didelot
This patch fixes 5 style problems reported by checkpatch:

WARNING: suspect code indent for conditional statements (8, 24)
#492: FILE: drivers/net/dsa/mv88e6xxx.c:492:
+   if (phydev->link)
+   reg |= PORT_PCS_CTRL_LINK_UP;

CHECK: Logical continuations should be on the previous line
#1318: FILE: drivers/net/dsa/mv88e6xxx.c:1318:
+oldstate == PORT_CONTROL_STATE_FORWARDING)
+   && (state == PORT_CONTROL_STATE_DISABLED ||

CHECK: multiple assignments should be avoided
#1662: FILE: drivers/net/dsa/mv88e6xxx.c:1662:
+   vlan->vid_begin = vlan->vid_end = next.vid;

WARNING: line over 80 characters
#2097: FILE: drivers/net/dsa/mv88e6xxx.c:2097:
+  const struct switchdev_obj_port_vlan 
*vlan,

WARNING: suspect code indent for conditional statements (16, 32)
#2734: FILE: drivers/net/dsa/mv88e6xxx.c:2734:
+   if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
[...]
+   reg |= PORT_CONTROL_EGRESS_ADD_TAG;

total: 0 errors, 3 warnings, 2 checks, 3805 lines checked

It also rebases and integrates changes sent by Ben Dooks [1]:

The driver has a number of functions that are not exported or
declared elsewhere, so make them static to avoid the following
warnings from sparse:

drivers/net/dsa/mv88e6xxx.c:113:5: warning: symbol 'mv88e6xxx_reg_read' was 
not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:167:5: warning: symbol 'mv88e6xxx_reg_write' 
was not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:231:5: warning: symbol 'mv88e6xxx_set_addr' was 
not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:367:6: warning: symbol 
'mv88e6xxx_ppu_state_init' was not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:3157:5: warning: symbol 
'mv88e6xxx_phy_page_read' was not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:3169:5: warning: symbol 
'mv88e6xxx_phy_page_write' was not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:3583:26: warning: symbol 
'mv88e6xxx_switch_driver' was not declared. Should it be static?
drivers/net/dsa/mv88e6xxx.c:3621:5: warning: symbol 'mv88e6xxx_probe' was 
not declared. Should it be static?

[1] http://patchwork.ozlabs.org/patch/632708/

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

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ee06055..1972ec5 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -111,7 +111,8 @@ static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state 
*ps,
return ret;
 }
 
-int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg)
+static int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr,
+ int reg)
 {
int ret;
 
@@ -165,8 +166,8 @@ static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state 
*ps, int addr,
return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
 }
 
-int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
-   int reg, u16 val)
+static int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
+  int reg, u16 val)
 {
int ret;
 
@@ -229,7 +230,7 @@ static int mv88e6xxx_set_addr_indirect(struct dsa_switch 
*ds, u8 *addr)
return 0;
 }
 
-int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
+static int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
 {
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
@@ -370,7 +371,7 @@ static void mv88e6xxx_ppu_access_put(struct 
mv88e6xxx_priv_state *ps)
mutex_unlock(>ppu_mutex);
 }
 
-void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
+static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
 {
mutex_init(>ppu_mutex);
INIT_WORK(>ppu_work, mv88e6xxx_ppu_reenable_work);
@@ -490,7 +491,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, 
int port,
 
reg |= PORT_PCS_CTRL_FORCE_LINK;
if (phydev->link)
-   reg |= PORT_PCS_CTRL_LINK_UP;
+   reg |= PORT_PCS_CTRL_LINK_UP;
 
if (mv88e6xxx_6065_family(ps) && phydev->speed > SPEED_100)
goto out;
@@ -1314,9 +1315,9 @@ static int _mv88e6xxx_port_state(struct 
mv88e6xxx_priv_state *ps, int port,
 * Blocking or Listening state.
 */
if ((oldstate == PORT_CONTROL_STATE_LEARNING ||
-oldstate == PORT_CONTROL_STATE_FORWARDING)
-   && (state == PORT_CONTROL_STATE_DISABLED ||
-   state == 

[PATCH v5 net-next v5 04/14] net: dsa: mv88e6xxx: do not increment bus refcount

2016-06-20 Thread Vivien Didelot
The MDIO device probe and remove functions are respectively incrementing
and decrementing the bus refcount themselves. Since these bus level
actions are out of the device scope, remove them.

Signed-off-by: Vivien Didelot 
Acked-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index b3170ea..4b4bffc 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3712,8 +3712,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
ps->sw_addr = mdiodev->addr;
mutex_init(>smi_mutex);
 
-   get_device(>bus->dev);
-
ds->drv = _switch_driver;
 
id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
@@ -3767,7 +3765,6 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
dsa_unregister_switch(ds);
-   put_device(>bus->dev);
 
mv88e6xxx_mdio_unregister(ps);
 }
-- 
2.9.0



[PATCH v5 net-next v5 10/14] net: dsa: mv88e6xxx: add SMI init helper

2016-06-20 Thread Vivien Didelot
Add an helper function to isolate SMI specific assignments and checks.

This function will later help choosing the different SMI accesses based
of the compatible info.

Since the chip structure is already allocated in the legacy probe, use
the mv88e6xxx_reg_read access routine instead of __mv88e6xxx_reg_read.

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

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 113092a..4e24ac5 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3616,6 +3616,19 @@ static struct mv88e6xxx_priv_state 
*mv88e6xxx_alloc_chip(struct device *dev)
return ps;
 }
 
+static int mv88e6xxx_smi_init(struct mv88e6xxx_priv_state *ps,
+ struct mii_bus *bus, int sw_addr)
+{
+   /* ADDR[0] pin is unavailable externally and considered zero */
+   if (sw_addr & 0x1)
+   return -EINVAL;
+
+   ps->bus = bus;
+   ps->sw_addr = sw_addr;
+
+   return 0;
+}
+
 static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
   struct device *host_dev, int sw_addr,
   void **priv)
@@ -3635,7 +3648,11 @@ static const char *mv88e6xxx_drv_probe(struct device 
*dsa_dev,
if (!ps)
return NULL;
 
-   id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
+   err = mv88e6xxx_smi_init(ps, bus, sw_addr);
+   if (err)
+   goto free;
+
+   id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
if (id < 0)
goto free;
 
@@ -3648,8 +3665,6 @@ static const char *mv88e6xxx_drv_probe(struct device 
*dsa_dev,
 
name = info->name;
 
-   ps->bus = bus;
-   ps->sw_addr = sw_addr;
ps->info = info;
 
err = mv88e6xxx_mdio_register(ps, NULL);
@@ -3741,8 +3756,9 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
if (!ps)
return -ENOMEM;
 
-   ps->bus = mdiodev->bus;
-   ps->sw_addr = mdiodev->addr;
+   err = mv88e6xxx_smi_init(ps, mdiodev->bus, mdiodev->addr);
+   if (err)
+   return err;
 
id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
if (id < 0)
-- 
2.9.0



[PATCH v5 net-next v5 07/14] net: dsa: mv88e6xxx: remove table args in info lookup

2016-06-20 Thread Vivien Didelot
The mv88e6xxx_table array and the mv88e6xxx_lookup_info function are
static, so remove the table and size arguments from the lookup function.

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

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ec28465..75e5408 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3590,15 +3590,13 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
},
 };
 
-static const struct mv88e6xxx_info *
-mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info 
*table,
- unsigned int num)
+static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int 
prod_num)
 {
int i;
 
-   for (i = 0; i < num; ++i)
-   if (table[i].prod_num == prod_num)
-   return [i];
+   for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
+   if (mv88e6xxx_table[i].prod_num == prod_num)
+   return _table[i];
 
return NULL;
 }
@@ -3625,8 +3623,7 @@ static const char *mv88e6xxx_drv_probe(struct device 
*dsa_dev,
prod_num = (id & 0xfff0) >> 4;
rev = id & 0x000f;
 
-   info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
-ARRAY_SIZE(mv88e6xxx_table));
+   info = mv88e6xxx_lookup_info(prod_num);
if (!info)
return NULL;
 
@@ -3739,8 +3736,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
prod_num = (id & 0xfff0) >> 4;
rev = id & 0x000f;
 
-   ps->info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
-ARRAY_SIZE(mv88e6xxx_table));
+   ps->info = mv88e6xxx_lookup_info(prod_num);
if (!ps->info)
return -ENODEV;
 
-- 
2.9.0



[PATCH v5 net-next v5 08/14] net: dsa: mv88e6xxx: rename smi_mutex to reg_lock

2016-06-20 Thread Vivien Didelot
The chip smi_mutex mutex is used to protect the access to the internal
switch registers, not only the Multi-chip Addressing Mode, as commented.

Since we will isolate SMI-specific pieces of code, avoid the confusion
now by renaming smi_mutex to reg_lock. No functional changes here.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx.c | 120 ++--
 drivers/net/dsa/mv88e6xxx.h |   7 +--
 2 files changed, 62 insertions(+), 65 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 75e5408..2c86172 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -29,10 +29,10 @@
 #include 
 #include "mv88e6xxx.h"
 
-static void assert_smi_lock(struct mv88e6xxx_priv_state *ps)
+static void assert_reg_lock(struct mv88e6xxx_priv_state *ps)
 {
-   if (unlikely(!mutex_is_locked(>smi_mutex))) {
-   dev_err(ps->dev, "SMI lock not held!\n");
+   if (unlikely(!mutex_is_locked(>reg_lock))) {
+   dev_err(ps->dev, "Switch registers lock not held!\n");
dump_stack();
}
 }
@@ -99,7 +99,7 @@ static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state 
*ps,
 {
int ret;
 
-   assert_smi_lock(ps);
+   assert_reg_lock(ps);
 
ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
if (ret < 0)
@@ -116,9 +116,9 @@ static int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state 
*ps, int addr,
 {
int ret;
 
-   mutex_lock(>smi_mutex);
+   mutex_lock(>reg_lock);
ret = _mv88e6xxx_reg_read(ps, addr, reg);
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
 
return ret;
 }
@@ -158,7 +158,7 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int 
sw_addr, int addr,
 static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
int reg, u16 val)
 {
-   assert_smi_lock(ps);
+   assert_reg_lock(ps);
 
dev_dbg(ps->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, val);
@@ -171,9 +171,9 @@ static int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state 
*ps, int addr,
 {
int ret;
 
-   mutex_lock(>smi_mutex);
+   mutex_lock(>reg_lock);
ret = _mv88e6xxx_reg_write(ps, addr, reg, val);
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
 
return ret;
 }
@@ -320,7 +320,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct 
*ugly)
 
ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
 
-   mutex_lock(>smi_mutex);
+   mutex_lock(>reg_lock);
 
if (mutex_trylock(>ppu_mutex)) {
if (mv88e6xxx_ppu_enable(ps) == 0)
@@ -328,7 +328,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct 
*ugly)
mutex_unlock(>ppu_mutex);
}
 
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
 }
 
 static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
@@ -477,7 +477,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, 
int port,
if (!phy_is_pseudo_fixed_link(phydev))
return;
 
-   mutex_lock(>smi_mutex);
+   mutex_lock(>reg_lock);
 
ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL);
if (ret < 0)
@@ -528,7 +528,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, 
int port,
_mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PCS_CTRL, reg);
 
 out:
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
 }
 
 static int _mv88e6xxx_stats_wait(struct mv88e6xxx_priv_state *ps)
@@ -753,11 +753,11 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch 
*ds, int port,
int ret;
int i, j;
 
-   mutex_lock(>smi_mutex);
+   mutex_lock(>reg_lock);
 
ret = _mv88e6xxx_stats_snapshot(ps, port);
if (ret < 0) {
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
return;
}
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
@@ -768,7 +768,7 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch 
*ds, int port,
}
}
 
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
 }
 
 static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
@@ -787,7 +787,7 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int 
port,
 
memset(p, 0xff, 32 * sizeof(u16));
 
-   mutex_lock(>smi_mutex);
+   mutex_lock(>reg_lock);
 
for (i = 0; i < 32; i++) {
int ret;
@@ -797,7 +797,7 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int 
port,
p[i] = ret;
}
 
-   mutex_unlock(>smi_mutex);
+   mutex_unlock(>reg_lock);
 }
 
 static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int 
offset,
@@ -824,9 +824,9 

[PATCH v5 net-next v5 12/14] net: dsa: mv88e6xxx: pass compatible info

2016-06-20 Thread Vivien Didelot
After allocating the chip structure, pass it a compatible info pointer.

The compatible info structure will be used later to describe how to
access the switch registers and where to read the switch ID.

For the standard MDIO probe, get it from the device node data. For the
legacy DSA driver probing, pass it the 88E6085 info.

Signed-off-by: Vivien Didelot 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mv88e6xxx.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index de92add..cadd1e3 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3617,6 +3618,7 @@ static int mv88e6xxx_detect(struct mv88e6xxx_priv_state 
*ps)
if (!info)
return -ENODEV;
 
+   /* Update the compatible info with the probed one */
ps->info = info;
 
dev_info(ps->dev, "switch 0x%x detected: %s, revision %u\n",
@@ -3669,6 +3671,9 @@ static const char *mv88e6xxx_drv_probe(struct device 
*dsa_dev,
if (!ps)
return NULL;
 
+   /* Legacy SMI probing will only support chips similar to 88E6085 */
+   ps->info = _table[MV88E6085];
+
err = mv88e6xxx_smi_init(ps, bus, sw_addr);
if (err)
goto free;
@@ -3754,14 +3759,21 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 {
struct device *dev = >dev;
struct device_node *np = dev->of_node;
+   const struct mv88e6xxx_info *compat_info;
struct mv88e6xxx_priv_state *ps;
u32 eeprom_len;
int err;
 
+   compat_info = of_device_get_match_data(dev);
+   if (!compat_info)
+   return -EINVAL;
+
ps = mv88e6xxx_alloc_chip(dev);
if (!ps)
return -ENOMEM;
 
+   ps->info = compat_info;
+
err = mv88e6xxx_smi_init(ps, mdiodev->bus, mdiodev->addr);
if (err)
return err;
@@ -3801,7 +3813,10 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
 }
 
 static const struct of_device_id mv88e6xxx_of_match[] = {
-   { .compatible = "marvell,mv88e6085" },
+   {
+   .compatible = "marvell,mv88e6085",
+   .data = _table[MV88E6085],
+   },
{ /* sentinel */ },
 };
 
-- 
2.9.0



  1   2   3   >