Re: [PATCHv3] net: usbnet: support 64bit stats in qmi_wwan driver

2017-03-31 Thread Greg Ungerer

Hi Oliver,

On 31/03/17 19:39, Oliver Neukum wrote:

Am Freitag, den 31.03.2017, 10:48 +0200 schrieb Bjørn Mork:

You get *all* the "0" line drivers for free, not only "qmi_wwan".  No
code changes needed, except for adding the single .ndo line to drivers
overriding the usbnet default net_device_ops. And even that only applies
to a few of them.  Most will be OK if you just change the usbnet
default.

I don't think the size of a complete series will be terrifying to
anyone.


It would really be nice to do that.
However, if you really don't want to do it, well you wrote
a patch. But I am afraid dropping the error count is not acceptable.


Of course dropping error counts would be, but that doesn't happen.

I will generate a patch that converts all usbnet users in one go.

Regards
Greg







Re: [PATCHv3] net: usbnet: support 64bit stats in qmi_wwan driver

2017-03-31 Thread Greg Ungerer

Hi Bjorn,

On 31/03/17 18:48, Bjørn Mork wrote:

Greg Ungerer  writes:

Add support for the net stats64 counters to the usbnet core and then to
the qmi_wwan driver.

This is a strait forward addition of 64bit counters for RX and TX packets
and byte counts. It is done in the same style as for the other net drivers
that support stats64.

The bulk of the change is to the usbnet core. Then it is trivial to use
that in the qmi_wwan.c driver. It would be very simple to extend this
support to other usbnet based drivers.


Sorry, but I am starting to have my doubts about this partial conversion
of the usbnet stats.  I don't have any problem with doing incremental
changes.  But in this case it means running duplicate code. And I see no
reasons to justify doing this incrementally.  As you say: It is very
simple to extend it to all usbnet drivers when the basic infrastructure
is in place.

You alreay do most of that work. So why not just update the other
drivers too, allowing us to drop the legacy counters?  Deleting code is
always good :)


Ok.



+void usbnet_get_stats64(struct net_device *net, struct rtnl_link_stats64 
*stats)
+{
+   struct usbnet *dev = netdev_priv(net);
+   unsigned int start;
+   int cpu;
+
+   netdev_stats_to_stats64(stats, &net->stats);
+
+   for_each_possible_cpu(cpu) {
+   struct pcpu_sw_netstats *stats64;
+   u64 rx_packets, rx_bytes;
+   u64 tx_packets, tx_bytes;
+
+   stats64 = per_cpu_ptr(dev->stats64, cpu);
+
+   do {
+   start = u64_stats_fetch_begin_irq(&stats64->syncp);
+   rx_packets = stats64->rx_packets;
+   rx_bytes = stats64->rx_bytes;
+   tx_packets = stats64->tx_packets;
+   tx_bytes = stats64->tx_bytes;
+   } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+
+   stats->rx_packets += rx_packets;
+   stats->rx_bytes += rx_bytes;
+   stats->tx_packets += tx_packets;
+   stats->tx_bytes += tx_bytes;
+   }
+}


So we only count packets and bytes.  No errors.  Why?


All stats are counted. That call to netdev_stats_to_stats64() transfers
all other stats struct fields (errors, etc) to the stats64 struct.
No error counts are lost (though they are only stored as 32bits values
on 32bit machines).



@@ -1212,8 +1249,15 @@ static void tx_complete (struct urb *urb)
struct usbnet   *dev = entry->dev;

if (urb->status == 0) {
+   struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
+
dev->net->stats.tx_packets += entry->packets;
dev->net->stats.tx_bytes += entry->length;
+
+   u64_stats_update_begin(&stats64->syncp);
+   stats64->tx_packets += entry->packets;
+   stats64->tx_bytes += entry->length;
+   u64_stats_update_end(&stats64->syncp);
} else {
dev->net->stats.tx_errors++;




This is one place where the old stats counted errors too.  But there are more:

bjorn@miraculix:/usr/local/src/git/linux$ git grep -E -- '->stats.*\+' 
drivers/net/usb/usbnet.c|grep -Ev '(bytes|packet)'
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_length_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_over_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.tx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.tx_dropped++;


Personally, I'd rather have incorrect byte counters than losing these


Luckily we can have all values correct :-)



error counters. They are valuable debugging aids. I don't see why they
cannot be converted to 64bit stats right away.  Except that it makes the
amount of double accounting much more obvious...

Which is why I have landed on on a request to convert all the usbnet
drivers in one go.  There aren't that many of them, and even fewer
touching the stats outside of usbnet.c.  Among those few, none have more
than 6 lines currently touching "stats":

bjorn@miraculix:/usr/local/src/git/linux$ for f in `git grep -l -- 'usbnet_probe' 
drivers/net/usb/`; do grep -Hc -- '->stats' $f; done
drivers/net/usb/asix_devices.c:0
drivers/net/usb/ax88179_178a.c:0
drivers/net/usb/cdc_eem.c:1
drivers/net/usb/cdc_ether.c:0
drivers/net/usb/cdc_mbim.c:0
drivers/net/usb/cdc_ncm.c:4
drivers/net/usb/cdc_subset.c:0
drivers/net/usb/ch9200.c:0
drivers/net/usb/cx82310_eth.c:0
drivers/net/usb/dm9601.c:5
drivers/net/usb/gl620a.c:0
drivers/net/usb/huawei_cdc_ncm.c:0
drivers/net/usb/int51x1.c:0
drivers/net/

Re: [PATCH net-next] udp: use sk_protocol instead of pcflag to detect udplite sockets

2017-03-31 Thread Eric Dumazet
On Fri, 2017-03-31 at 11:47 +0200, Paolo Abeni wrote:
> In the udp_sock struct, the 'forward_deficit' and 'pcflag' fields
> share the same cacheline. While the first is dirtied by
> udp_recvmsg, the latter is read, possibly several times, by the
> bottom half processing to discriminate between udp and udplite
> sockets.
> 
> With this patch, sk->sk_protocol is used to check is the socket is
> really an udplite one, avoiding some cache misses per
> packet and improving the performance under udp_flood with
> small packet up to 10%.
> 
> Signed-off-by: Paolo Abeni 
> ---
>  include/linux/udp.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/udp.h b/include/linux/udp.h
> index c0f5308..6cb4061 100644
> --- a/include/linux/udp.h
> +++ b/include/linux/udp.h
> @@ -115,6 +115,6 @@ static inline bool udp_get_no_check6_rx(struct sock *sk)
>  #define udp_portaddr_for_each_entry_rcu(__sk, list) \
>   hlist_for_each_entry_rcu(__sk, list, __sk_common.skc_portaddr_node)
>  
> -#define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
> +#define IS_UDPLITE(__sk) (__sk->sk_protocol == IPPROTO_UDPLITE)
>  
>  #endif   /* _LINUX_UDP_H */



I am pretty sure we agreed in the past that forward_deficit would need
to be placed on a cache line of its own. Somehow we manage to not
implement this properly.

What about other fields like encap_rcv, encap_destroy, gro_receive,
gro_complete. They really should have the same false sharing issue.

Proper fix is :

 include/linux/udp.h |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/udp.h b/include/linux/udp.h
index 
c0f530809d1f3db7323e51a52224eb49d8f97da0..bdfd11823c12f6c08dc6b2adb247b8e0a7f2e5d5
 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -80,8 +80,10 @@ struct udp_sock {
struct sk_buff *skb,
int nhoff);
 
-   /* This field is dirtied by udp_recvmsg() */
-   int forward_deficit;
+   /* This field is dirtied by udp_recvmsg().
+* Make sure it wont share a cache line with prior fields.
+*/
+   int forward_deficit cacheline_aligned_in_smp;
 };
 
 static inline struct udp_sock *udp_sk(const struct sock *sk)






[PATCH] net: stmmac: fix cbs configuration

2017-03-31 Thread Joao Pinto
Sending again, because forgot to include net-dev.

The QoS IP does not accept AVB capabilities to default/queue 0, this way we
guarantee 75% bandwidth for AVB. This patch assures that only queues >= 1
gets CBS confgured. Additional info was also added to stmmac.txt.

Reported-by: Niklas Cassel 
Signed-off-by: Joao Pinto 
---
 Documentation/devicetree/bindings/net/stmmac.txt  | 2 ++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/stmmac.txt 
b/Documentation/devicetree/bindings/net/stmmac.txt
index 784d988..f652b0c 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -103,6 +103,8 @@ Optional properties:
- Choose one of these modes:
- snps,dcb-algorithm: TX queue will be working in DCB
- snps,avb-algorithm: TX queue will be working in AVB
+ [Attention] Queue 0 is reserved for legacy traffic
+ and so no AVB is available in this queue.
- Configure Credit Base Shaper (if AVB Mode selected):
- snps,send_slope: enable Low Power Interface
- snps,idle_slope: unlock on WoL
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 43361f3..c1c6319 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1880,7 +1880,8 @@ static void stmmac_configure_cbs(struct stmmac_priv *priv)
u32 mode_to_use;
u32 queue;
 
-   for (queue = 0; queue < tx_queues_count; queue++) {
+   /* queue 0 is reserved for legacy traffic */
+   for (queue = 1; queue < tx_queues_count; queue++) {
mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
if (mode_to_use == MTL_QUEUE_DCB)
continue;
-- 
2.9.3



[PATCH v2] tracing/kprobes: expose maxactive for kretprobe in kprobe_events

2017-03-31 Thread Alban Crequy
When a kretprobe is installed on a kernel function, there is a maximum
limit of how many calls in parallel it can catch (aka "maxactive"). A
kernel module could call register_kretprobe() and initialize maxactive
(see example in samples/kprobes/kretprobe_example.c).

But that is not exposed to userspace and it is currently not possible to
choose maxactive when writing to /sys/kernel/debug/tracing/kprobe_events

The default maxactive can be as low as 1 on single-core with a
non-preemptive kernel. This is too low and we need to increase it not
only for recursive functions, but for functions that sleep or resched.

This patch updates the format of the command that can be written to
kprobe_events so that maxactive can be optionally specified.

I need this for a bpf program attached to the kretprobe of
inet_csk_accept, which can sleep for a long time.

This patch includes a basic selftest:

> # ./ftracetest -v  test.d/kprobe/
> === Ftrace unit tests ===
> [1] Kprobe dynamic event - adding and removing[PASS]
> [2] Kprobe dynamic event - busy event check   [PASS]
> [3] Kprobe dynamic event with arguments   [PASS]
> [4] Kprobes event arguments with types[PASS]
> [5] Kprobe dynamic event with function tracer [PASS]
> [6] Kretprobe dynamic event with arguments[PASS]
> [7] Kretprobe dynamic event with maxactive[PASS]
>
> # of passed:  7
> # of failed:  0
> # of unresolved:  0
> # of untested:  0
> # of unsupported:  0
> # of xfailed:  0
> # of undefined(test bug):  0

BugLink: https://github.com/iovisor/bcc/issues/1072
Signed-off-by: Alban Crequy 

---

Changes since v1:
- Remove "(*)" from documentation. (Review from Masami Hiramatsu)
- Fix support for "r100" without the event name (Review from Masami Hiramatsu)
- Get rid of magic numbers within the code.  (Review from Steven Rostedt)
  Note that I didn't use KRETPROBE_MAXACTIVE_ALLOC since that patch is not
  merged.
- Return -E2BIG when maxactive is too big.
- Add basic selftest
---
 Documentation/trace/kprobetrace.txt|  4 ++-
 kernel/trace/trace_kprobe.c| 39 ++
 .../ftrace/test.d/kprobe/kretprobe_maxactive.tc| 39 ++
 3 files changed, 75 insertions(+), 7 deletions(-)
 create mode 100644 
tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc

diff --git a/Documentation/trace/kprobetrace.txt 
b/Documentation/trace/kprobetrace.txt
index 41ef9d8..7051a20 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -23,7 +23,7 @@ current_tracer. Instead of that, add probe points via
 Synopsis of kprobe_events
 -
   p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe
-  r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS]: Set a return probe
+  r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe
   -:[GRP/]EVENT: Clear a probe
 
  GRP   : Group name. If omitted, use "kprobes" for it.
@@ -32,6 +32,8 @@ Synopsis of kprobe_events
  MOD   : Module name which has given SYM.
  SYM[+offs]: Symbol+offset where the probe is inserted.
  MEMADDR   : Address where the probe is inserted.
+ MAXACTIVE : Maximum number of instances of the specified function that
+ can be probed simultaneously, or 0 for the default.
 
  FETCHARGS : Arguments. Each probe can have up to 128 args.
   %REG : Fetch register REG
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index c5089c7..ae81f3c 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -25,6 +25,7 @@
 #include "trace_probe.h"
 
 #define KPROBE_EVENT_SYSTEM "kprobes"
+#define KRETPROBE_MAXACTIVE_MAX 4096
 
 /**
  * Kprobe event core functions
@@ -282,6 +283,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char 
*group,
 void *addr,
 const char *symbol,
 unsigned long offs,
+int maxactive,
 int nargs, bool is_return)
 {
struct trace_kprobe *tk;
@@ -309,6 +311,8 @@ static struct trace_kprobe *alloc_trace_kprobe(const char 
*group,
else
tk->rp.kp.pre_handler = kprobe_dispatcher;
 
+   tk->rp.maxactive = maxactive;
+
if (!event || !is_good_name(event)) {
ret = -EINVAL;
goto error;
@@ -598,8 +602,10 @@ static int create_trace_kprobe(int argc, char **argv)
 {
/*
 * Argument syntax:
-*  - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
-*  - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
+*  - Add kprobe:
+*  p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
+*  - Add kretprobe:
+*  r[MAXA

[PATCH] selftests: add a generic testsuite for ethernet device

2017-03-31 Thread Corentin Labbe
Hello

My original intent was to add network test to the kernelci project.
Since they use kselftests, they forwarded me to this.

This patch add a basic network test suite which do:
- bring up netdev
- change mac address
- try some ethtool commands
- bring down netdev

The test is non disruptive, so that an already used network interface will
not be modified (mac/IP address for example).

Regards

Corentin Labbe (1):
  selftests: add a generic testsuite for ethernet device

 tools/testing/selftests/net/Makefile |   2 +-
 tools/testing/selftests/net/netdevice.sh | 185 +++
 2 files changed, 186 insertions(+), 1 deletion(-)
 create mode 100755 tools/testing/selftests/net/netdevice.sh

-- 
2.10.2



[PATCH] selftests: add a generic testsuite for ethernet device

2017-03-31 Thread Corentin Labbe
This patch add a generic testsuite for testing ethernet network device driver.

Signed-off-by: Corentin Labbe 
---
 tools/testing/selftests/net/Makefile |   2 +-
 tools/testing/selftests/net/netdevice.sh | 185 +++
 2 files changed, 186 insertions(+), 1 deletion(-)
 create mode 100755 tools/testing/selftests/net/netdevice.sh

diff --git a/tools/testing/selftests/net/Makefile 
b/tools/testing/selftests/net/Makefile
index fbfe5d0..35cbb4c 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -5,7 +5,7 @@ CFLAGS += -I../../../../usr/include/
 
 reuseport_bpf_numa: LDFLAGS += -lnuma
 
-TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh
+TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh
 TEST_GEN_FILES =  socket
 TEST_GEN_FILES += psock_fanout psock_tpacket
 TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
diff --git a/tools/testing/selftests/net/netdevice.sh 
b/tools/testing/selftests/net/netdevice.sh
new file mode 100755
index 000..89ba827
--- /dev/null
+++ b/tools/testing/selftests/net/netdevice.sh
@@ -0,0 +1,185 @@
+#!/bin/sh
+#
+# This test is for checking network interface
+# For the moment it tests only ethernet interface (but wifi could be easily 
added)
+#
+# We assume that all network driver are loaded
+# if not they probably have failed earlier in the boot process and their 
logged error will be catched by another test
+#
+
+# this function will try to up the interface
+# if already up, nothing done
+# arg1: network interface name
+kci_net_start()
+{
+   netdev=$1
+
+   ip link show "$netdev" |grep -q UP
+   if [ $? -eq 0 ];then
+   echo "SKIP: interface $netdev already up"
+   return 0
+   fi
+
+   ip link set "$netdev" up
+   if [ $? -ne 0 ];then
+   echo "FAIL: Fail to up $netdev"
+   return 1
+   else
+   echo "PASS: set interface $netdev up"
+   NETDEV_STARTED=1
+   fi
+   return 0
+}
+
+# this function will try to setup an IP and MAC address on a network interface
+# Doing nothing if the interface was already up
+# arg1: network interface name
+kci_net_setup()
+{
+   netdev=$1
+
+   # do nothing if the interface was already up
+   if [ $NETDEV_STARTED -eq 0 ];then
+   return 0
+   fi
+
+   ip link set dev $netdev address 02:03:04:05:06:07
+   if [ $? -ne 0 ];then
+   echo "FAIL: Cannot set MAC address to $netdev"
+   return 1
+   fi
+   echo "PASS: set MAC address to $netdev"
+
+   #check that the interface did not already have an IP
+   ip address show "$netdev" |grep '^[[:space:]]*inet'
+   if [ $? -eq 0 ];then
+   echo "SKIP: $netdev already have an IP"
+   return 0
+   fi
+
+   # TODO what ipaddr to set ? DHCP ?
+   echo "SKIP: set IP address to $netdev"
+   return 0
+}
+
+# test an ethtool command
+# arg1: return code for not supported (see ethtool code source)
+# arg2: summary of the command
+# arg3: command to execute
+kci_netdev_ethtool_test()
+{
+   if [ $# -le 2 ];then
+   echo "SKIP: invalid number of arguments"
+   return 1
+   fi
+   $3 >/dev/null
+   ret=$?
+   if [ $ret -ne 0 ];then
+   if [ $ret -eq "$1" ];then
+   echo "SKIP: ethtool $2 $netdev not supported"
+   else
+   echo "FAIL: ethtool $2 $netdev"
+   return 1
+   fi
+   else
+   echo "PASS: ethtool $2 $netdev"
+   fi
+   return 0
+}
+
+# test ethtool commands
+# arg1: network interface name
+kci_netdev_ethtool()
+{
+   netdev=$1
+
+   #check presence of ethtool
+   ethtool --version 2>/dev/null >/dev/null
+   if [ $? -ne 0 ];then
+   echo "SKIP: ethtool not present"
+   return 1
+   fi
+
+   TMP_ETHTOOL_FEATURES="$(mktemp)"
+   if [ ! -e "$TMP_ETHTOOL_FEATURES" ];then
+   echo "SKIP: Cannot create a tmp file"
+   return 1
+   fi
+
+   ethtool -k "$netdev" > "$TMP_ETHTOOL_FEATURES"
+   if [ $? -ne 0 ];then
+   echo "FAIL: ethtool -k $netdev"
+   rm "$TMP_ETHTOOL_FEATURES"
+   return 1
+   fi
+   #TODO for each non fixed features, try to turn them on/off
+   rm "$TMP_ETHTOOL_FEATURES"
+
+   kci_netdev_ethtool_test 74 'dump' "ethtool -d $netdev"
+   kci_netdev_ethtool_test 94 'stats' "ethtool -S $netdev"
+   return 0
+}
+
+# stop a netdev
+# arg1: network interface name
+kci_netdev_stop()
+{
+   netdev=$1
+
+   if [ $NETDEV_STARTED -eq 0 ];then
+   echo "SKIP: interface $netdev kept up"
+   return 0
+   fi
+
+   ip link set "$netdev" down
+   if [ $? -ne 0 ];then
+   echo "FAIL: stop $netdev"
+   re

[PATCH V2 net-next 01/18] net: hns: Fix the implementation of irq affinity function

2017-03-31 Thread Salil Mehta
From: lipeng 

This patch fixes the implementation of the IRQ affinity
function. This function is used to create the cpu mask
which eventually is used to initialize the cpu<->queue
association for XPS(Transmit Packet Steering).

Signed-off-by: lipeng 
Signed-off-by: Kejian Yan 
Reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 75 +++
 drivers/net/ethernet/hisilicon/hns/hns_enet.h |  1 +
 2 files changed, 30 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index fca37e2..73ec8c8 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1196,54 +1196,31 @@ static void hns_nic_ring_close(struct net_device 
*netdev, int idx)
napi_disable(&priv->ring_data[idx].napi);
 }
 
-static void hns_set_irq_affinity(struct hns_nic_priv *priv)
+static int hns_nic_init_affinity_mask(int q_num, int ring_idx,
+ struct hnae_ring *ring, cpumask_t *mask)
 {
-   struct hnae_handle *h = priv->ae_handle;
-   struct hns_nic_ring_data *rd;
-   int i;
int cpu;
-   cpumask_var_t mask;
 
-   if (!alloc_cpumask_var(&mask, GFP_KERNEL))
-   return;
-
-   /*diffrent irq banlance for 16core and 32core*/
-   if (h->q_num == num_possible_cpus()) {
-   for (i = 0; i < h->q_num * 2; i++) {
-   rd = &priv->ring_data[i];
-   if (cpu_online(rd->queue_index)) {
-   cpumask_clear(mask);
-   cpu = rd->queue_index;
-   cpumask_set_cpu(cpu, mask);
-   (void)irq_set_affinity_hint(rd->ring->irq,
-   mask);
-   }
-   }
+   /* Diffrent irq banlance between 16core and 32core.
+* The cpu mask set by ring index according to the ring flag
+* which indicate the ring is tx or rx.
+*/
+   if (q_num == num_possible_cpus()) {
+   if (is_tx_ring(ring))
+   cpu = ring_idx;
+   else
+   cpu = ring_idx - q_num;
} else {
-   for (i = 0; i < h->q_num; i++) {
-   rd = &priv->ring_data[i];
-   if (cpu_online(rd->queue_index * 2)) {
-   cpumask_clear(mask);
-   cpu = rd->queue_index * 2;
-   cpumask_set_cpu(cpu, mask);
-   (void)irq_set_affinity_hint(rd->ring->irq,
-   mask);
-   }
-   }
-
-   for (i = h->q_num; i < h->q_num * 2; i++) {
-   rd = &priv->ring_data[i];
-   if (cpu_online(rd->queue_index * 2 + 1)) {
-   cpumask_clear(mask);
-   cpu = rd->queue_index * 2 + 1;
-   cpumask_set_cpu(cpu, mask);
-   (void)irq_set_affinity_hint(rd->ring->irq,
-   mask);
-   }
-   }
+   if (is_tx_ring(ring))
+   cpu = ring_idx * 2;
+   else
+   cpu = (ring_idx - q_num) * 2 + 1;
}
 
-   free_cpumask_var(mask);
+   cpumask_clear(mask);
+   cpumask_set_cpu(cpu, mask);
+
+   return cpu;
 }
 
 static int hns_nic_init_irq(struct hns_nic_priv *priv)
@@ -1252,6 +1229,7 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv)
struct hns_nic_ring_data *rd;
int i;
int ret;
+   int cpu;
 
for (i = 0; i < h->q_num * 2; i++) {
rd = &priv->ring_data[i];
@@ -1261,7 +1239,7 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv)
 
snprintf(rd->ring->ring_name, RCB_RING_NAME_LEN,
 "%s-%s%d", priv->netdev->name,
-(i < h->q_num ? "tx" : "rx"), rd->queue_index);
+(is_tx_ring(rd->ring) ? "tx" : "rx"), rd->queue_index);
 
rd->ring->ring_name[RCB_RING_NAME_LEN - 1] = '\0';
 
@@ -1273,12 +1251,17 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv)
return ret;
}
disable_irq(rd->ring->irq);
+
+   cpu = hns_nic_init_affinity_mask(h->q_num, i,
+rd->ring, &rd->mask);
+
+   if (cpu_online(cpu))
+   irq_set_affinity_hint(rd->ring->irq,
+ &rd->mask);
+
rd->ring->irq_init_flag = RCB_IRQ_INITED;
}
 
- 

[PATCH V2 net-next 00/18] net: hns: Misc. HNS Bug Fixes & Code Improvements

2017-03-31 Thread Salil Mehta
This patch set introduces various HNS bug fixes, optimizations and code
improvements.

Daode Huang (1):
  net: hns: bug fix of ethtool show the speed

Kejian Yan (7):
  net: hns: Remove the redundant adding and deleting mac function
  net: hns: Remove redundant mac_get_id()
  net: hns: Remove redundant mac table operations
  net: hns: Clean redundant code from hns_mdio.c file
  net: hns: Optimise the code in hns_mdio_wait_ready()
  net: hns: Simplify the exception sequence in hns_ppe_init()
  net: hns: Adjust the SBM module buffer threshold

Salil Mehta (1):
  net: hns: Some checkpatch.pl script & warning fixes

lipeng (9):
  net: hns: Fix the implementation of irq affinity function
  net: hns: Modify GMAC init TX threshold value
  net: hns: Optimize the code for GMAC pad and crc Config
  net: hns: Remove redundant memset during buffer release
  net: hns: Optimize hns_nic_common_poll for better performance
  net: hns: Fix to adjust buf_size of ring according to mtu
  net: hns: Replace netif_tx_lock to ring spin lock
  net: hns: Correct HNS RSS key set function
  net: hns: Avoid Hip06 chip TX packet line bug

 drivers/net/ethernet/hisilicon/hns/hnae.c  |   7 +-
 drivers/net/ethernet/hisilicon/hns/hnae.h  |  47 ++-
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c  | 127 +--
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c |  61 ++--
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c  |  41 +--
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h  |   5 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 249 +
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h |  14 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c  |  17 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c  | 143 ++--
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h  |  26 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h  |   6 +-
 .../net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c|  13 -
 drivers/net/ethernet/hisilicon/hns/hns_enet.c  | 400 -
 drivers/net/ethernet/hisilicon/hns/hns_enet.h  |   3 +-
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c   |  34 +-
 drivers/net/ethernet/hisilicon/hns_mdio.c  |  20 +-
 17 files changed, 653 insertions(+), 560 deletions(-)

-- 
2.7.4




[PATCH V2 net-next 04/18] net: hns: Remove redundant memset during buffer release

2017-03-31 Thread Salil Mehta
From: lipeng 

Because all members of desc_cb is assigned when xmit one package, so it
can delete in hnae_free_buffer, as follows:
- "dma, priv, length, type" are assigned in fill_v2_desc.
- "page_offset, reuse_flag, buf" are not used in tx direction.

Signed-off-by: lipeng 
Signed-off-by: Weiwei Deng 
Reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hnae.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c 
b/drivers/net/ethernet/hisilicon/hns/hnae.c
index b6ed818..78af663 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.c
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -61,7 +61,6 @@ static void hnae_free_buffer(struct hnae_ring *ring, struct 
hnae_desc_cb *cb)
dev_kfree_skb_any((struct sk_buff *)cb->priv);
else if (unlikely(is_rx_ring(ring)))
put_page((struct page *)cb->priv);
-   memset(cb, 0, sizeof(*cb));
 }
 
 static int hnae_map_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
-- 
2.7.4




[PATCH V2 net-next 02/18] net: hns: Modify GMAC init TX threshold value

2017-03-31 Thread Salil Mehta
From: lipeng 

This patch reduces GMAC TX threshold value to avoid gmac
hang-up with speed 100M/duplex half.

Signed-off-by: lipeng 
Signed-off-by: JinchuanTian 
Reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 6 ++
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h  | 4 
 2 files changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 3382441..a8dbe00 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -325,6 +325,12 @@ static void hns_gmac_init(void *mac_drv)
hns_gmac_tx_loop_pkt_dis(mac_drv);
if (drv->mac_cb->mac_type == HNAE_PORT_DEBUG)
hns_gmac_set_uc_match(mac_drv, 0);
+
+   /* reduce gmac tx water line to avoid gmac hang-up
+* in speed 100M and duplex half.
+*/
+   dsaf_set_dev_field(drv, GMAC_TX_WATER_LINE_REG, GMAC_TX_WATER_LINE_MASK,
+  GMAC_TX_WATER_LINE_SHIFT, 8);
 }
 
 void hns_gmac_update_stats(void *mac_drv)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index 8fa18fc..4b8af68 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -466,6 +466,7 @@
 
 #define GMAC_DUPLEX_TYPE_REG   0x0008UL
 #define GMAC_FD_FC_TYPE_REG0x000CUL
+#define GMAC_TX_WATER_LINE_REG 0x0010UL
 #define GMAC_FC_TX_TIMER_REG   0x001CUL
 #define GMAC_FD_FC_ADDR_LOW_REG0x0020UL
 #define GMAC_FD_FC_ADDR_HIGH_REG   0x0024UL
@@ -912,6 +913,9 @@
 
 #define GMAC_DUPLEX_TYPE_B 0
 
+#define GMAC_TX_WATER_LINE_MASK((1UL << 8) - 1)
+#define GMAC_TX_WATER_LINE_SHIFT   0
+
 #define GMAC_FC_TX_TIMER_S 0
 #define GMAC_FC_TX_TIMER_M 0x
 
-- 
2.7.4




[PATCH V2 net-next 03/18] net: hns: Optimize the code for GMAC pad and crc Config

2017-03-31 Thread Salil Mehta
From: lipeng 

This patch optimises the init configuration code leg
for gmac pad and crc set interface.

Signed-off-by: lipeng 
Signed-off-by: JinchuanTian 
Reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 36 ++
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index a8dbe00..723f3ae 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -148,6 +148,17 @@ static void hns_gmac_config_max_frame_length(void 
*mac_drv, u16 newval)
   GMAC_MAX_FRM_SIZE_S, newval);
 }
 
+static void hns_gmac_config_pad_and_crc(void *mac_drv, u8 newval)
+{
+   u32 tx_ctrl;
+   struct mac_driver *drv = (struct mac_driver *)mac_drv;
+
+   tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
+   dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, !!newval);
+   dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, !!newval);
+   dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl);
+}
+
 static void hns_gmac_config_an_mode(void *mac_drv, u8 newval)
 {
struct mac_driver *drv = (struct mac_driver *)mac_drv;
@@ -250,7 +261,6 @@ static void hns_gmac_get_pausefrm_cfg(void *mac_drv, u32 
*rx_pause_en,
 static int hns_gmac_adjust_link(void *mac_drv, enum mac_speed speed,
u32 full_duplex)
 {
-   u32 tx_ctrl;
struct mac_driver *drv = (struct mac_driver *)mac_drv;
 
dsaf_set_dev_bit(drv, GMAC_DUPLEX_TYPE_REG,
@@ -279,14 +289,6 @@ static int hns_gmac_adjust_link(void *mac_drv, enum 
mac_speed speed,
return -EINVAL;
}
 
-   tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
-   dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, 1);
-   dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, 1);
-   dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl);
-
-   dsaf_set_dev_bit(drv, GMAC_MODE_CHANGE_EN_REG,
-GMAC_MODE_CHANGE_EB_B, 1);
-
return 0;
 }
 
@@ -326,6 +328,11 @@ static void hns_gmac_init(void *mac_drv)
if (drv->mac_cb->mac_type == HNAE_PORT_DEBUG)
hns_gmac_set_uc_match(mac_drv, 0);
 
+   hns_gmac_config_pad_and_crc(mac_drv, 1);
+
+   dsaf_set_dev_bit(drv, GMAC_MODE_CHANGE_EN_REG,
+GMAC_MODE_CHANGE_EB_B, 1);
+
/* reduce gmac tx water line to avoid gmac hang-up
 * in speed 100M and duplex half.
 */
@@ -459,17 +466,6 @@ static int hns_gmac_config_loopback(void *mac_drv, enum 
hnae_loop loop_mode,
return 0;
 }
 
-static void hns_gmac_config_pad_and_crc(void *mac_drv, u8 newval)
-{
-   u32 tx_ctrl;
-   struct mac_driver *drv = (struct mac_driver *)mac_drv;
-
-   tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG);
-   dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, !!newval);
-   dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, !!newval);
-   dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl);
-}
-
 static void hns_gmac_get_id(void *mac_drv, u8 *mac_id)
 {
struct mac_driver *drv = (struct mac_driver *)mac_drv;
-- 
2.7.4




[PATCH V2 net-next 06/18] net: hns: Optimize hns_nic_common_poll for better performance

2017-03-31 Thread Salil Mehta
From: lipeng 

After polling less than buget packages, we need check again. If
there are still some packages, we call napi_schedule add softirq
queue, this is not better way. So we return buget value instead
of napi_schedule.

Signed-off-by: lipeng 
reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 50 ---
 drivers/net/ethernet/hisilicon/hns/hns_enet.h |  2 +-
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 73ec8c8..5f67db2 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -859,7 +859,7 @@ static int hns_nic_rx_poll_one(struct hns_nic_ring_data 
*ring_data,
return recv_pkts;
 }
 
-static void hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data)
+static bool hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data)
 {
struct hnae_ring *ring = ring_data->ring;
int num = 0;
@@ -873,22 +873,23 @@ static void hns_nic_rx_fini_pro(struct hns_nic_ring_data 
*ring_data)
ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
ring_data->ring, 1);
 
-   napi_schedule(&ring_data->napi);
+   return false;
+   } else {
+   return true;
}
 }
 
-static void hns_nic_rx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
+static bool hns_nic_rx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
 {
struct hnae_ring *ring = ring_data->ring;
-   int num = 0;
+   int num;
 
num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
 
-   if (num == 0)
-   ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
-   ring, 0);
+   if (!num)
+   return true;
else
-   napi_schedule(&ring_data->napi);
+   return false;
 }
 
 static inline void hns_nic_reclaim_one_desc(struct hnae_ring *ring,
@@ -989,7 +990,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data 
*ring_data,
return 0;
 }
 
-static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data)
+static bool hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data)
 {
struct hnae_ring *ring = ring_data->ring;
int head;
@@ -1002,20 +1003,21 @@ static void hns_nic_tx_fini_pro(struct 
hns_nic_ring_data *ring_data)
ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
ring_data->ring, 1);
 
-   napi_schedule(&ring_data->napi);
+   return false;
+   } else {
+   return true;
}
 }
 
-static void hns_nic_tx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
+static bool hns_nic_tx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
 {
struct hnae_ring *ring = ring_data->ring;
int head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
 
if (head == ring->next_to_clean)
-   ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
-   ring, 0);
+   return true;
else
-   napi_schedule(&ring_data->napi);
+   return false;
 }
 
 static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data)
@@ -1042,15 +1044,23 @@ static void hns_nic_tx_clr_all_bufs(struct 
hns_nic_ring_data *ring_data)
 
 static int hns_nic_common_poll(struct napi_struct *napi, int budget)
 {
+   int clean_complete = 0;
struct hns_nic_ring_data *ring_data =
container_of(napi, struct hns_nic_ring_data, napi);
-   int clean_complete = ring_data->poll_one(
-   ring_data, budget, ring_data->ex_process);
+   struct hnae_ring *ring = ring_data->ring;
 
-   if (clean_complete >= 0 && clean_complete < budget) {
-   napi_complete(napi);
-   ring_data->fini_process(ring_data);
-   return 0;
+try_again:
+   clean_complete += ring_data->poll_one(
+   ring_data, budget - clean_complete,
+   ring_data->ex_process);
+
+   if (clean_complete < budget) {
+   if (ring_data->fini_process(ring_data)) {
+   napi_complete(napi);
+   ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
+   } else {
+   goto try_again;
+   }
}
 
return clean_complete;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.h
index fff8f8a..1b83232 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h
@@ -41,7 +41,7 @@ struct hns_nic_ring_data {
int queue_index;
int (*poll_one)(struct hns_nic_ring_data *, int, void *);
void (*ex_process)(struct hns_nic_ring_data *, struct sk_bu

[PATCH V2 net-next 08/18] net: hns: Replace netif_tx_lock to ring spin lock

2017-03-31 Thread Salil Mehta
From: lipeng 

netif_tx_lock is a global spin lock, it will take affect
in all rings in the netdevice. In tx_poll_one process, it can
only lock the current ring, in this case, we define a spin lock
in hnae_ring struct for it.

Signed-off-by: lipeng 
reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hnae.c |  1 +
 drivers/net/ethernet/hisilicon/hns/hnae.h |  3 +++
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 21 +++--
 3 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c 
b/drivers/net/ethernet/hisilicon/hns/hnae.c
index 78af663..513c257 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.c
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -196,6 +196,7 @@ hnae_init_ring(struct hnae_queue *q, struct hnae_ring 
*ring, int flags)
 
ring->q = q;
ring->flags = flags;
+   spin_lock_init(&ring->lock);
assert(!ring->desc && !ring->desc_cb && !ring->desc_dma_addr);
 
/* not matter for tx or rx ring, the ntc and ntc start from 0 */
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h 
b/drivers/net/ethernet/hisilicon/hns/hnae.h
index c66581d..859c536 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -275,6 +275,9 @@ struct hnae_ring {
/* statistic */
struct ring_stats stats;
 
+   /* ring lock for poll one */
+   spinlock_t lock;
+
dma_addr_t desc_dma_addr;
u32 buf_size;   /* size for hnae_desc->addr, preset by AE */
u16 desc_num;   /* total number of desc */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 3449a18..3634366 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -922,12 +922,13 @@ static int is_valid_clean_head(struct hnae_ring *ring, 
int h)
 
 /* netif_tx_lock will turn down the performance, set only when necessary */
 #ifdef CONFIG_NET_POLL_CONTROLLER
-#define NETIF_TX_LOCK(ndev) netif_tx_lock(ndev)
-#define NETIF_TX_UNLOCK(ndev) netif_tx_unlock(ndev)
+#define NETIF_TX_LOCK(ring) spin_lock(&ring->lock)
+#define NETIF_TX_UNLOCK(ring) spin_unlock(&ring->lock)
 #else
-#define NETIF_TX_LOCK(ndev)
-#define NETIF_TX_UNLOCK(ndev)
+#define NETIF_TX_LOCK(ring)
+#define NETIF_TX_UNLOCK(ring)
 #endif
+
 /* reclaim all desc in one budget
  * return error or number of desc left
  */
@@ -941,13 +942,13 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data 
*ring_data,
int head;
int bytes, pkts;
 
-   NETIF_TX_LOCK(ndev);
+   NETIF_TX_LOCK(ring);
 
head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
rmb(); /* make sure head is ready before touch any data */
 
if (is_ring_empty(ring) || head == ring->next_to_clean) {
-   NETIF_TX_UNLOCK(ndev);
+   NETIF_TX_UNLOCK(ring);
return 0; /* no data to poll */
}
 
@@ -955,7 +956,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data 
*ring_data,
netdev_err(ndev, "wrong head (%d, %d-%d)\n", head,
   ring->next_to_use, ring->next_to_clean);
ring->stats.io_err_cnt++;
-   NETIF_TX_UNLOCK(ndev);
+   NETIF_TX_UNLOCK(ring);
return -EIO;
}
 
@@ -967,7 +968,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data 
*ring_data,
prefetch(&ring->desc_cb[ring->next_to_clean]);
}
 
-   NETIF_TX_UNLOCK(ndev);
+   NETIF_TX_UNLOCK(ring);
 
dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
netdev_tx_completed_queue(dev_queue, pkts, bytes);
@@ -1028,7 +1029,7 @@ static void hns_nic_tx_clr_all_bufs(struct 
hns_nic_ring_data *ring_data)
int head;
int bytes, pkts;
 
-   NETIF_TX_LOCK(ndev);
+   NETIF_TX_LOCK(ring);
 
head = ring->next_to_use; /* ntu :soft setted ring position*/
bytes = 0;
@@ -1036,7 +1037,7 @@ static void hns_nic_tx_clr_all_bufs(struct 
hns_nic_ring_data *ring_data)
while (head != ring->next_to_clean)
hns_nic_reclaim_one_desc(ring, &bytes, &pkts);
 
-   NETIF_TX_UNLOCK(ndev);
+   NETIF_TX_UNLOCK(ring);
 
dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
netdev_tx_reset_queue(dev_queue);
-- 
2.7.4




[PATCH V2 net-next 09/18] net: hns: Correct HNS RSS key set function

2017-03-31 Thread Salil Mehta
From: lipeng 

This patch fixes below ethtool configuration error:

localhost:~ # ethtool -X eth0 hkey XX:XX:XX...
Cannot set Rx flow hash configuration: Operation not supported

Signed-off-by: lipeng 
Reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 23 ++-
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c  |  9 -
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index cd7e88e..f0142e5 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -826,8 +826,9 @@ static int hns_ae_get_rss(struct hnae_handle *handle, u32 
*indir, u8 *key,
memcpy(key, ppe_cb->rss_key, HNS_PPEV2_RSS_KEY_SIZE);
 
/* update the current hash->queue mappings from the shadow RSS table */
-   memcpy(indir, ppe_cb->rss_indir_table,
-  HNS_PPEV2_RSS_IND_TBL_SIZE * sizeof(*indir));
+   if (indir)
+   memcpy(indir, ppe_cb->rss_indir_table,
+  HNS_PPEV2_RSS_IND_TBL_SIZE  * sizeof(*indir));
 
return 0;
 }
@@ -838,15 +839,19 @@ static int hns_ae_set_rss(struct hnae_handle *handle, 
const u32 *indir,
struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle);
 
/* set the RSS Hash Key if specififed by the user */
-   if (key)
-   hns_ppe_set_rss_key(ppe_cb, (u32 *)key);
+   if (key) {
+   memcpy(ppe_cb->rss_key, key, HNS_PPEV2_RSS_KEY_SIZE);
+   hns_ppe_set_rss_key(ppe_cb, ppe_cb->rss_key);
+   }
 
-   /* update the shadow RSS table with user specified qids */
-   memcpy(ppe_cb->rss_indir_table, indir,
-  HNS_PPEV2_RSS_IND_TBL_SIZE * sizeof(*indir));
+   if (indir) {
+   /* update the shadow RSS table with user specified qids */
+   memcpy(ppe_cb->rss_indir_table, indir,
+  HNS_PPEV2_RSS_IND_TBL_SIZE  * sizeof(*indir));
 
-   /* now update the hardware */
-   hns_ppe_set_indir_table(ppe_cb, ppe_cb->rss_indir_table);
+   /* now update the hardware */
+   hns_ppe_set_indir_table(ppe_cb, ppe_cb->rss_indir_table);
+   }
 
return 0;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 3404eac..3a2a342 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -1244,6 +1244,7 @@ hns_set_rss(struct net_device *netdev, const u32 *indir, 
const u8 *key,
 {
struct hns_nic_priv *priv = netdev_priv(netdev);
struct hnae_ae_ops *ops;
+   int ret;
 
if (AE_IS_VER1(priv->enet_ver)) {
netdev_err(netdev,
@@ -1253,12 +1254,10 @@ hns_set_rss(struct net_device *netdev, const u32 
*indir, const u8 *key,
 
ops = priv->ae_handle->dev->ops;
 
-   /* currently hfunc can only be Toeplitz hash */
-   if (key ||
-   (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
+   if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
+   netdev_err(netdev, "Invalid hfunc!\n");
return -EOPNOTSUPP;
-   if (!indir)
-   return 0;
+   }
 
return ops->set_rss(priv->ae_handle, indir, key, hfunc);
 }
-- 
2.7.4




[PATCH V2 net-next 05/18] net: hns: bug fix of ethtool show the speed

2017-03-31 Thread Salil Mehta
From: Daode Huang 

When run ethtool ethX on hns driver, the speed will show
as "Unknown". The base.speed is not correct assigned,
this patch fix this bug.

Signed-off-by: Daode Huang 
Reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 3ac2183..3404eac 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -146,7 +146,7 @@ static int hns_nic_get_link_ksettings(struct net_device 
*net_dev,
 
/* When there is no phy, autoneg is off. */
cmd->base.autoneg = false;
-   cmd->base.cmd = speed;
+   cmd->base.speed = speed;
cmd->base.duplex = duplex;
 
if (net_dev->phydev)
-- 
2.7.4




[PATCH V2 net-next 07/18] net: hns: Fix to adjust buf_size of ring according to mtu

2017-03-31 Thread Salil Mehta
From: lipeng 

Because buf_size of ring set to 2048, the process of rx_poll_one
can reuse the page, therefore the performance of XGE can improve.
But the chip only supports three bds in one package, so the max mtu
is 6K when it sets to 2048. For better performane in litter mtu, we
need change buf_size according to mtu.

When user change mtu, hns is only change the desc in memory. There
are some desc has been fetched by the chip, these desc can not be
changed by the code. So it needs set the port loopback and send
some packages to let the chip consumes the wrong desc and fetch new
desc.
Because the Pv660 do not support rss indirection, we need add version
check in mtu change process.

Signed-off-by: lipeng 
reviewed-by: Yisen Zhuang 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hnae.h |  37 
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c |  26 ++-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c |   3 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h |   2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c |  41 +++-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h |   3 +
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 249 +-
 7 files changed, 337 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h 
b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 8016854..c66581d 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -67,6 +67,8 @@ do { \
 #define AE_IS_VER1(ver) ((ver) == AE_VERSION_1)
 #define AE_NAME_SIZE 16
 
+#define BD_SIZE_2048_MAX_MTU   6000
+
 /* some said the RX and TX RCB format should not be the same in the future. But
  * it is the same now...
  */
@@ -646,6 +648,41 @@ static inline void hnae_reuse_buffer(struct hnae_ring 
*ring, int i)
ring->desc[i].rx.ipoff_bnum_pid_flag = 0;
 }
 
+/* when reinit buffer size, we should reinit buffer description */
+static inline void hnae_reinit_all_ring_desc(struct hnae_handle *h)
+{
+   int i, j;
+   struct hnae_ring *ring;
+
+   for (i = 0; i < h->q_num; i++) {
+   ring = &h->qs[i]->rx_ring;
+   for (j = 0; j < ring->desc_num; j++)
+   ring->desc[j].addr = cpu_to_le64(ring->desc_cb[j].dma);
+   }
+
+   wmb();  /* commit all data before submit */
+}
+
+/* when reinit buffer size, we should reinit page offset */
+static inline void hnae_reinit_all_ring_page_off(struct hnae_handle *h)
+{
+   int i, j;
+   struct hnae_ring *ring;
+
+   for (i = 0; i < h->q_num; i++) {
+   ring = &h->qs[i]->rx_ring;
+   for (j = 0; j < ring->desc_num; j++) {
+   ring->desc_cb[j].page_offset = 0;
+   if (ring->desc[j].addr !=
+   cpu_to_le64(ring->desc_cb[j].dma))
+   ring->desc[j].addr =
+   cpu_to_le64(ring->desc_cb[j].dma);
+   }
+   }
+
+   wmb();  /* commit all data before submit */
+}
+
 #define hnae_set_field(origin, mask, shift, val) \
do { \
(origin) &= (~(mask)); \
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index 0a9cdf0..cd7e88e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -267,8 +267,32 @@ static int hns_ae_clr_multicast(struct hnae_handle *handle)
 static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu)
 {
struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+   struct hnae_queue *q;
+   u32 rx_buf_size;
+   int i, ret;
+
+   /* when buf_size is 2048, max mtu is 6K for rx ring max bd num is 3. */
+   if (!AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver)) {
+   if (new_mtu <= BD_SIZE_2048_MAX_MTU)
+   rx_buf_size = 2048;
+   else
+   rx_buf_size = 4096;
+   } else {
+   rx_buf_size = mac_cb->dsaf_dev->buf_size;
+   }
+
+   ret = hns_mac_set_mtu(mac_cb, new_mtu, rx_buf_size);
 
-   return hns_mac_set_mtu(mac_cb, new_mtu);
+   if (!ret) {
+   /* reinit ring buf_size */
+   for (i = 0; i < handle->q_num; i++) {
+   q = handle->qs[i];
+   q->rx_ring.buf_size = rx_buf_size;
+   hns_rcb_set_rx_ring_bs(q, rx_buf_size);
+   }
+   }
+
+   return ret;
 }
 
 static void hns_ae_set_tso_stats(struct hnae_handle *handle, int enable)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index 3239d27..edf9a23 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -491,10 +491,9 @@ void hns_mac_reset(struct hns_mac_cb *mac_cb)
}
 }
 
-int hns

[PATCH V2 net-next 10/18] net: hns: Remove the redundant adding and deleting mac function

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

The functions (hns_dsaf_set_mac_mc_entry() and hns_mac_del_mac()) are
not called by any functions. They are dead code in hns. And the same
features are implemented by the patch (the id is 66355f5).

Reported-by: Weiwei Deng 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c  | 38 --
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h  |  1 -
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 81 --
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h |  2 -
 4 files changed, 122 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index edf9a23..696f2ae 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -332,44 +332,6 @@ int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
return 0;
 }
 
-/**
- *hns_mac_del_mac - delete mac address into dsaf table,can't delete the same
- *  address twice
- *@net_dev: net device
- *@vfn :   vf lan
- *@mac : mac address
- *return status
- */
-int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac)
-{
-   struct mac_entry_idx *old_mac;
-   struct dsaf_device *dsaf_dev;
-   u32 ret;
-
-   dsaf_dev = mac_cb->dsaf_dev;
-
-   if (vfn < DSAF_MAX_VM_NUM) {
-   old_mac = &mac_cb->addr_entry_idx[vfn];
-   } else {
-   dev_err(mac_cb->dev,
-   "vf queue is too large, %s mac%d queue = %#x!\n",
-   mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vfn);
-   return -EINVAL;
-   }
-
-   if (dsaf_dev) {
-   ret = hns_dsaf_del_mac_entry(dsaf_dev, old_mac->vlan_id,
-mac_cb->mac_id, old_mac->addr);
-   if (ret)
-   return ret;
-
-   if (memcmp(old_mac->addr, mac, sizeof(old_mac->addr)) == 0)
-   old_mac->valid = 0;
-   }
-
-   return 0;
-}
-
 int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn)
 {
struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
index 7f14d91..e6842c9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
@@ -436,7 +436,6 @@ int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
 int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vm, bool enable);
 void hns_mac_start(struct hns_mac_cb *mac_cb);
 void hns_mac_stop(struct hns_mac_cb *mac_cb);
-int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac);
 void hns_mac_uninit(struct dsaf_device *dsaf_dev);
 void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex);
 void hns_mac_reset(struct hns_mac_cb *mac_cb);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 90dbda7..6a069ff 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -1647,87 +1647,6 @@ int hns_dsaf_rm_mac_addr(
  mac_entry->addr);
 }
 
-/**
- * hns_dsaf_set_mac_mc_entry - set mac mc-entry
- * @dsaf_dev: dsa fabric device struct pointer
- * @mac_entry: mc-mac entry
- */
-int hns_dsaf_set_mac_mc_entry(
-   struct dsaf_device *dsaf_dev,
-   struct dsaf_drv_mac_multi_dest_entry *mac_entry)
-{
-   u16 entry_index = DSAF_INVALID_ENTRY_IDX;
-   struct dsaf_drv_tbl_tcam_key mac_key;
-   struct dsaf_tbl_tcam_mcast_cfg mac_data;
-   struct dsaf_drv_priv *priv =
-   (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
-   struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
-   struct dsaf_drv_tbl_tcam_key tmp_mac_key;
-   struct dsaf_tbl_tcam_data tcam_data;
-
-   /* mac addr check */
-   if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-   dev_err(dsaf_dev->dev, "set uc %s Mac %pM err!\n",
-   dsaf_dev->ae_dev.name, mac_entry->addr);
-   return -EINVAL;
-   }
-
-   /*config key */
-   hns_dsaf_set_mac_key(dsaf_dev, &mac_key,
-mac_entry->in_vlan_id,
-mac_entry->in_port_num, mac_entry->addr);
-
-   /* entry ie exist? */
-   entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
-   if (entry_index == DSAF_INVALID_ENTRY_IDX) {
-   /*if hasnot, find enpty entry*/
-   entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev);
-   if (entry_index == DSAF_INVALID_ENTRY_IDX) {
-   /*if hasnot empty, error*/
-   dev_err(dsaf_dev->dev,
-   "set_uc_entry failed, %s Mac 

[PATCH V2 net-next 11/18] net: hns: Remove redundant mac_get_id()

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

There is a mac_id in mac control block structure, so the callback
function mac_get_id() is useless. Here we remove this function.

Reported-by: Weiwei Deng 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c  |  8 
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h   |  2 --
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 13 -
 3 files changed, 23 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 723f3ae..035db86 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -466,13 +466,6 @@ static int hns_gmac_config_loopback(void *mac_drv, enum 
hnae_loop loop_mode,
return 0;
 }
 
-static void hns_gmac_get_id(void *mac_drv, u8 *mac_id)
-{
-   struct mac_driver *drv = (struct mac_driver *)mac_drv;
-
-   *mac_id = drv->mac_id;
-}
-
 static void hns_gmac_get_info(void *mac_drv, struct mac_info *mac_info)
 {
enum hns_gmac_duplex_mdoe duplex;
@@ -714,7 +707,6 @@ void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct 
mac_params *mac_param)
mac_drv->config_pad_and_crc = hns_gmac_config_pad_and_crc;
mac_drv->config_half_duplex = hns_gmac_set_duplex_type;
mac_drv->set_rx_ignore_pause_frames = hns_gmac_set_rx_auto_pause_frames;
-   mac_drv->mac_get_id = hns_gmac_get_id;
mac_drv->get_info = hns_gmac_get_info;
mac_drv->autoneg_stat = hns_gmac_autoneg_stat;
mac_drv->get_pause_enable = hns_gmac_get_pausefrm_cfg;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
index e6842c9..24dfba5 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
@@ -373,8 +373,6 @@ struct mac_driver {
void (*set_rx_ignore_pause_frames)(void *mac_drv, u32 enable);
/* config rx mode for promiscuous*/
void (*set_promiscuous)(void *mac_drv, u8 enable);
-   /* get mac id */
-   void (*mac_get_id)(void *mac_drv, u8 *mac_id);
void (*mac_pausefrm_cfg)(void *mac_drv, u32 rx_en, u32 tx_en);
 
void (*autoneg_stat)(void *mac_drv, u32 *enable);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
index aae830a..37a2fc3 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
@@ -300,18 +300,6 @@ static void hns_xgmac_set_tx_auto_pause_frames(void 
*mac_drv, u16 enable)
 }
 
 /**
- *hns_xgmac_get_id - get xgmac port id
- *@mac_drv: mac driver
- *@newval:xgmac max frame length
- */
-static void hns_xgmac_get_id(void *mac_drv, u8 *mac_id)
-{
-   struct mac_driver *drv = (struct mac_driver *)mac_drv;
-
-   *mac_id = drv->mac_id;
-}
-
-/**
  *hns_xgmac_config_max_frame_length - set xgmac max frame length
  *@mac_drv: mac driver
  *@newval:xgmac max frame length
@@ -833,7 +821,6 @@ void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct 
mac_params *mac_param)
mac_drv->config_half_duplex = NULL;
mac_drv->set_rx_ignore_pause_frames =
hns_xgmac_set_rx_ignore_pause_frames;
-   mac_drv->mac_get_id = hns_xgmac_get_id;
mac_drv->mac_free = hns_xgmac_free;
mac_drv->adjust_link = NULL;
mac_drv->set_tx_auto_pause_frames = hns_xgmac_set_tx_auto_pause_frames;
-- 
2.7.4




[PATCH V2 net-next 13/18] net: hns: Clean redundant code from hns_mdio.c file

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

This patch cleans the redundant code from  hns_mdio.c.

Reported-by: Ping Zhang 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns_mdio.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c 
b/drivers/net/ethernet/hisilicon/hns_mdio.c
index 501eb20..fad1c5b 100644
--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -23,17 +23,9 @@
 #include 
 #include 
 #include 
-#include 
 
 #define MDIO_DRV_NAME "Hi-HNS_MDIO"
 #define MDIO_BUS_NAME "Hisilicon MII Bus"
-#define MDIO_DRV_VERSION "1.3.0"
-#define MDIO_COPYRIGHT "Copyright(c) 2015 Huawei Corporation."
-#define MDIO_DRV_STRING MDIO_BUS_NAME
-#define MDIO_DEFAULT_DEVICE_DESCR MDIO_BUS_NAME
-
-#define MDIO_CTL_DEV_ADDR(x)   (x & 0x1f)
-#define MDIO_CTL_PORT_ADDR(x)  ((x & 0x1f) << 5)
 
 #define MDIO_TIMEOUT   100
 
@@ -64,9 +56,7 @@ struct hns_mdio_device {
 #define MDIO_CMD_DEVAD_S   0
 #define MDIO_CMD_PRTAD_M   0x1f
 #define MDIO_CMD_PRTAD_S   5
-#define MDIO_CMD_OP_M  0x3
 #define MDIO_CMD_OP_S  10
-#define MDIO_CMD_ST_M  0x3
 #define MDIO_CMD_ST_S  12
 #define MDIO_CMD_START_B   14
 
-- 
2.7.4




[PATCH V2 net-next 12/18] net: hns: Remove redundant mac table operations

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

This patch removes redundant functions used only for debugging
purposes.

Reported-by: Weiwei Deng 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 160 -
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h |  10 --
 2 files changed, 170 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 6a069ff..abd8aec 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -2008,166 +2008,6 @@ int hns_dsaf_clr_mac_mc_port(struct dsaf_device 
*dsaf_dev, u8 mac_id,
return ret;
 }
 
-/**
- * hns_dsaf_get_mac_uc_entry - get mac uc entry
- * @dsaf_dev: dsa fabric device struct pointer
- * @mac_entry: mac entry
- */
-int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev,
- struct dsaf_drv_mac_single_dest_entry *mac_entry)
-{
-   u16 entry_index = DSAF_INVALID_ENTRY_IDX;
-   struct dsaf_drv_tbl_tcam_key mac_key;
-
-   struct dsaf_tbl_tcam_ucast_cfg mac_data;
-   struct dsaf_tbl_tcam_data tcam_data;
-
-   /* check macaddr */
-   if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
-   MAC_IS_BROADCAST(mac_entry->addr)) {
-   dev_err(dsaf_dev->dev, "get_entry failed,addr %pM\n",
-   mac_entry->addr);
-   return -EINVAL;
-   }
-
-   /*config key */
-   hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id,
-mac_entry->in_port_num, mac_entry->addr);
-
-   /*check exist? */
-   entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
-   if (entry_index == DSAF_INVALID_ENTRY_IDX) {
-   /*find none, error */
-   dev_err(dsaf_dev->dev,
-   "get_uc_entry failed, %s Mac key(%#x:%#x)\n",
-   dsaf_dev->ae_dev.name,
-   mac_key.high.val, mac_key.low.val);
-   return -EINVAL;
-   }
-   dev_dbg(dsaf_dev->dev,
-   "get_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
-   dsaf_dev->ae_dev.name, mac_key.high.val,
-   mac_key.low.val, entry_index);
-
-   /* read entry */
-   hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
-
-   mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
-   mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
-
-   mac_entry->port_num = mac_data.tbl_ucast_out_port;
-
-   return 0;
-}
-
-/**
- * hns_dsaf_get_mac_mc_entry - get mac mc entry
- * @dsaf_dev: dsa fabric device struct pointer
- * @mac_entry: mac entry
- */
-int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev,
- struct dsaf_drv_mac_multi_dest_entry *mac_entry)
-{
-   u16 entry_index = DSAF_INVALID_ENTRY_IDX;
-   struct dsaf_drv_tbl_tcam_key mac_key;
-
-   struct dsaf_tbl_tcam_mcast_cfg mac_data;
-   struct dsaf_tbl_tcam_data tcam_data;
-
-   /*check mac addr */
-   if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
-   MAC_IS_BROADCAST(mac_entry->addr)) {
-   dev_err(dsaf_dev->dev, "get_entry failed,addr %pM\n",
-   mac_entry->addr);
-   return -EINVAL;
-   }
-
-   /*config key */
-   hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id,
-mac_entry->in_port_num, mac_entry->addr);
-
-   /*check exist? */
-   entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
-   if (entry_index == DSAF_INVALID_ENTRY_IDX) {
-   /* find none, error */
-   dev_err(dsaf_dev->dev,
-   "get_mac_uc_entry failed, %s Mac key(%#x:%#x)\n",
-   dsaf_dev->ae_dev.name, mac_key.high.val,
-   mac_key.low.val);
-   return -EINVAL;
-   }
-   dev_dbg(dsaf_dev->dev,
-   "get_mac_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
-   dsaf_dev->ae_dev.name, mac_key.high.val,
-   mac_key.low.val, entry_index);
-
-   /*read entry */
-   hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
-
-   mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
-   mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
-
-   mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
-   return 0;
-}
-
-/**
- * hns_dsaf_get_mac_entry_by_index - get mac entry by tab index
- * @dsaf_dev: dsa fabric device struct pointer
- * @entry_index: tab entry index
- * @mac_entry: mac entry
- */
-int hns_dsaf_get_mac_entry_by_index(
-   struct dsaf_device *dsaf_dev,
-   u16 entry_index, struct dsaf_drv_mac_multi_dest_entry *mac_entry)
-{
-   struct dsaf_drv_tbl_tcam_key mac_key;
-
-   struct dsaf_tbl_tcam_

[PATCH V2 net-next 14/18] net: hns: Optimise the code in hns_mdio_wait_ready()

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

This patch fixes the code to clear pclint warning/info.

Reported-by: Ping Zhang 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns_mdio.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c 
b/drivers/net/ethernet/hisilicon/hns_mdio.c
index fad1c5b..e5221d9 100644
--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -175,18 +175,20 @@ static int mdio_sc_cfg_reg_write(struct hns_mdio_device 
*mdio_dev,
 static int hns_mdio_wait_ready(struct mii_bus *bus)
 {
struct hns_mdio_device *mdio_dev = bus->priv;
+   u32 cmd_reg_value;
int i;
-   u32 cmd_reg_value = 1;
 
/* waitting for MDIO_COMMAND_REG 's mdio_start==0 */
/* after that can do read or write*/
-   for (i = 0; cmd_reg_value; i++) {
+   for (i = 0; i < MDIO_TIMEOUT; i++) {
cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,
 MDIO_COMMAND_REG,
 MDIO_CMD_START_B);
-   if (i == MDIO_TIMEOUT)
-   return -ETIMEDOUT;
+   if (!cmd_reg_value)
+   break;
}
+   if ((i == MDIO_TIMEOUT) && cmd_reg_value)
+   return -ETIMEDOUT;
 
return 0;
 }
-- 
2.7.4




[PATCH V2 net-next 18/18] net: hns: Some checkpatch.pl script & warning fixes

2017-03-31 Thread Salil Mehta
This patch fixes some checkpatch.pl script caught errors and
warnings during the compilation time.

Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hnae.h  |  1 -
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 11 +--
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h |  2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c  |  1 -
 drivers/net/ethernet/hisilicon/hns/hns_enet.c  |  9 +
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c   |  1 -
 6 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h 
b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 0943138..04211ac 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -103,7 +103,6 @@ enum hnae_led_state {
 #define HNS_RX_FLAG_L4ID_TCP 0x1
 #define HNS_RX_FLAG_L4ID_SCTP 0x3
 
-
 #define HNS_TXD_ASID_S 0
 #define HNS_TXD_ASID_M (0xff << HNS_TXD_ASID_S)
 #define HNS_TXD_BUFNUM_S 8
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 035db86..74bd260 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -86,12 +86,11 @@ static void hns_gmac_disable(void *mac_drv, enum 
mac_commom_mode mode)
dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 0);
 }
 
-/**
-*hns_gmac_get_en - get port enable
-*@mac_drv:mac device
-*@rx:rx enable
-*@tx:tx enable
-*/
+/* hns_gmac_get_en - get port enable
+ * @mac_drv:mac device
+ * @rx:rx enable
+ * @tx:tx enable
+ */
 static void hns_gmac_get_en(void *mac_drv, u32 *rx, u32 *tx)
 {
struct mac_driver *drv = (struct mac_driver *)mac_drv;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index 4db02e2..4507e82 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -68,7 +68,7 @@ enum dsaf_roce_qos_sl {
 };
 
 #define DSAF_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset
-#define HNS_DSAF_IS_DEBUG(dev) (dev->dsaf_mode == DSAF_MODE_DISABLE_SP)
+#define HNS_DSAF_IS_DEBUG(dev) ((dev)->dsaf_mode == DSAF_MODE_DISABLE_SP)
 
 enum hal_dsaf_mode {
HRD_DSAF_NO_DSAF_MODE   = 0x0,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index 9b66057..c20a0f4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -471,7 +471,6 @@ static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb 
*ring_pair_cb)
 static int hns_rcb_get_port_in_comm(
struct rcb_common_cb *rcb_common, int ring_idx)
 {
-
return ring_idx / (rcb_common->max_q_per_vf * rcb_common->max_vfn);
 }
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c 
b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 3634366..837f119 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -512,7 +512,8 @@ static void hns_nic_reuse_page(struct sk_buff *skb, int i,
int last_offset;
bool twobufs;
 
-   twobufs = ((PAGE_SIZE < 8192) && hnae_buf_size(ring) == 
HNS_BUFFER_SIZE_2048);
+   twobufs = ((PAGE_SIZE < 8192) && hnae_buf_size(ring)
+   == HNS_BUFFER_SIZE_2048);
 
desc = &ring->desc[ring->next_to_clean];
size = le16_to_cpu(desc->rx.size);
@@ -922,8 +923,8 @@ static int is_valid_clean_head(struct hnae_ring *ring, int 
h)
 
 /* netif_tx_lock will turn down the performance, set only when necessary */
 #ifdef CONFIG_NET_POLL_CONTROLLER
-#define NETIF_TX_LOCK(ring) spin_lock(&ring->lock)
-#define NETIF_TX_UNLOCK(ring) spin_unlock(&ring->lock)
+#define NETIF_TX_LOCK(ring) spin_lock(&(ring)->lock)
+#define NETIF_TX_UNLOCK(ring) spin_unlock(&(ring)->lock)
 #else
 #define NETIF_TX_LOCK(ring)
 #define NETIF_TX_UNLOCK(ring)
@@ -2012,7 +2013,7 @@ static void hns_nic_reset_subtask(struct hns_nic_priv 
*priv)
 static void hns_nic_service_event_complete(struct hns_nic_priv *priv)
 {
WARN_ON(!test_bit(NIC_STATE_SERVICE_SCHED, &priv->state));
-
+   /* make sure to commit the things */
smp_mb__before_atomic();
clear_bit(NIC_STATE_SERVICE_SCHED, &priv->state);
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 36f33bd..b8fab14 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -1242,7 +1242,6 @@ hns_set_rss(struct net_device *netdev, const u32 *indir, 
const u8 *key,
 {
struct hns_nic_priv *priv = netdev_priv(netdev);
struct hnae_ae_ops *ops;
-   int ret;
 
if (AE_IS_VER1(priv->enet_ver)) {
netdev_err(netdev,
-- 
2.7.4




[PATCH V2 net-next 17/18] net: hns: Avoid Hip06 chip TX packet line bug

2017-03-31 Thread Salil Mehta
From: lipeng 

There is a bug on Hip06 that tx ring interrupts packets count will be
clear when drivers send data to tx ring, so that the tx packets count
will never upgrade to packets line, and cause the interrupts engendered
was delayed.
Sometimes, it will cause sending performance lower than expected.

To fix this bug, we set tx ring interrupts packets line to 1 forever,
to avoid count clear. And set the gap time to 20us, to solve the problem
that too many interrupts engendered when packets line is 1.

This patch could advance the send performance on ARM  from 6.6G to 9.37G
when an iperf send thread on ARM and an iperf send thread on X86 for XGE.

Signed-off-by: lipeng 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hnae.c |   5 ++
 drivers/net/ethernet/hisilicon/hns/hnae.h |   6 +-
 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c |  78 -
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 101 --
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h |  23 -
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h |   2 +-
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c  |  24 +++--
 7 files changed, 169 insertions(+), 70 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c 
b/drivers/net/ethernet/hisilicon/hns/hnae.c
index 513c257..8950b74 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.c
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -57,10 +57,15 @@ static int hnae_alloc_buffer(struct hnae_ring *ring, struct 
hnae_desc_cb *cb)
 
 static void hnae_free_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
 {
+   if (unlikely(!cb->priv))
+   return;
+
if (cb->type == DESC_TYPE_SKB)
dev_kfree_skb_any((struct sk_buff *)cb->priv);
else if (unlikely(is_rx_ring(ring)))
put_page((struct page *)cb->priv);
+
+   cb->priv = NULL;
 }
 
 static int hnae_map_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb)
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h 
b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 859c536..0943138 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -488,11 +488,11 @@ struct hnae_ae_ops {
  u32 auto_neg, u32 rx_en, u32 tx_en);
void (*get_coalesce_usecs)(struct hnae_handle *handle,
   u32 *tx_usecs, u32 *rx_usecs);
-   void (*get_rx_max_coalesced_frames)(struct hnae_handle *handle,
-   u32 *tx_frames, u32 *rx_frames);
+   void (*get_max_coalesced_frames)(struct hnae_handle *handle,
+u32 *tx_frames, u32 *rx_frames);
int (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout);
int (*set_coalesce_frames)(struct hnae_handle *handle,
-  u32 coalesce_frames);
+  u32 tx_frames, u32 rx_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,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index f0142e5..ff864a1 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -487,15 +487,21 @@ static void hns_ae_get_coalesce_usecs(struct hnae_handle 
*handle,
   ring_pair->port_id_in_comm);
 }
 
-static void hns_ae_get_rx_max_coalesced_frames(struct hnae_handle *handle,
-  u32 *tx_frames, u32 *rx_frames)
+static void hns_ae_get_max_coalesced_frames(struct hnae_handle *handle,
+   u32 *tx_frames, u32 *rx_frames)
 {
struct ring_pair_cb *ring_pair =
container_of(handle->qs[0], struct ring_pair_cb, q);
+   struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
 
-   *tx_frames = hns_rcb_get_coalesced_frames(ring_pair->rcb_common,
- ring_pair->port_id_in_comm);
-   *rx_frames = hns_rcb_get_coalesced_frames(ring_pair->rcb_common,
+   if (AE_IS_VER1(dsaf_dev->dsaf_ver) ||
+   handle->port_type == HNAE_PORT_DEBUG)
+   *tx_frames = hns_rcb_get_rx_coalesced_frames(
+   ring_pair->rcb_common, ring_pair->port_id_in_comm);
+   else
+   *tx_frames = hns_rcb_get_tx_coalesced_frames(
+   ring_pair->rcb_common, ring_pair->port_id_in_comm);
+   *rx_frames = hns_rcb_get_rx_coalesced_frames(ring_pair->rcb_common,
  ring_pair->port_id_in_comm);
 }
 
@@ -509,15 +515,34 @@ static int hns_ae_set_coalesce_usecs(struct hnae_

[PATCH V2 net-next 16/18] net: hns: Adjust the SBM module buffer threshold

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

HNS needs SMB Buffers to store at least two packets after sending
pause frame because of the link delay. The MTU of HNS is 9728. As
the processor user manual described, the SBM buffer threshold should
be modified.

Reported-by: Ping Zhang 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 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 abd8aec..d07b4fe 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -510,10 +510,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, 48);
+  DSAFV2_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 55);
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, 80);
+  DSAFV2_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 110);
dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
 
/* for no enable pfc mode */
@@ -521,10 +521,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_CFG4_SET_BUF_NUM_NO_PFC_M,
-  DSAFV2_SBM_CFG4_SET_BUF_NUM_NO_PFC_S, 192);
+  DSAFV2_SBM_CFG4_SET_BUF_NUM_NO_PFC_S, 128);
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, 240);
+  DSAFV2_SBM_CFG4_RESET_BUF_NUM_NO_PFC_S, 192);
dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg);
}
 
-- 
2.7.4




[PATCH V2 net-next 15/18] net: hns: Simplify the exception sequence in hns_ppe_init()

2017-03-31 Thread Salil Mehta
From: Kejian Yan 

We need to free all ppe submodule if it fails to initialize ppe by
any fault, so this patch will free all ppe resource before
hns_ppe_init() returns exception situation

Reported-by: JinchuanTian 
Signed-off-by: Kejian Yan 
Reviewed-by: Salil Mehta 
Signed-off-by: Salil Mehta 
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c 
b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
index 6ea8722..eba406b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
@@ -496,17 +496,17 @@ void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 
*data)
  */
 int hns_ppe_init(struct dsaf_device *dsaf_dev)
 {
-   int i, k;
int ret;
+   int i;
 
for (i = 0; i < HNS_PPE_COM_NUM; i++) {
ret = hns_ppe_common_get_cfg(dsaf_dev, i);
if (ret)
-   goto get_ppe_cfg_fail;
+   goto get_cfg_fail;
 
ret = hns_rcb_common_get_cfg(dsaf_dev, i);
if (ret)
-   goto get_rcb_cfg_fail;
+   goto get_cfg_fail;
 
hns_ppe_get_cfg(dsaf_dev->ppe_common[i]);
 
@@ -518,13 +518,12 @@ int hns_ppe_init(struct dsaf_device *dsaf_dev)
 
return 0;
 
-get_rcb_cfg_fail:
-   hns_ppe_common_free_cfg(dsaf_dev, i);
-get_ppe_cfg_fail:
-   for (k = i - 1; k >= 0; k--) {
-   hns_rcb_common_free_cfg(dsaf_dev, k);
-   hns_ppe_common_free_cfg(dsaf_dev, k);
+get_cfg_fail:
+   for (i = 0; i < HNS_PPE_COM_NUM; i++) {
+   hns_rcb_common_free_cfg(dsaf_dev, i);
+   hns_ppe_common_free_cfg(dsaf_dev, i);
}
+
return ret;
 }
 
-- 
2.7.4




Re: stmmac CBS configuration for TX AVB queue

2017-03-31 Thread Joao Pinto
Às 10:59 AM de 3/31/2017, Niklas Cassel escreveu:
> Hello Joao
> 
> 
> I was looking at
> 
> commit 19d9187317979cf0c25f67017d2676149abc46b2
> Author: Joao Pinto 
> Date:   Fri Mar 10 18:24:59 2017 +
> 
> net: stmmac: configuration of CBS in case of a TX AVB queue
> 
> This patch adds the configuration of the AVB Credit-Based Shaper.
> 
> 
> 
> It looks to me that we loop through all txqueues (including 0)
> 
> static void stmmac_configure_cbs(struct stmmac_priv *priv)
> ...
> for (queue = 0; queue < tx_queues_count; queue++) {
> ...
> priv->hw->mac->config_cbs(...)
> 
> 
> then in
> 
> static void dwmac4_config_cbs(..)
> ...
> value = readl(ioaddr + MTL_ETSX_CTRL_BASE_ADDR(queue));
> 
> 
> The MTL_ETSX_CTRL_BASE_ADDR register only exists for txqueues != 0.
> (Since txqueue0 will always handle legacy traffic.)
> 
> I think that we need to make sure that we do not enter
> config_cbs() for txqueue0, even if the user's device tree
> has txqueue0 set to AVB, since MTL_ETSX_CTRL_BASE_ADDR
> will evaluate to a non-existing register for txqueue0.
> 
> Perhaps also clarify how we expect the user to configure
> his device tree for txqueue0 when using AVB in:
> Documentation/devicetree/bindings/net/stmmac.txt
> 
> 
> Best regards,
> Niklas
> 

You are right, we did not add AVB capabilities to default/Q0, this way we
guarantee 75% bandwidth for AVB. I will send a patch soon to fix this.

Thanks,
Joao


[PATCH net 4/5] l2tp: hold session while sending creation notifications

2017-03-31 Thread Guillaume Nault
l2tp_session_find() doesn't take any reference on the returned session.
Therefore, the session may disappear while sending the notification.

Use l2tp_session_get() instead and decrement session's refcount once
the notification is sent.

Fixes: 33f72e6f0c67 ("l2tp : multicast notification to the registered 
listeners")
Signed-off-by: Guillaume Nault 
---
 net/l2tp/l2tp_netlink.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 3620fba31786..f1b68effb077 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -642,10 +642,12 @@ static int l2tp_nl_cmd_session_create(struct sk_buff 
*skb, struct genl_info *inf
session_id, peer_session_id, &cfg);
 
if (ret >= 0) {
-   session = l2tp_session_find(net, tunnel, session_id);
-   if (session)
+   session = l2tp_session_get(net, tunnel, session_id, false);
+   if (session) {
ret = l2tp_session_notify(&l2tp_nl_family, info, 
session,
  L2TP_CMD_SESSION_CREATE);
+   l2tp_session_dec_refcount(session);
+   }
}
 
 out:
-- 
2.11.0



[PATCH net 3/5] l2tp: fix duplicate session creation

2017-03-31 Thread Guillaume Nault
l2tp_session_create() relies on its caller for checking for duplicate
sessions. This is racy since a session can be concurrently inserted
after the caller's verification.

Fix this by letting l2tp_session_create() verify sessions uniqueness
upon insertion. Callers need to be adapted to check for
l2tp_session_create()'s return code instead of calling
l2tp_session_find().

pppol2tp_connect() is a bit special because it has to work on existing
sessions (if they're not connected) or to create a new session if none
is found. When acting on a preexisting session, a reference must be
held or it could go away on us. So we have to use l2tp_session_get()
instead of l2tp_session_find() and drop the reference before exiting.

Fixes: d9e31d17ceba ("l2tp: Add L2TP ethernet pseudowire support")
Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp 
parts")
Signed-off-by: Guillaume Nault 
---
 net/l2tp/l2tp_core.c | 70 +++-
 net/l2tp/l2tp_eth.c  | 10 ++--
 net/l2tp/l2tp_ppp.c  | 60 ++--
 3 files changed, 84 insertions(+), 56 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 8a067536d15c..46b450a1bc21 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -374,6 +374,48 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct 
net *net, char *ifname)
 }
 EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname);
 
+static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel,
+ struct l2tp_session *session)
+{
+   struct l2tp_session *session_walk;
+   struct hlist_head *g_head;
+   struct hlist_head *head;
+   struct l2tp_net *pn;
+
+   head = l2tp_session_id_hash(tunnel, session->session_id);
+
+   write_lock_bh(&tunnel->hlist_lock);
+   hlist_for_each_entry(session_walk, head, hlist)
+   if (session_walk->session_id == session->session_id)
+   goto exist;
+
+   if (tunnel->version == L2TP_HDR_VER_3) {
+   pn = l2tp_pernet(tunnel->l2tp_net);
+   g_head = l2tp_session_id_hash_2(l2tp_pernet(tunnel->l2tp_net),
+   session->session_id);
+
+   spin_lock_bh(&pn->l2tp_session_hlist_lock);
+   hlist_for_each_entry(session_walk, g_head, global_hlist)
+   if (session_walk->session_id == session->session_id)
+   goto exist_glob;
+
+   hlist_add_head_rcu(&session->global_hlist, g_head);
+   spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+   }
+
+   hlist_add_head(&session->hlist, head);
+   write_unlock_bh(&tunnel->hlist_lock);
+
+   return 0;
+
+exist_glob:
+   spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+exist:
+   write_unlock_bh(&tunnel->hlist_lock);
+
+   return -EEXIST;
+}
+
 /* Lookup a tunnel by id
  */
 struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id)
@@ -1785,6 +1827,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_set_header_len);
 struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel 
*tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
 {
struct l2tp_session *session;
+   int err;
 
session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL);
if (session != NULL) {
@@ -1840,6 +1883,13 @@ struct l2tp_session *l2tp_session_create(int priv_size, 
struct l2tp_tunnel *tunn
 
l2tp_session_set_header_len(session, tunnel->version);
 
+   err = l2tp_session_add_to_tunnel(tunnel, session);
+   if (err) {
+   kfree(session);
+
+   return ERR_PTR(err);
+   }
+
/* Bump the reference count. The session context is deleted
 * only when this drops to zero.
 */
@@ -1849,28 +1899,14 @@ struct l2tp_session *l2tp_session_create(int priv_size, 
struct l2tp_tunnel *tunn
/* Ensure tunnel socket isn't deleted */
sock_hold(tunnel->sock);
 
-   /* Add session to the tunnel's hash list */
-   write_lock_bh(&tunnel->hlist_lock);
-   hlist_add_head(&session->hlist,
-  l2tp_session_id_hash(tunnel, session_id));
-   write_unlock_bh(&tunnel->hlist_lock);
-
-   /* And to the global session list if L2TPv3 */
-   if (tunnel->version != L2TP_HDR_VER_2) {
-   struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
-
-   spin_lock_bh(&pn->l2tp_session_hlist_lock);
-   hlist_add_head_rcu(&session->global_hlist,
-  l2tp_session_id_hash_2(pn, 
session_id));
-   spin_unlock_bh(&pn->l2tp_session_hlist_lock);
-   }
-
/* Ignore management

[PATCH net 2/5] l2tp: ensure session can't get removed during pppol2tp_session_ioctl()

2017-03-31 Thread Guillaume Nault
Holding a reference on session is required before calling
pppol2tp_session_ioctl(). The session could get freed while processing the
ioctl otherwise. Since pppol2tp_session_ioctl() uses the session's socket,
we also need to take a reference on it in l2tp_session_get().

Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp 
parts")
Signed-off-by: Guillaume Nault 
---
 net/l2tp/l2tp_ppp.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 123b6a2411a0..827e55c41ba2 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1141,11 +1141,18 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel 
*tunnel,
if (stats.session_id != 0) {
/* resend to session ioctl handler */
struct l2tp_session *session =
-   l2tp_session_find(sock_net(sk), tunnel, 
stats.session_id);
-   if (session != NULL)
-   err = pppol2tp_session_ioctl(session, cmd, arg);
-   else
+   l2tp_session_get(sock_net(sk), tunnel,
+stats.session_id, true);
+
+   if (session) {
+   err = pppol2tp_session_ioctl(session, cmd,
+arg);
+   if (session->deref)
+   session->deref(session);
+   l2tp_session_dec_refcount(session);
+   } else {
err = -EBADR;
+   }
break;
}
 #ifdef CONFIG_XFRM
-- 
2.11.0



[PATCH net 1/5] l2tp: fix race in l2tp_recv_common()

2017-03-31 Thread Guillaume Nault
Taking a reference on sessions in l2tp_recv_common() is racy; this
has to be done by the callers.

To this end, a new function is required (l2tp_session_get()) to
atomically lookup a session and take a reference on it. Callers then
have to manually drop this reference.

Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp 
parts")
Signed-off-by: Guillaume Nault 
---
 net/l2tp/l2tp_core.c | 73 ++--
 net/l2tp/l2tp_core.h |  3 +++
 net/l2tp/l2tp_ip.c   | 17 
 net/l2tp/l2tp_ip6.c  | 18 +
 4 files changed, 88 insertions(+), 23 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 8adab6335ced..8a067536d15c 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -278,6 +278,55 @@ struct l2tp_session *l2tp_session_find(struct net *net, 
struct l2tp_tunnel *tunn
 }
 EXPORT_SYMBOL_GPL(l2tp_session_find);
 
+/* Like l2tp_session_find() but takes a reference on the returned session.
+ * Optionally calls session->ref() too if do_ref is true.
+ */
+struct l2tp_session *l2tp_session_get(struct net *net,
+ struct l2tp_tunnel *tunnel,
+ u32 session_id, bool do_ref)
+{
+   struct hlist_head *session_list;
+   struct l2tp_session *session;
+
+   if (!tunnel) {
+   struct l2tp_net *pn = l2tp_pernet(net);
+
+   session_list = l2tp_session_id_hash_2(pn, session_id);
+
+   rcu_read_lock_bh();
+   hlist_for_each_entry_rcu(session, session_list, global_hlist) {
+   if (session->session_id == session_id) {
+   l2tp_session_inc_refcount(session);
+   if (do_ref && session->ref)
+   session->ref(session);
+   rcu_read_unlock_bh();
+
+   return session;
+   }
+   }
+   rcu_read_unlock_bh();
+
+   return NULL;
+   }
+
+   session_list = l2tp_session_id_hash(tunnel, session_id);
+   read_lock_bh(&tunnel->hlist_lock);
+   hlist_for_each_entry(session, session_list, hlist) {
+   if (session->session_id == session_id) {
+   l2tp_session_inc_refcount(session);
+   if (do_ref && session->ref)
+   session->ref(session);
+   read_unlock_bh(&tunnel->hlist_lock);
+
+   return session;
+   }
+   }
+   read_unlock_bh(&tunnel->hlist_lock);
+
+   return NULL;
+}
+EXPORT_SYMBOL_GPL(l2tp_session_get);
+
 struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
 {
int hash;
@@ -633,6 +682,9 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, 
struct sk_buff *skb)
  * a data (not control) frame before coming here. Fields up to the
  * session-id have already been parsed and ptr points to the data
  * after the session-id.
+ *
+ * session->ref() must have been called prior to l2tp_recv_common().
+ * session->deref() will be called automatically after skb is processed.
  */
 void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
  unsigned char *ptr, unsigned char *optr, u16 hdrflags,
@@ -642,14 +694,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct 
sk_buff *skb,
int offset;
u32 ns, nr;
 
-   /* The ref count is increased since we now hold a pointer to
-* the session. Take care to decrement the refcnt when exiting
-* this function from now on...
-*/
-   l2tp_session_inc_refcount(session);
-   if (session->ref)
-   (*session->ref)(session);
-
/* Parse and check optional cookie */
if (session->peer_cookie_len > 0) {
if (memcmp(ptr, &session->peer_cookie[0], 
session->peer_cookie_len)) {
@@ -802,8 +846,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct 
sk_buff *skb,
/* Try to dequeue as many skbs from reorder_q as we can. */
l2tp_recv_dequeue(session);
 
-   l2tp_session_dec_refcount(session);
-
return;
 
 discard:
@@ -812,8 +854,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct 
sk_buff *skb,
 
if (session->deref)
(*session->deref)(session);
-
-   l2tp_session_dec_refcount(session);
 }
 EXPORT_SYMBOL(l2tp_recv_common);
 
@@ -920,8 +960,14 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, 
struct sk_buff *skb,
}
 
/* Find the session context */
-   session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id);
+   session = l2tp_session_get(tunnel->l2tp_net, tunnel, session_id, true);
if (!session || !session->recv_skb) {
+   if (session) {
+   if (session->deref)
+   

[PATCH net 5/5] l2tp: take a reference on sessions used in genetlink handlers

2017-03-31 Thread Guillaume Nault
Callers of l2tp_nl_session_find() need to hold a reference on the
returned session since there's no guarantee that it isn't going to
disappear from under them.

Relying on the fact that no l2tp netlink message may be processed
concurrently isn't enough: sessions can be deleted by other means
(e.g. by closing the PPPOL2TP socket of a ppp pseudowire).

l2tp_nl_cmd_session_delete() is a bit special: it runs a callback
function that may require a previous call to session->ref(). In
particular, for ppp pseudowires, the callback is l2tp_session_delete(),
which then calls pppol2tp_session_close() and dereferences the PPPOL2TP
socket. The socket might already be gone at the moment
l2tp_session_delete() calls session->ref(), so we need to take a
reference during the session lookup. So we need to pass the do_ref
variable down to l2tp_session_get() and l2tp_session_get_by_ifname().

Since all callers have to be updated, l2tp_session_find_by_ifname() and
l2tp_nl_session_find() are renamed to reflect their new behaviour.

Fixes: 33f72e6f0c67 ("l2tp : multicast notification to the registered 
listeners")
Signed-off-by: Guillaume Nault 
---
 net/l2tp/l2tp_core.c|  9 +++--
 net/l2tp/l2tp_core.h|  3 ++-
 net/l2tp/l2tp_netlink.c | 39 ++-
 3 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 46b450a1bc21..e927422d8c58 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -352,7 +352,8 @@ EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
 /* Lookup a session by interface name.
  * This is very inefficient but is only used by management interfaces.
  */
-struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname)
+struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname,
+   bool do_ref)
 {
struct l2tp_net *pn = l2tp_pernet(net);
int hash;
@@ -362,7 +363,11 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct 
net *net, char *ifname)
for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
hlist_for_each_entry_rcu(session, 
&pn->l2tp_session_hlist[hash], global_hlist) {
if (!strcmp(session->ifname, ifname)) {
+   l2tp_session_inc_refcount(session);
+   if (do_ref && session->ref)
+   session->ref(session);
rcu_read_unlock_bh();
+
return session;
}
}
@@ -372,7 +377,7 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct net 
*net, char *ifname)
 
return NULL;
 }
-EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname);
+EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname);
 
 static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel,
  struct l2tp_session *session)
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 4544e81a3d27..3b9b704a84e4 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -237,7 +237,8 @@ struct l2tp_session *l2tp_session_find(struct net *net,
   struct l2tp_tunnel *tunnel,
   u32 session_id);
 struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int 
nth);
-struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char 
*ifname);
+struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname,
+   bool do_ref);
 struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
 struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
 
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index f1b68effb077..93e317377c66 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -48,7 +48,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 
portid, u32 seq,
 /* Accessed under genl lock */
 static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
 
-static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info)
+static struct l2tp_session *l2tp_nl_session_get(struct genl_info *info,
+   bool do_ref)
 {
u32 tunnel_id;
u32 session_id;
@@ -59,14 +60,15 @@ static struct l2tp_session *l2tp_nl_session_find(struct 
genl_info *info)
 
if (info->attrs[L2TP_ATTR_IFNAME]) {
ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
-   session = l2tp_session_find_by_ifname(net, ifname);
+   session = l2tp_session_get_by_ifname(net, ifname, do_ref);
} else if ((info->attrs[L2TP_ATTR_SESSION_ID]) &&
   (info->attrs[L2TP_ATTR_CONN_ID])) {
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
session_id = nla_get_u32(info->attrs[L2TP

[PATCH net 0/5] l2tp: fix usage of l2tp_session_find()

2017-03-31 Thread Guillaume Nault
l2tp_session_find() doesn't take a reference on the session returned to
its caller. Virtually all l2tp_session_find() users are racy, either
because the session can disappear from under them or because they take
a reference too late. This leads to bugs like 'use after free' or
failure to notice duplicate session creations.

In some cases, taking a reference on the session is not enough. The
special callbacks .ref() and .deref() also have to be called in cases
where the PPP pseudo-wire uses the socket associated with the session.
Therefore, when looking up a session, we also have to pass a flag
indicating if the .ref() callback has to be called.

In the future, we probably could drop the .ref() and .deref() callbacks
entirely by protecting the .sock field of struct pppol2tp_session with
RCU, thus allowing it to be freed and set to NULL even if the L2TP
session is still alive.

Guillaume Nault (5):
  l2tp: fix race in l2tp_recv_common()
  l2tp: ensure session can't get removed during pppol2tp_session_ioctl()
  l2tp: fix duplicate session creation
  l2tp: hold session while sending creation notifications
  l2tp: take a reference on sessions used in genetlink handlers

 net/l2tp/l2tp_core.c| 152 ++--
 net/l2tp/l2tp_core.h|   6 +-
 net/l2tp/l2tp_eth.c |  10 +---
 net/l2tp/l2tp_ip.c  |  17 --
 net/l2tp/l2tp_ip6.c |  18 --
 net/l2tp/l2tp_netlink.c |  45 +-
 net/l2tp/l2tp_ppp.c |  75 +---
 7 files changed, 222 insertions(+), 101 deletions(-)

-- 
2.11.0



Re: [PATCH] [net-next] stmmac: use netif_set_real_num_{rx,tx}_queues

2017-03-31 Thread Joao Pinto
Às 11:14 AM de 3/31/2017, Joao Pinto escreveu:
> Às 6:48 PM de 3/30/2017, David Miller escreveu:
>> From: Thierry Reding 
>> Date: Thu, 30 Mar 2017 16:34:36 +0200
>>
>>> On Thu, Mar 30, 2017 at 09:45:36AM +0200, Corentin Labbe wrote:
 On Tue, Mar 28, 2017 at 06:01:05PM -0700, David Miller wrote:
> From: Arnd Bergmann 
> Date: Tue, 28 Mar 2017 11:48:21 +0200
>
>> A driver must not access the two fields directly but should instead use
>> the helper functions to set the values and keep a consistent internal
>> state:
>>
>> ethernet/stmicro/stmmac/stmmac_main.c: In function 'stmmac_dvr_probe':
>> ethernet/stmicro/stmmac/stmmac_main.c:4083:8: error: 'struct net_device' 
>> has no member named 'real_num_rx_queues'; did you mean 
>> 'real_num_tx_queues'?
>>
>> Fixes: a8f5102af2a7 ("net: stmmac: TX and RX queue priority 
>> configuration")
>> Signed-off-by: Arnd Bergmann 
>
> Applied.

 This break my revert patch. (since it patch ("net: stmmac: enable multiple 
 buffers").
 Since dwmac-sunxi is still broken, what can I do ? send two revert patch ? 
 or adapt the reverting patch.
>>>
>>> Have you tried if the kcalloc() patch I sent on Tuesday fixes things the
>>> issues introduced by the multiple buffers patch? Niklas reported that it
>>> restores functionality on his setup.
>>
>> I think he said yesterday that he did indeed test all of your patches and it
>> did not fix things for him.
>>
>> http://marc.info/?l=linux-kernel&m=149076922813085&w=2
>>
>> I am going to revert the enable multiple buffers commit, and I would ask that
>> all involved parties work together in the background to resolve all of this.

@David: Could you please create a branch in your git tree for us to work on it
until the multiple buffers get stable for everyone? This way the patches could
circulate in the mailing-list with a different target, like stmmac-next or 
similar.

What do you think?

Joao

>>
>> Thank you.
>>
> 
> @David: Agreed.
> 
> @Corentin: Please check if the DMA Engine is well configured and if the dma
> rx/tx has started. This is done by dumping the DMA Registers.
> Please also check the MAC related registers and dump them in order to have a
> clear picture if the IP is being well configured.
> This is critial to analise what's hapenning in your setup.
> 
> Joao
> 



Re: [PATCH] [net-next] stmmac: use netif_set_real_num_{rx,tx}_queues

2017-03-31 Thread Joao Pinto
Às 6:48 PM de 3/30/2017, David Miller escreveu:
> From: Thierry Reding 
> Date: Thu, 30 Mar 2017 16:34:36 +0200
> 
>> On Thu, Mar 30, 2017 at 09:45:36AM +0200, Corentin Labbe wrote:
>>> On Tue, Mar 28, 2017 at 06:01:05PM -0700, David Miller wrote:
 From: Arnd Bergmann 
 Date: Tue, 28 Mar 2017 11:48:21 +0200

> A driver must not access the two fields directly but should instead use
> the helper functions to set the values and keep a consistent internal
> state:
>
> ethernet/stmicro/stmmac/stmmac_main.c: In function 'stmmac_dvr_probe':
> ethernet/stmicro/stmmac/stmmac_main.c:4083:8: error: 'struct net_device' 
> has no member named 'real_num_rx_queues'; did you mean 
> 'real_num_tx_queues'?
>
> Fixes: a8f5102af2a7 ("net: stmmac: TX and RX queue priority 
> configuration")
> Signed-off-by: Arnd Bergmann 

 Applied.
>>>
>>> This break my revert patch. (since it patch ("net: stmmac: enable multiple 
>>> buffers").
>>> Since dwmac-sunxi is still broken, what can I do ? send two revert patch ? 
>>> or adapt the reverting patch.
>>
>> Have you tried if the kcalloc() patch I sent on Tuesday fixes things the
>> issues introduced by the multiple buffers patch? Niklas reported that it
>> restores functionality on his setup.
> 
> I think he said yesterday that he did indeed test all of your patches and it
> did not fix things for him.
> 
> http://marc.info/?l=linux-kernel&m=149076922813085&w=2
> 
> I am going to revert the enable multiple buffers commit, and I would ask that
> all involved parties work together in the background to resolve all of this.
> 
> Thank you.
> 

@David: Agreed.

@Corentin: Please check if the DMA Engine is well configured and if the dma
rx/tx has started. This is done by dumping the DMA Registers.
Please also check the MAC related registers and dump them in order to have a
clear picture if the IP is being well configured.
This is critial to analise what's hapenning in your setup.

Joao


[PATCH net-next] sctp: add SCTP_PR_STREAM_STATUS sockopt for prsctp

2017-03-31 Thread Xin Long
Before when implementing sctp prsctp, SCTP_PR_STREAM_STATUS wasn't
added, as it needs to save abandoned_(un)sent for every stream.

After sctp stream reconf is added in sctp, assoc has structure
sctp_stream_out to save per stream info.

This patch is to add SCTP_PR_STREAM_STATUS by putting the prsctp
per stream statistics into sctp_stream_out.

Signed-off-by: Xin Long 
---
 include/net/sctp/structs.h |  2 ++
 include/uapi/linux/sctp.h  |  1 +
 net/sctp/chunk.c   | 14 +--
 net/sctp/outqueue.c| 10 
 net/sctp/socket.c  | 59 ++
 5 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 592dece..3e61a54 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1315,6 +1315,8 @@ struct sctp_inithdr_host {
 struct sctp_stream_out {
__u16   ssn;
__u8state;
+   __u64   abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
+   __u64   abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
 };
 
 struct sctp_stream_in {
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 7212870..ced9d8b 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -115,6 +115,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_PR_SUPPORTED  113
 #define SCTP_DEFAULT_PRINFO114
 #define SCTP_PR_ASSOC_STATUS   115
+#define SCTP_PR_STREAM_STATUS  116
 #define SCTP_RECONFIG_SUPPORTED117
 #define SCTP_ENABLE_STREAM_RESET   118
 #define SCTP_RESET_STREAMS 119
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index e3621cb..697721a 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -306,14 +306,24 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
 
if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
time_after(jiffies, chunk->msg->expires_at)) {
-   if (chunk->sent_count)
+   struct sctp_stream_out *streamout =
+   &chunk->asoc->stream->out[chunk->sinfo.sinfo_stream];
+
+   if (chunk->sent_count) {
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
-   else
+   streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
+   } else {
chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
+   streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
+   }
return 1;
} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
   chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
+   struct sctp_stream_out *streamout =
+   &chunk->asoc->stream->out[chunk->sinfo.sinfo_stream];
+
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
+   streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
return 1;
} else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
   chunk->msg->expires_at &&
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 025ccff..3f78d7f 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -353,6 +353,8 @@ static int sctp_prsctp_prune_sent(struct sctp_association 
*asoc,
struct sctp_chunk *chk, *temp;
 
list_for_each_entry_safe(chk, temp, queue, transmitted_list) {
+   struct sctp_stream_out *streamout;
+
if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
continue;
@@ -361,8 +363,10 @@ static int sctp_prsctp_prune_sent(struct sctp_association 
*asoc,
sctp_insert_list(&asoc->outqueue.abandoned,
 &chk->transmitted_list);
 
+   streamout = &asoc->stream->out[chk->sinfo.sinfo_stream];
asoc->sent_cnt_removable--;
asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
+   streamout->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
 
if (!chk->tsn_gap_acked) {
if (chk->transport)
@@ -396,6 +400,12 @@ static int sctp_prsctp_prune_unsent(struct 
sctp_association *asoc,
q->out_qlen -= chk->skb->len;
asoc->sent_cnt_removable--;
asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
+   if (chk->sinfo.sinfo_stream < asoc->stream->outcnt) {
+   struct sctp_stream_out *streamout =
+   &asoc->stream->out[chk->sinfo.sinfo_stream];
+
+   streamout->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
+   }
 
msg_len -= SCTP_DATA_SNDSIZE(chk) +
   sizeof(struct sk_buff) +
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index ccc08fc..8c0b528 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6576,6 +6576,61 @@ static int sctp_getsockopt_pr_assocstatus(struct sock 
*

Re: [PATCH] bluetooth: 6lowpan: fix delay work init in add_peer_chan()

2017-03-31 Thread Marcel Holtmann
Hi Michael,

> When adding 6lowpan devices very rapidly we sometimes see a crash:
> [23122.306615] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.9.0-43-arm64 #1 
> Debian 4.9.9.linaro.43-1
> [23122.315400] Hardware name: HiKey Development Board (DT)
> [23122.320623] task: 800075443080 task.stack: 800075484000
> [23122.326551] PC is at expire_timers+0x70/0x150
> [23122.330907] LR is at run_timer_softirq+0xa0/0x1a0
> [23122.335616] pc : [] lr : [] pstate: 
> 61c5
> 
> This was due to add_peer_chan() unconditionally initializing the
> lowpan_btle_dev->notify_peers delayed work structure, even if the
> lowpan_btle_dev passed into add_peer_chan() had previously been
> initialized.
> 
> Normally, this would go unnoticed as the delayed work timer is set for
> 100 msec, however when calling add_peer_chan() faster than 100 msec it
> clears out a previously queued delay work causing the crash above.
> 
> To fix this, let add_peer_chan() know when a new lowpan_btle_dev is passed
> in so that it only performs the delay work initialization when needed.
> 
> Signed-off-by: Michael Scott 
> ---
> net/bluetooth/6lowpan.c | 10 +++---
> 1 file changed, 7 insertions(+), 3 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel



Re: [PATCH] bluetooth: 6lowpan: fix use after free in chan_suspend/resume

2017-03-31 Thread Marcel Holtmann
Hi Michael,

> A status field in the skb_cb struct was storing a channel status
> based on channel suspend/resume events.  This stored status was
> then used to return EAGAIN if there were packet sending issues
> in snd_pkt().
> 
> The issue is that the skb has been freed by the time the callback
> to 6lowpan's suspend/resume was called.  So, this generates a
> "use after free" issue that was noticed while running kernel tests
> with KASAN debug enabled.
> 
> Let's eliminate the status field entirely as we can use the channel
> tx_credits to indicate whether we should return EAGAIN when handling
> packets.
> 
> Signed-off-by: Michael Scott 
> ---
> net/bluetooth/6lowpan.c | 21 +++--
> 1 file changed, 3 insertions(+), 18 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel



Re: [PATCH] treewide: Correct diffrent[iate] and banlance typos

2017-03-31 Thread Mauro Carvalho Chehab
Em Thu, 30 Mar 2017 20:44:16 -0700
Joe Perches  escreveu:

> Add these misspellings to scripts/spelling.txt too
> 
> Signed-off-by: Joe Perches 
> ---
>  drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h | 2 +-
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c  | 2 +-
>  drivers/net/ethernet/hisilicon/hns/hns_enet.c   | 2 +-
>  drivers/net/ethernet/qlogic/qed/qed_int.c   | 2 +-
>  drivers/net/ethernet/qlogic/qed/qed_main.c  | 2 +-
>  drivers/net/ethernet/qlogic/qed/qed_sriov.c | 2 +-
>  include/linux/mlx4/device.h | 2 +-
>  scripts/spelling.txt| 3 +++
>  8 files changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h 
> b/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h
> index 354ec07eae87..23ae72468025 100644
> --- a/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h
> +++ b/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h
> @@ -70,7 +70,7 @@
>  * (3) both long and short but short preferred and long only when necesarry
>  *
>  * These modes must be selected compile time via compile switches.
> -* Compile switch settings for the diffrent modes:
> +* Compile switch settings for the different modes:
>  * (1) DRXDAPFASI_LONG_ADDR_ALLOWED=0, DRXDAPFASI_SHORT_ADDR_ALLOWED=1
>  * (2) DRXDAPFASI_LONG_ADDR_ALLOWED=1, DRXDAPFASI_SHORT_ADDR_ALLOWED=0
>  * (3) DRXDAPFASI_LONG_ADDR_ALLOWED=1, DRXDAPFASI_SHORT_ADDR_ALLOWED=1
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c 
> b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
> index cea6bdcde33f..8baf9d3eb4b1 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
> @@ -1591,7 +1591,7 @@ static int __bnx2x_vlan_mac_execute_step(struct bnx2x 
> *bp,
>   if (rc != 0) {
>   __bnx2x_vlan_mac_h_pend(bp, o, *ramrod_flags);
>  
> - /* Calling function should not diffrentiate between this case
> + /* Calling function should not differentiate between this case
>* and the case in which there is already a pending ramrod
>*/
>   rc = 1;


Acked-by: Mauro Carvalho Chehab 

Thanks,
Mauro


Re: [PATCH net] ftgmac100: Mostly rewrite the driver

2017-03-31 Thread Benjamin Herrenschmidt
On Wed, 2017-03-29 at 20:15 -0700, David Miller wrote:
> 
> > I've started re-doing the work in the form of a series of patches.
> > 
> > I can't promise I'll manage to make them all really small but I'll
> > do my best. So hold onto reviewing if you haven't started already.
> > 
> > The end result will, I hope, be identical.
> 
> Thanks for doing this.

Alright. 2 days and half a night later, we have a 55 patches series
  ...oops ;-)

I did a few things differently from the original patch but overall it's
pretty similar. At least that exercise allowed me to find and fix a
couple of bugs along the way. I hope I didn't introduce twice as
many...

We're running some more testing tonight, if it's all solid I'll shoot
it out tomorrow or sunday. Dave, it's ok to just spam the list with a
55 patches series like that ?

For the curious, if any, it's there along with an unrelated fix for
testing:

https://github.com/ozbenh/linux-ast/commits/upstreaming-work

Cheers,
Ben.





stmmac CBS configuration for TX AVB queue

2017-03-31 Thread Niklas Cassel
Hello Joao


I was looking at

commit 19d9187317979cf0c25f67017d2676149abc46b2
Author: Joao Pinto 
Date:   Fri Mar 10 18:24:59 2017 +

net: stmmac: configuration of CBS in case of a TX AVB queue

This patch adds the configuration of the AVB Credit-Based Shaper.



It looks to me that we loop through all txqueues (including 0)

static void stmmac_configure_cbs(struct stmmac_priv *priv)
...
for (queue = 0; queue < tx_queues_count; queue++) {
...
priv->hw->mac->config_cbs(...)


then in

static void dwmac4_config_cbs(..)
...
value = readl(ioaddr + MTL_ETSX_CTRL_BASE_ADDR(queue));


The MTL_ETSX_CTRL_BASE_ADDR register only exists for txqueues != 0.
(Since txqueue0 will always handle legacy traffic.)

I think that we need to make sure that we do not enter
config_cbs() for txqueue0, even if the user's device tree
has txqueue0 set to AVB, since MTL_ETSX_CTRL_BASE_ADDR
will evaluate to a non-existing register for txqueue0.

Perhaps also clarify how we expect the user to configure
his device tree for txqueue0 when using AVB in:
Documentation/devicetree/bindings/net/stmmac.txt


Best regards,
Niklas


RE: [PATCH net 00/19] net: hns: Misc. HNS Bug Fixes & Code Improvements

2017-03-31 Thread Salil Mehta


> -Original Message-
> From: David Miller [mailto:da...@davemloft.net]
> Sent: Friday, March 31, 2017 4:03 AM
> To: Salil Mehta
> Cc: Zhuangyuzeng (Yisen); mehta.salil@gmail.com;
> netdev@vger.kernel.org; linux-ker...@vger.kernel.org; Linuxarm
> Subject: Re: [PATCH net 00/19] net: hns: Misc. HNS Bug Fixes & Code
> Improvements
> 
> From: Salil Mehta 
> Date: Thu, 30 Mar 2017 16:30:47 +0100
> 
> > This patch set introduces various HNS bug fixes, optimizations and
> code
> > improvements.
> 
> There is no way you should do such an expensive calculation for every
> single transmit packet as you are doing in your select_queue() routine.
> 
> That's really crazy.
> 
> Just use the networking stack's queue selection scheme, or suggest
> ways to improve it.  Don't do private hashing like this in your
> driver, please!
Hi David,
I got your point. I will drop this patch from this patch-set for now.

Thanks
Salil 










[PATCH net] sctp: use right in and out stream cnt

2017-03-31 Thread Xin Long
Since sctp reconf was added in sctp, the real cnt of in/out stream
have not been c.sinit_max_instreams and c.sinit_num_ostreams any
more.

This patch is to replace them with stream->in/outcnt.

Signed-off-by: Xin Long 
---
 net/sctp/outqueue.c |  3 +--
 net/sctp/proc.c |  4 ++--
 net/sctp/sm_statefuns.c |  6 +++---
 net/sctp/socket.c   | 10 +-
 4 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 025ccff..8081476 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1026,8 +1026,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int 
rtx_timeout, gfp_t gfp)
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
 * stream identifier.
 */
-   if (chunk->sinfo.sinfo_stream >=
-   asoc->c.sinit_num_ostreams) {
+   if (chunk->sinfo.sinfo_stream >= asoc->stream->outcnt) {
 
/* Mark as failed send. */
sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM);
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 206377f..a0b29d4 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -361,8 +361,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void 
*v)
sctp_seq_dump_remote_addrs(seq, assoc);
seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d "
   "%8d %8d %8d %8d",
-   assoc->hbinterval, assoc->c.sinit_max_instreams,
-   assoc->c.sinit_num_ostreams, assoc->max_retrans,
+   assoc->hbinterval, assoc->stream->incnt,
+   assoc->stream->outcnt, assoc->max_retrans,
assoc->init_retries, assoc->shutdown_retries,
assoc->rtx_data_chunks,
atomic_read(&sk->sk_wmem_alloc),
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index e03bb1a..24c6ccc 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3946,7 +3946,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net,
 
/* Silently discard the chunk if stream-id is not valid */
sctp_walk_fwdtsn(skip, chunk) {
-   if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams)
+   if (ntohs(skip->stream) >= asoc->stream->incnt)
goto discard_noforce;
}
 
@@ -4017,7 +4017,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
 
/* Silently discard the chunk if stream-id is not valid */
sctp_walk_fwdtsn(skip, chunk) {
-   if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams)
+   if (ntohs(skip->stream) >= asoc->stream->incnt)
goto gen_shutdown;
}
 
@@ -6353,7 +6353,7 @@ static int sctp_eat_data(const struct sctp_association 
*asoc,
 * and discard the DATA chunk.
 */
sid = ntohs(data_hdr->stream);
-   if (sid >= asoc->c.sinit_max_instreams) {
+   if (sid >= asoc->stream->incnt) {
/* Mark tsn as received even though we drop it */
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
 
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index baa269a..12fbae2 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1920,7 +1920,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr 
*msg, size_t msg_len)
}
 
/* Check for invalid stream. */
-   if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) {
+   if (sinfo->sinfo_stream >= asoc->stream->outcnt) {
err = -EINVAL;
goto out_free;
}
@@ -4461,8 +4461,8 @@ int sctp_get_sctp_info(struct sock *sk, struct 
sctp_association *asoc,
info->sctpi_rwnd = asoc->a_rwnd;
info->sctpi_unackdata = asoc->unack_data;
info->sctpi_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map);
-   info->sctpi_instrms = asoc->c.sinit_max_instreams;
-   info->sctpi_outstrms = asoc->c.sinit_num_ostreams;
+   info->sctpi_instrms = asoc->stream->incnt;
+   info->sctpi_outstrms = asoc->stream->outcnt;
list_for_each(pos, &asoc->base.inqueue.in_chunk_list)
info->sctpi_inqueue++;
list_for_each(pos, &asoc->outqueue.out_chunk_list)
@@ -4691,8 +4691,8 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, 
int len,
status.sstat_unackdata = asoc->unack_data;
 
status.sstat_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map);
-   status.sstat_instrms = asoc->c.sinit_max_instreams;
-   status.sstat_outstrms = asoc->c.sinit_num_ostreams;
+   status.sstat_instrms = asoc->stream->incnt;
+   status.sstat_outstrms = asoc->stream->outcnt;
status.sstat_fragmentation_point = asoc->frag_point;
status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr,
-- 
2.1.0



[PATCH net-next] net: dsa: fix build error with devlink build as module

2017-03-31 Thread Tobias Regnery
After commit 96567d5dacf4 ("net: dsa: dsa2: Add basic support of devlink")
I see the following link error with CONFIG_NET_DSA=y and CONFIG_NET_DEVLINK=m:

net/built-in.o: In function 'dsa_register_switch':
(.text+0xe226b): undefined reference to `devlink_alloc'
net/built-in.o: In function 'dsa_register_switch':
(.text+0xe2284): undefined reference to `devlink_register'
net/built-in.o: In function 'dsa_register_switch':
(.text+0xe243e): undefined reference to `devlink_port_register'
net/built-in.o: In function 'dsa_register_switch':
(.text+0xe24e1): undefined reference to `devlink_port_register'
net/built-in.o: In function 'dsa_register_switch':
(.text+0xe24fa): undefined reference to `devlink_port_type_eth_set'
net/built-in.o: In function 'dsa_dst_unapply.part.8':
dsa2.c:(.text.unlikely+0x345): undefined reference to 'devlink_port_unregister'
dsa2.c:(.text.unlikely+0x36c): undefined reference to 'devlink_port_unregister'
dsa2.c:(.text.unlikely+0x38e): undefined reference to 'devlink_port_unregister'
dsa2.c:(.text.unlikely+0x3f2): undefined reference to 'devlink_unregister'
dsa2.c:(.text.unlikely+0x3fb): undefined reference to 'devlink_free'

Fix this by adding a dependency on MAY_USE_DEVLINK so that CONFIG_NET_DSA
get switched to be build as module when CONFIG_NET_DEVLINK=m.

Fixes: 96567d5dacf4 ("net: dsa: dsa2: Add basic support of devlink")
Signed-off-by: Tobias Regnery 
---
 net/dsa/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 9649238eef40..da4d64f432db 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -6,7 +6,7 @@ config HAVE_NET_DSA
 
 config NET_DSA
tristate "Distributed Switch Architecture"
-   depends on HAVE_NET_DSA
+   depends on HAVE_NET_DSA && MAY_USE_DEVLINK
select NET_SWITCHDEV
select PHYLIB
---help---
-- 
2.11.0



[PATCH net-next] udp: use sk_protocol instead of pcflag to detect udplite sockets

2017-03-31 Thread Paolo Abeni
In the udp_sock struct, the 'forward_deficit' and 'pcflag' fields
share the same cacheline. While the first is dirtied by
udp_recvmsg, the latter is read, possibly several times, by the
bottom half processing to discriminate between udp and udplite
sockets.

With this patch, sk->sk_protocol is used to check is the socket is
really an udplite one, avoiding some cache misses per
packet and improving the performance under udp_flood with
small packet up to 10%.

Signed-off-by: Paolo Abeni 
---
 include/linux/udp.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/udp.h b/include/linux/udp.h
index c0f5308..6cb4061 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -115,6 +115,6 @@ static inline bool udp_get_no_check6_rx(struct sock *sk)
 #define udp_portaddr_for_each_entry_rcu(__sk, list) \
hlist_for_each_entry_rcu(__sk, list, __sk_common.skc_portaddr_node)
 
-#define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
+#define IS_UDPLITE(__sk) (__sk->sk_protocol == IPPROTO_UDPLITE)
 
 #endif /* _LINUX_UDP_H */
-- 
2.9.3



Re: [RFC PATCH tip/master 1/3] trace: kprobes: Show sum of probe/retprobe nmissed count

2017-03-31 Thread Alban Crequy
On Wed, Mar 29, 2017 at 7:22 AM, Masami Hiramatsu  wrote:
> Show sum of probe and retprobe nmissed count in
> kprobe_profile, since retprobe can be missed even
> if the kprobe itself succeeeded.
> This explains user why their return probe didn't hit
> sometimes.
>
> Signed-off-by: Masami Hiramatsu 

I tested this patch with my kretprobe on "inet_csk_accept" when there
are many processes waiting in the accept() syscall. I can now
successfully see the nmissed counter in
/sys/kernel/debug/tracing/kprobe_profile being incremented when the
kretprobe is missed.

Tested-by: Alban Crequy 


> ---
>  kernel/trace/trace_kprobe.c |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
> index 013f4e7..bbdc3de 100644
> --- a/kernel/trace/trace_kprobe.c
> +++ b/kernel/trace/trace_kprobe.c
> @@ -896,7 +896,7 @@ static int probes_profile_seq_show(struct seq_file *m, 
> void *v)
> seq_printf(m, "  %-44s %15lu %15lu\n",
>trace_event_name(&tk->tp.call),
>trace_kprobe_nhit(tk),
> -  tk->rp.kp.nmissed);
> +  tk->rp.kp.nmissed + tk->rp.nmissed);
>
> return 0;
>  }
>


Re: [PATCHv3] net: usbnet: support 64bit stats in qmi_wwan driver

2017-03-31 Thread Oliver Neukum
Am Freitag, den 31.03.2017, 10:48 +0200 schrieb Bjørn Mork:
> You get *all* the "0" line drivers for free, not only "qmi_wwan".  No
> code changes needed, except for adding the single .ndo line to drivers
> overriding the usbnet default net_device_ops. And even that only applies
> to a few of them.  Most will be OK if you just change the usbnet
> default.
> 
> I don't think the size of a complete series will be terrifying to
> anyone.

It would really be nice to do that.
However, if you really don't want to do it, well you wrote
a patch. But I am afraid dropping the error count is not acceptable.

Regards
Oliver



[PATCH v3 1/3] net: phy: avoid setting unsupported EEE advertisments

2017-03-31 Thread Russell King
We currently allow userspace to set any EEE advertisments it desires,
whether or not the PHY supports them.  For example:

 # ethtool --set-eee eth1 advertise 0x
 # ethtool --show-eee eth1
 EEE Settings for eth1:
EEE status: disabled
Tx LPI: disabled
Supported EEE link modes:  100baseT/Full
   1000baseT/Full
   1baseT/Full
Advertised EEE link modes:  100baseT/Full
1000baseT/Full
1000baseKX/Full
1baseT/Full
1baseKX4/Full
1baseKR/Full

Clearly, this is not sane, we should only allow link modes that are
supported to be advertised (as we do elsewhere.)  Ensure that we mask
the MDIO_AN_EEE_ADV value with the capabilities retrieved from the
MDIO_PCS_EEE_ABLE register.

Reviewed-by: Florian Fainelli 
Signed-off-by: Russell King 
---
 drivers/net/phy/phy.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ba4676ee9018..7b1c93b0233a 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1332,17 +1332,22 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
  */
 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
 {
-   int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
+   int cap, adv;
 
if (!phydev->drv)
return -EIO;
 
-   /* Mask prohibited EEE modes */
-   val &= ~phydev->eee_broken_modes;
+   /* Get Supported EEE */
+   cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
+   if (cap < 0)
+   return cap;
 
-   phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+   adv = ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
 
-   return 0;
+   /* Mask prohibited EEE modes */
+   adv &= ~phydev->eee_broken_modes;
+
+   return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
 }
 EXPORT_SYMBOL(phy_ethtool_set_eee);
 
-- 
2.7.4



[PATCH v3 2/3] net: phy: restart phy autonegotiation after EEE advertisment change

2017-03-31 Thread Russell King
When the EEE advertisment is changed, we should restart autonegotiation
to update the link partner with the new EEE settings.  Add this trigger
but only if the advertisment has changed.

Reviewed-by: Florian Fainelli 
Signed-off-by: Russell King 
---
 drivers/net/phy/phy.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 7b1c93b0233a..345251f21699 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1332,7 +1332,7 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
  */
 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
 {
-   int cap, adv;
+   int cap, old_adv, adv, ret;
 
if (!phydev->drv)
return -EIO;
@@ -1342,12 +1342,29 @@ int phy_ethtool_set_eee(struct phy_device *phydev, 
struct ethtool_eee *data)
if (cap < 0)
return cap;
 
+   old_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
+   if (old_adv < 0)
+   return old_adv;
+
adv = ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
 
/* Mask prohibited EEE modes */
adv &= ~phydev->eee_broken_modes;
 
-   return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
+   if (old_adv != adv) {
+   ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
+   if (ret < 0)
+   return ret;
+
+   /* Restart autonegotiation so the new modes get sent to the
+* link partner.
+*/
+   ret = genphy_restart_aneg(phydev);
+   if (ret < 0)
+   return ret;
+   }
+
+   return 0;
 }
 EXPORT_SYMBOL(phy_ethtool_set_eee);
 
-- 
2.7.4



[PATCH v3 3/3] net: phy: allow EEE with any interface mode

2017-03-31 Thread Russell King
EEE is able to work in any PHY interface mode, there is nothing which
fundamentally restricts it to only a few modes.  For example, EEE works
in SGMII mode with the Marvell 88E1512.

Rather than just adding SGMII mode to the list, Florian suggests
removing the list of interface modes entirely:

  It actually sounds like we should just kill the check entirely,
  it does not appear that any of the interface mode would not
  fundamentally be able to support EEE, because the "lowest" mode
  we support is MII, and even there it's quite possible to support
  EEE.

Reviewed-by: Florian Fainelli 
Signed-off-by: Russell King 
---
 drivers/net/phy/phy.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 345251f21699..867c42154087 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1208,15 +1208,8 @@ int phy_init_eee(struct phy_device *phydev, bool 
clk_stop_enable)
return -EIO;
 
/* According to 802.3az,the EEE is supported only in full duplex-mode.
-* Also EEE feature is active when core is operating with MII, GMII
-* or RGMII (all kinds). Internal PHYs are also allowed to proceed and
-* should return an error if they do not support EEE.
 */
-   if ((phydev->duplex == DUPLEX_FULL) &&
-   ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
-   (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
-phy_interface_is_rgmii(phydev) ||
-phy_is_internal(phydev))) {
+   if (phydev->duplex == DUPLEX_FULL) {
int eee_lp, eee_cap, eee_adv;
u32 lp, cap, adv;
int status;
-- 
2.7.4



Re: [PATCH] bluetooth: 6lowpan: fix delay work init in add_peer_chan()

2017-03-31 Thread Jukka Rissanen
Hi Michael,

On Tue, 2017-03-28 at 23:10 -0700, Michael Scott wrote:
> When adding 6lowpan devices very rapidly we sometimes see a crash:
> [23122.306615] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.9.0-43-
> arm64 #1 Debian 4.9.9.linaro.43-1
> [23122.315400] Hardware name: HiKey Development Board (DT)
> [23122.320623] task: 800075443080 task.stack: 800075484000
> [23122.326551] PC is at expire_timers+0x70/0x150
> [23122.330907] LR is at run_timer_softirq+0xa0/0x1a0
> [23122.335616] pc : [] lr : []
> pstate: 61c5
> 
> This was due to add_peer_chan() unconditionally initializing the
> lowpan_btle_dev->notify_peers delayed work structure, even if the
> lowpan_btle_dev passed into add_peer_chan() had previously been
> initialized.
> 
> Normally, this would go unnoticed as the delayed work timer is set
> for
> 100 msec, however when calling add_peer_chan() faster than 100 msec
> it
> clears out a previously queued delay work causing the crash above.
> 
> To fix this, let add_peer_chan() know when a new lowpan_btle_dev is
> passed
> in so that it only performs the delay work initialization when
> needed.
> 
> Signed-off-by: Michael Scott 
> ---
>  net/bluetooth/6lowpan.c | 10 +++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index e27be3ca0a0c..c282482edc2c 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -754,7 +754,8 @@ static void set_ip_addr_bits(u8 addr_type, u8
> *addr)
>  }
>  
>  static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan,
> - struct lowpan_btle_dev *dev)
> + struct lowpan_btle_dev *dev,
> + bool new_netdev)
>  {
>   struct lowpan_peer *peer;
>  
> @@ -785,7 +786,8 @@ static struct l2cap_chan *add_peer_chan(struct
> l2cap_chan *chan,
>   spin_unlock(&devices_lock);
>  
>   /* Notifying peers about us needs to be done without locks
> held */
> - INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers);
> + if (new_netdev)
> + INIT_DELAYED_WORK(&dev->notify_peers,
> do_notify_peers);
>   schedule_delayed_work(&dev->notify_peers,
> msecs_to_jiffies(100));
>  
>   return peer->chan;
> @@ -842,6 +844,7 @@ static int setup_netdev(struct l2cap_chan *chan,
> struct lowpan_btle_dev **dev)
>  static inline void chan_ready_cb(struct l2cap_chan *chan)
>  {
>   struct lowpan_btle_dev *dev;
> + bool new_netdev = false;
>  
>   dev = lookup_dev(chan->conn);
>  
> @@ -852,12 +855,13 @@ static inline void chan_ready_cb(struct
> l2cap_chan *chan)
>   l2cap_chan_del(chan, -ENOENT);
>   return;
>   }
> + new_netdev = true;
>   }
>  
>   if (!try_module_get(THIS_MODULE))
>   return;
>  
> - add_peer_chan(chan, dev);
> + add_peer_chan(chan, dev, new_netdev);
>   ifup(dev->netdev);
>  }
>  

Good catch!

Acked-by: Jukka Rissanen 


Cheers,
Jukka





[PATCH v3 0/3] phylib EEE updates

2017-03-31 Thread Russell King - ARM Linux
David,

This series of patches depends on the previous set of changes, and is
therefore net-next material.

While testing the EEE code, I discovered a number of issues:

1. It is possible to enable advertisment of EEE modes which are not
   supported by the hardware.  We omit to check the supported modes
   and mask off those modes that are not supported before writing the
   EEE advertisment register.

2. We need to restart autonegotiation after a change of the EEE
   advertisment, otherwise the link partner does not see the updated
   EEE modes.

3. SGMII connected PHYs are also capable of supporting EEE.

Through discussion with Florian, it has been decided to remove the check
for the PHY interface mode in patch (3).

 drivers/net/phy/phy.c | 37 ++---
 1 file changed, 26 insertions(+), 11 deletions(-)

v2: fix "phy_restart_aneg" build error identified by 0-day
v3: drop RFC tag, replace 3rd patch

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


Re: [PATCH] bluetooth: 6lowpan: fix use after free in chan_suspend/resume

2017-03-31 Thread Jukka Rissanen
Hi Michael,

On Tue, 2017-03-28 at 23:10 -0700, Michael Scott wrote:
> A status field in the skb_cb struct was storing a channel status
> based on channel suspend/resume events.  This stored status was
> then used to return EAGAIN if there were packet sending issues
> in snd_pkt().
> 
> The issue is that the skb has been freed by the time the callback
> to 6lowpan's suspend/resume was called.  So, this generates a
> "use after free" issue that was noticed while running kernel tests
> with KASAN debug enabled.
> 
> Let's eliminate the status field entirely as we can use the channel
> tx_credits to indicate whether we should return EAGAIN when handling
> packets.
> 
> Signed-off-by: Michael Scott 
> ---
>  net/bluetooth/6lowpan.c | 21 +++--
>  1 file changed, 3 insertions(+), 18 deletions(-)
> 
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index d491529332f4..e27be3ca0a0c 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -38,7 +38,6 @@ struct skb_cb {
>   struct in6_addr addr;
>   struct in6_addr gw;
>   struct l2cap_chan *chan;
> - int status;
>  };
>  #define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
>  
> @@ -528,7 +527,7 @@ static int send_pkt(struct l2cap_chan *chan,
> struct sk_buff *skb,
>   }
>  
>   if (!err)
> - err = lowpan_cb(skb)->status;
> + err = (!chan->tx_credits ? -EAGAIN : 0);
>  
>   if (err < 0) {
>   if (err == -EAGAIN)
> @@ -964,26 +963,12 @@ static struct sk_buff *chan_alloc_skb_cb(struct
> l2cap_chan *chan,
>  
>  static void chan_suspend_cb(struct l2cap_chan *chan)
>  {
> - struct sk_buff *skb = chan->data;
> -
> - BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb);
> -
> - if (!skb)
> - return;
> -
> - lowpan_cb(skb)->status = -EAGAIN;
> + BT_DBG("chan %p suspend", chan);
>  }
>  
>  static void chan_resume_cb(struct l2cap_chan *chan)
>  {
> - struct sk_buff *skb = chan->data;
> -
> - BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb);
> -
> - if (!skb)
> - return;
> -
> - lowpan_cb(skb)->status = 0;
> + BT_DBG("chan %p resume", chan);
>  }
>  
>  static long chan_get_sndtimeo_cb(struct l2cap_chan *chan)

Good catch! If we can avoid using the status variable, that is very
good. We could probably also remove the resume and suspend callbacks as
they are now empty functions (unless we need the debug info for
something).

Acked-by: Jukka Rissanen 


Cheers,
Jukka




Re: [PATCH v3 1/2] net: phy: Fix PHY AN done state machine for interrupt driven PHYs

2017-03-31 Thread Roger Quadros
Florian,

On 30/03/17 23:02, Florian Fainelli wrote:
> On 03/27/2017 04:59 AM, Roger Quadros wrote:
>> The Ethernet link on an interrupt driven PHY was not coming up if the
>> Ethernet cable was plugged before the Ethernet interface was brought up.
>>
>> The PHY state machine seems to be stuck from RUNNING to AN state
>> with no new interrupts from the PHY. So it doesn't know when the
>> PHY Auto-negotiation has been completed and doesn't transition to RUNNING
>> state with ANEG done thus netif_carrier_on() is never called.
>>
>> NOTE: genphy_config_aneg() will not restart PHY Auto-negotiation of
>> advertisement parameters didn't change.
>>
>> Fix this by scheduling the PHY state machine in phy_start_aneg().
>> There is no way of knowing in phy.c whether auto-negotiation was
>> restarted or not by the PHY driver so we just wait for the next
>> poll/interrupt to update the PHY state machine.
>>
>> Fixes: 3c293f4e08b5 ("net: phy: Trigger state machine on state change and 
>> not polling.")
>> Cc: stable  # v4.9+
>> Signed-off-by: Roger Quadros 
> 
> Reviewed-by: Florian Fainelli 
> 
Thanks for the review, but there are a still few unanswered questions in the 
parallel thread.
Can you please clarify those first before this patch gets picked? Thanks.

cheers,
-roger


Re: [PATCHv3] net: usbnet: support 64bit stats in qmi_wwan driver

2017-03-31 Thread Bjørn Mork
Greg Ungerer  writes:

> Add support for the net stats64 counters to the usbnet core and then to
> the qmi_wwan driver.
>
> This is a strait forward addition of 64bit counters for RX and TX packets
> and byte counts. It is done in the same style as for the other net drivers
> that support stats64.
>
> The bulk of the change is to the usbnet core. Then it is trivial to use
> that in the qmi_wwan.c driver. It would be very simple to extend this
> support to other usbnet based drivers.

Sorry, but I am starting to have my doubts about this partial conversion
of the usbnet stats.  I don't have any problem with doing incremental
changes.  But in this case it means running duplicate code. And I see no
reasons to justify doing this incrementally.  As you say: It is very
simple to extend it to all usbnet drivers when the basic infrastructure
is in place.

You alreay do most of that work. So why not just update the other
drivers too, allowing us to drop the legacy counters?  Deleting code is
always good :)


> +void usbnet_get_stats64(struct net_device *net, struct rtnl_link_stats64 
> *stats)
> +{
> + struct usbnet *dev = netdev_priv(net);
> + unsigned int start;
> + int cpu;
> +
> + netdev_stats_to_stats64(stats, &net->stats);
> +
> + for_each_possible_cpu(cpu) {
> + struct pcpu_sw_netstats *stats64;
> + u64 rx_packets, rx_bytes;
> + u64 tx_packets, tx_bytes;
> +
> + stats64 = per_cpu_ptr(dev->stats64, cpu);
> +
> + do {
> + start = u64_stats_fetch_begin_irq(&stats64->syncp);
> + rx_packets = stats64->rx_packets;
> + rx_bytes = stats64->rx_bytes;
> + tx_packets = stats64->tx_packets;
> + tx_bytes = stats64->tx_bytes;
> + } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
> +
> + stats->rx_packets += rx_packets;
> + stats->rx_bytes += rx_bytes;
> + stats->tx_packets += tx_packets;
> + stats->tx_bytes += tx_bytes;
> + }
> +}

So we only count packets and bytes.  No errors.  Why?

> @@ -1212,8 +1249,15 @@ static void tx_complete (struct urb *urb)
>   struct usbnet   *dev = entry->dev;
>  
>   if (urb->status == 0) {
> + struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
> +
>   dev->net->stats.tx_packets += entry->packets;
>   dev->net->stats.tx_bytes += entry->length;
> +
> + u64_stats_update_begin(&stats64->syncp);
> + stats64->tx_packets += entry->packets;
> + stats64->tx_bytes += entry->length;
> + u64_stats_update_end(&stats64->syncp);
>   } else {
>   dev->net->stats.tx_errors++;
>  


This is one place where the old stats counted errors too.  But there are more:

bjorn@miraculix:/usr/local/src/git/linux$ git grep -E -- '->stats.*\+' 
drivers/net/usb/usbnet.c|grep -Ev '(bytes|packet)'
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_length_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_over_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.rx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.tx_errors++;
drivers/net/usb/usbnet.c:   dev->net->stats.tx_dropped++;


Personally, I'd rather have incorrect byte counters than losing these
error counters. They are valuable debugging aids. I don't see why they
cannot be converted to 64bit stats right away.  Except that it makes the
amount of double accounting much more obvious...

Which is why I have landed on on a request to convert all the usbnet
drivers in one go.  There aren't that many of them, and even fewer
touching the stats outside of usbnet.c.  Among those few, none have more
than 6 lines currently touching "stats":

bjorn@miraculix:/usr/local/src/git/linux$ for f in `git grep -l -- 
'usbnet_probe' drivers/net/usb/`; do grep -Hc -- '->stats' $f; done
drivers/net/usb/asix_devices.c:0
drivers/net/usb/ax88179_178a.c:0
drivers/net/usb/cdc_eem.c:1
drivers/net/usb/cdc_ether.c:0
drivers/net/usb/cdc_mbim.c:0
drivers/net/usb/cdc_ncm.c:4
drivers/net/usb/cdc_subset.c:0
drivers/net/usb/ch9200.c:0
drivers/net/usb/cx82310_eth.c:0
drivers/net/usb/dm9601.c:5
drivers/net/usb/gl620a.c:0
drivers/net/usb/huawei_cdc_ncm.c:0
drivers/net/usb/int51x1.c:0
drivers/net/usb/kalmia.c:0
drivers/net/usb/lg-vl600.c:4
drivers/net/usb/mcs7830.c:4
drivers/net/usb/net1080.c:6
drivers/net/usb/plusb.c:0
drivers/net/usb/qmi_wwan.c:0
drivers/net/usb/rndis_host.c:1
drivers/net/usb/sierra_net.c:6
drivers/net/usb/smsc75xx.c:4
drivers/net/usb/smsc95xx.c:5
drivers/net/usb/sr9

Re: [PATCH] bluetooth: 6lowpan: fix use after free in chan_suspend/resume

2017-03-31 Thread Luiz Augusto von Dentz
Hi Michael,

On Wed, Mar 29, 2017 at 9:10 AM, Michael Scott  wrote:
> A status field in the skb_cb struct was storing a channel status
> based on channel suspend/resume events.  This stored status was
> then used to return EAGAIN if there were packet sending issues
> in snd_pkt().
>
> The issue is that the skb has been freed by the time the callback
> to 6lowpan's suspend/resume was called.  So, this generates a
> "use after free" issue that was noticed while running kernel tests
> with KASAN debug enabled.
>
> Let's eliminate the status field entirely as we can use the channel
> tx_credits to indicate whether we should return EAGAIN when handling
> packets.
>
> Signed-off-by: Michael Scott 
> ---
>  net/bluetooth/6lowpan.c | 21 +++--
>  1 file changed, 3 insertions(+), 18 deletions(-)
>
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index d491529332f4..e27be3ca0a0c 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -38,7 +38,6 @@ struct skb_cb {
> struct in6_addr addr;
> struct in6_addr gw;
> struct l2cap_chan *chan;
> -   int status;
>  };
>  #define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
>
> @@ -528,7 +527,7 @@ static int send_pkt(struct l2cap_chan *chan, struct 
> sk_buff *skb,
> }
>
> if (!err)
> -   err = lowpan_cb(skb)->status;
> +   err = (!chan->tx_credits ? -EAGAIN : 0);
>
> if (err < 0) {
> if (err == -EAGAIN)
> @@ -964,26 +963,12 @@ static struct sk_buff *chan_alloc_skb_cb(struct 
> l2cap_chan *chan,
>
>  static void chan_suspend_cb(struct l2cap_chan *chan)
>  {
> -   struct sk_buff *skb = chan->data;
> -
> -   BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb);
> -
> -   if (!skb)
> -   return;
> -
> -   lowpan_cb(skb)->status = -EAGAIN;
> +   BT_DBG("chan %p suspend", chan);
>  }
>
>  static void chan_resume_cb(struct l2cap_chan *chan)
>  {
> -   struct sk_buff *skb = chan->data;
> -
> -   BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb);
> -
> -   if (!skb)
> -   return;
> -
> -   lowpan_cb(skb)->status = 0;
> +   BT_DBG("chan %p resume", chan);
>  }
>
>  static long chan_get_sndtimeo_cb(struct l2cap_chan *chan)
> --
> 2.11.0

It should be possible to queue the packets on l2cap_chan_send, Im not
sure why we have this suspend logic in the first place so perhaps
Jukka can shed some light here.



-- 
Luiz Augusto von Dentz


[net-next v3] vxlan: fix ND proxy when skb doesn't have transport header offset

2017-03-31 Thread Vincent Bernat
When an incoming frame is tagged or when GRO is disabled, the skb
handled to vxlan_xmit() doesn't contain a valid transport header
offset. This makes ND proxying fail.

We combine two changes: replace use of skb_transport_offset() and ensure
the necessary amount of skb is linear just before using it:

 - In vxlan_xmit(), when determining if we have an ICMPv6 neighbor
   discovery packet, just check if it is an ICMPv6 packet and rely on
   neigh_reduce() to do more checks if this is the case. The use of
   pskb_may_pull() is replaced by skb_header_pointer() for just the IPv6
   header.

 - In neigh_reduce(), add pskb_may_pull() for IPv6 header and neighbor
   discovery message since this was removed from vxlan_xmit(). Replace
   skb_transport_header() with ipv6_hdr() + 1.

 - In vxlan_na_create(), replace first skb_transport_offset() with
   ipv6_hdr() + 1 and second with skb_network_offset() + sizeof(struct
   ipv6hdr). Additionally, ensure we pskb_may_pull() the whole skb as we
   need it to iterate over the options.

Signed-off-by: Vincent Bernat 
---
 drivers/net/vxlan.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 1e54fb5c883a..54dda367de2b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1515,7 +1515,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff 
*request,
int ns_olen;
int i, len;
 
-   if (dev == NULL)
+   if (dev == NULL || !pskb_may_pull(request, request->len))
return NULL;
 
len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
@@ -1530,10 +1530,11 @@ static struct sk_buff *vxlan_na_create(struct sk_buff 
*request,
skb_push(reply, sizeof(struct ethhdr));
skb_reset_mac_header(reply);
 
-   ns = (struct nd_msg *)skb_transport_header(request);
+   ns = (struct nd_msg *)(ipv6_hdr(request) + 1);
 
daddr = eth_hdr(request)->h_source;
-   ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns);
+   ns_olen = request->len - skb_network_offset(request) -
+   sizeof(struct ipv6hdr) - sizeof(*ns);
for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
@@ -1604,10 +1605,13 @@ static int neigh_reduce(struct net_device *dev, struct 
sk_buff *skb, __be32 vni)
if (!in6_dev)
goto out;
 
+   if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)))
+   goto out;
+
iphdr = ipv6_hdr(skb);
daddr = &iphdr->daddr;
 
-   msg = (struct nd_msg *)skb_transport_header(skb);
+   msg = (struct nd_msg *)(iphdr + 1);
if (msg->icmph.icmp6_code != 0 ||
msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
goto out;
@@ -2238,21 +2242,17 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, 
struct net_device *dev)
}
 
if (vxlan->flags & VXLAN_F_PROXY) {
+   struct ipv6hdr *hdr, _hdr;
eth = eth_hdr(skb);
if (ntohs(eth->h_proto) == ETH_P_ARP)
return arp_reduce(dev, skb, vni);
 #if IS_ENABLED(CONFIG_IPV6)
else if (ntohs(eth->h_proto) == ETH_P_IPV6 &&
-pskb_may_pull(skb, sizeof(struct ipv6hdr)
-  + sizeof(struct nd_msg)) &&
-ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
-   struct nd_msg *msg;
-
-   msg = (struct nd_msg 
*)skb_transport_header(skb);
-   if (msg->icmph.icmp6_code == 0 &&
-   msg->icmph.icmp6_type == 
NDISC_NEIGHBOUR_SOLICITATION)
-   return neigh_reduce(dev, skb, vni);
-   }
+(hdr = skb_header_pointer(skb,
+  skb_network_offset(skb),
+  sizeof(_hdr), &_hdr)) &&
+hdr->nexthdr == IPPROTO_ICMPV6)
+   return neigh_reduce(dev, skb, vni);
 #endif
}
 
-- 
2.11.0



Re: [PATCH v2 net-next 3/6] tools/lib/bpf: expose bpf_program__set_type()

2017-03-31 Thread Wangnan (F)

Hi Alexei,

Please see the patch I sent. Since we export bpf_program__set_type(),
bpf_program__set_xxx() should be built based on it.

Thank you.

On 2017/3/31 12:45, Alexei Starovoitov wrote:

expose bpf_program__set_type() to set program type

Signed-off-by: Alexei Starovoitov 
Acked-by: Daniel Borkmann 
Acked-by: Martin KaFai Lau 
---
  





[PATCH] af_key: Add lock to key dump

2017-03-31 Thread Yuejie Shi
A dump may come in the middle of another dump, modifying its dump
structure members. This race condition will result in NULL pointer
dereference in kernel. So add a lock to prevent that race.

Fixes: 83321d6b9872 ("[AF_KEY]: Dump SA/SP entries non-atomically")
Signed-off-by: Yuejie Shi 
---
 net/key/af_key.c | 46 ++
 1 file changed, 38 insertions(+), 8 deletions(-)

diff --git a/net/key/af_key.c b/net/key/af_key.c
index c6252ed..1b0ea80 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -63,6 +63,7 @@ struct pfkey_sock {
} u;
struct sk_buff  *skb;
} dump;
+   struct mutex dump_lock;
 };
 
 static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
@@ -139,6 +140,7 @@ static int pfkey_create(struct net *net, struct socket 
*sock, int protocol,
 {
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
struct sock *sk;
+   struct pfkey_sock *pfk;
int err;
 
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
@@ -153,6 +155,9 @@ static int pfkey_create(struct net *net, struct socket 
*sock, int protocol,
if (sk == NULL)
goto out;
 
+   pfk = pfkey_sk(sk);
+   mutex_init(&pfk->dump_lock);
+
sock->ops = &pfkey_ops;
sock_init_data(sock, sk);
 
@@ -281,13 +286,23 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
struct sadb_msg *hdr;
int rc;
 
+   mutex_lock(&pfk->dump_lock);
+   if (!pfk->dump.dump) {
+   rc = 0;
+   goto out;
+   }
+
rc = pfk->dump.dump(pfk);
-   if (rc == -ENOBUFS)
-   return 0;
+   if (rc == -ENOBUFS) {
+   rc = 0;
+   goto out;
+   }
 
if (pfk->dump.skb) {
-   if (!pfkey_can_dump(&pfk->sk))
-   return 0;
+   if (!pfkey_can_dump(&pfk->sk)) {
+   rc = 0;
+   goto out;
+   }
 
hdr = (struct sadb_msg *) pfk->dump.skb->data;
hdr->sadb_msg_seq = 0;
@@ -298,6 +313,9 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
}
 
pfkey_terminate_dump(pfk);
+
+out:
+   mutex_unlock(&pfk->dump_lock);
return rc;
 }
 
@@ -1793,19 +1811,26 @@ static int pfkey_dump(struct sock *sk, struct sk_buff 
*skb, const struct sadb_ms
struct xfrm_address_filter *filter = NULL;
struct pfkey_sock *pfk = pfkey_sk(sk);
 
-   if (pfk->dump.dump != NULL)
+   mutex_lock(&pfk->dump_lock);
+   if (pfk->dump.dump != NULL) {
+   mutex_unlock(&pfk->dump_lock);
return -EBUSY;
+   }
 
proto = pfkey_satype2proto(hdr->sadb_msg_satype);
-   if (proto == 0)
+   if (proto == 0) {
+   mutex_unlock(&pfk->dump_lock);
return -EINVAL;
+   }
 
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
 
filter = kmalloc(sizeof(*filter), GFP_KERNEL);
-   if (filter == NULL)
+   if (filter == NULL) {
+   mutex_unlock(&pfk->dump_lock);
return -ENOMEM;
+   }
 
memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr,
   sizeof(xfrm_address_t));
@@ -1821,6 +1846,7 @@ static int pfkey_dump(struct sock *sk, struct sk_buff 
*skb, const struct sadb_ms
pfk->dump.dump = pfkey_dump_sa;
pfk->dump.done = pfkey_dump_sa_done;
xfrm_state_walk_init(&pfk->dump.u.state, proto, filter);
+   mutex_unlock(&pfk->dump_lock);
 
return pfkey_do_dump(pfk);
 }
@@ -2679,14 +2705,18 @@ static int pfkey_spddump(struct sock *sk, struct 
sk_buff *skb, const struct sadb
 {
struct pfkey_sock *pfk = pfkey_sk(sk);
 
-   if (pfk->dump.dump != NULL)
+   mutex_lock(&pfk->dump_lock);
+   if (pfk->dump.dump != NULL) {
+   mutex_unlock(&pfk->dump_lock);
return -EBUSY;
+   }
 
pfk->dump.msg_version = hdr->sadb_msg_version;
pfk->dump.msg_portid = hdr->sadb_msg_pid;
pfk->dump.dump = pfkey_dump_sp;
pfk->dump.done = pfkey_dump_sp_done;
xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
+   mutex_unlock(&pfk->dump_lock);
 
return pfkey_do_dump(pfk);
 }
-- 
2.7.4



<    1   2