Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH tip/core/rcu 2/7] sfc: Replace spin_is_locked() with lockdep
From: Edward Cree @ 2018-11-12 13:02 UTC (permalink / raw)
  To: Paul E. McKenney, linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, fweisbec, oleg, joel,
	Lance Roy, Solarflare linux maintainers, Bert Kenward,
	David S. Miller, netdev
In-Reply-To: <20181111200443.10772-2-paulmck@linux.ibm.com>

On 11/11/18 20:04, Paul E. McKenney wrote:
> From: Lance Roy <ldr709@gmail.com>
>
> lockdep_assert_held() is better suited to checking locking requirements,
> since it only checks if the current thread holds the lock regardless of
> whether someone else does. This is also a step towards possibly removing
> spin_is_locked().
>
> Signed-off-by: Lance Roy <ldr709@gmail.com>
> Cc: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
> Cc: Edward Cree <ecree@solarflare.com>
> Cc: Bert Kenward <bkenward@solarflare.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: <netdev@vger.kernel.org>
> Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
> ---
Acked-by: Edward Cree <ecree@solarflare.com>
>  drivers/net/ethernet/sfc/efx.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
> index 98fe7e762e17..3643015a55cf 100644
> --- a/drivers/net/ethernet/sfc/efx.c
> +++ b/drivers/net/ethernet/sfc/efx.c
> @@ -3167,7 +3167,7 @@ struct hlist_head *efx_rps_hash_bucket(struct efx_nic *efx,
>  {
>  	u32 hash = efx_filter_spec_hash(spec);
>  
> -	WARN_ON(!spin_is_locked(&efx->rps_hash_lock));
> +	lockdep_assert_held(&efx->rps_hash_lock);
>  	if (!efx->rps_hash_table)
>  		return NULL;
>  	return &efx->rps_hash_table[hash % EFX_ARFS_HASH_TABLE_SIZE];

^ permalink raw reply

* Re: [RFC PATCH 0/3] acpi: Add acpi mdio support code
From: Wang, Dongsheng @ 2018-11-12  2:52 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: timur@kernel.org, Zheng, Joey, f.fainelli@gmail.com,
	rjw@rjwysocki.net, linux-acpi@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <20181108232353.GL5259@lunn.ch>

On 2018/11/9 7:23, Andrew Lunn wrote:
> I'm just trying to ensure whatever is defined is flexible enough that
> we really can later support everything which DT does. We have PHYs on
> MDIO busses, inside switches, which are on MDIO busses, which are
> inside Ethernet interfaces, etc.
>
> An MDIO bus is very similar to an i2c bus. How is that described in
> ACPI? Anything we can learn from that?

All the documents I've seen are from UEFII/ACPICA and I have not seen any
independent description of MDIO in the ACPI documents. Maybe I missed a
document, too.

I think not all devices need to be described in ACPI. The ACPI defines what
should be included in a device, as well as some special definitions. Our
MDIO
doesn't need a special definition, because it's enough to use a generic ACPI
description. I think that's why MDIO doesn't have a separate description.

Cheers,
Dongsheng

^ permalink raw reply

* [PATCH net v2 1/1] bnx2x: Assign unique DMAE channel number for FW DMAE transactions.
From: Sudarsana Reddy Kalluru @ 2018-11-12  2:27 UTC (permalink / raw)
  To: davem; +Cc: netdev, Michal.Kalderon

Driver assigns DMAE channel 0 for FW as part of START_RAMROD command. FW
uses this channel for DMAE operations (e.g., TIME_SYNC implementation).
Driver also uses the same channel 0 for DMAE operations for some of the PFs
(e.g., PF0 on Port0). This could lead to concurrent access to the DMAE
channel by FW and driver which is not legal. Hence need to assign unique
DMAE id for FW.
Currently following DMAE channels are used by the clients,
  MFW - OCBB/OCSD functionality uses DMAE channel 14/15
  Driver 0-3 and 8-11 (for PF dmae operations)
         4 and 12 (for stats requests)
Assigning unique dmae_id '13' to the FW.

Changes from previous version:
------------------------------
v2: Incorporated the review comments.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h    | 7 +++++++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index be15061..0de487a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -2191,6 +2191,13 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 #define PMF_DMAE_C(bp)			(BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
 					 E1HVN_MAX)
 
+/* Following is the DMAE channel number allocation for the clients.
+ *   MFW: OCBB/OCSD implementations use DMAE channels 14/15 respectively.
+ *   Driver: 0-3 and 8-11 (for PF dmae operations)
+ *           4 and 12 (for stats requests)
+ */
+#define BNX2X_FW_DMAE_C                 13 /* Channel for FW DMAE operations */
+
 /* PCIE link and speed */
 #define PCICFG_LINK_WIDTH		0x1f00000
 #define PCICFG_LINK_WIDTH_SHIFT		20
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 3f4d2c8..a9eaaf3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -6149,6 +6149,7 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
 	rdata->sd_vlan_tag	= cpu_to_le16(start_params->sd_vlan_tag);
 	rdata->path_id		= BP_PATH(bp);
 	rdata->network_cos_mode	= start_params->network_cos_mode;
+	rdata->dmae_cmd_id	= BNX2X_FW_DMAE_C;
 
 	rdata->vxlan_dst_port	= cpu_to_le16(start_params->vxlan_dst_port);
 	rdata->geneve_dst_port	= cpu_to_le16(start_params->geneve_dst_port);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC net-next] net: SAIL based FIB lookup for XDP
From: Md. Islam @ 2018-11-12  2:25 UTC (permalink / raw)
  To: Netdev, David Ahern, Jesper Dangaard Brouer, David Miller,
	Stephen Hemminger, john fastabend, Alexey Kuznetsov

This patch implements SAIL[1] based routing table lookup for XDP. I
however made some changes from the original proposal (details are
described in the patch). This changes decreased the memory consumption
from 21.94 MB to 4.97 MB for my example routing table with 400K
routes.

This patch can perform FIB lookup in 50 CPU cycles for the example
routing table (with 400K routes) whereas LC-trie takes around 350 CPU
cycles.

I tried to follow all the advice I got from my last patch. Looking
forward to your review.

1. Yang, Tong, et al. "Guarantee IP lookup performance with FIB
explosion." ACM SIGCOMM Computer Communication Review. Vol. 44. No. 4.
ACM, 2014.

Thanks
Tamim

Signed-off-by: MD Iftakharul Islam (Tamim) <mislam4@kent.edu>
---
 MAINTAINERS             |   5 +
 include/net/ip_fib.h    |  60 ++++
 net/core/filter.c       |  49 +++
 net/ipv4/Kconfig        |  11 +
 net/ipv4/Makefile       |   1 +
 net/ipv4/fib_sail_xdp.c | 939 ++++++++++++++++++++++++++++++++++++++++++++++++
 net/ipv4/fib_trie.c     |  12 +
 7 files changed, 1077 insertions(+)
 create mode 100644 net/ipv4/fib_sail_xdp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b22e7fd..969e625 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7630,6 +7630,11 @@ M:    Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
 S:    Maintained
 F:    net/ipv4/netfilter/ipt_MASQUERADE.c

+SAIL FIB LOOKUP
+M:    MD Iftakharul Islam (Tamim) <tamim@csebuet.org>
+S:    Maintained
+F:    net/ipv4/fib_sail_xdp.c
+
 IPMI SUBSYSTEM
 M:    Corey Minyard <minyard@acm.org>
 L:    openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 69c91d1..cc275c7 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -197,6 +197,62 @@ struct fib_entry_notifier_info {
     u32 tb_id;
 };

+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+/*
+ * The router can have upto 255 ports. This limitation
+ * allows us to represent netdev_index as an u8
+ */
+#define NETDEV_COUNT_MAX 255
+
+struct chunk {
+    /*256-bit bitmap. Here i-th bit (from LSB) is set to 1 if C24[i] > 0 */
+    u64 bitmap[4];
+    /*
+     * Index to C24 where chunk is started. A chunk corresponds
+     * to 256 elements. Instead of having just one start index for the
+     * whole chunk, we divide the chunk into 4 parts and save start
+     * index for each part.
+     */
+    u64 start_index[4];
+};
+
+struct sail {
+    /*default next-hop (Level 0)*/
+    u8    def_nh;
+
+    /*Level 16*/
+    u8 __rcu *N16;
+    u8 __rcu *P16;
+    u16 __rcu *C16;
+
+    /*Level 24*/
+    u8 __rcu *N24;
+    u8 __rcu *P24;
+    struct chunk __rcu *CK24;
+    u32 __rcu *C24;
+    u32 cnk24_count;/*Number of chunks in level 24*/
+
+    /*Level 32*/
+    u8 __rcu *N32;
+    u8 __rcu *P32;
+    u32 cnk32_count;/*Number of chunks in level 32*/
+
+    /*Index to this array is stored in N16, N24 and N32*/
+    struct net_device    *netdevs[NETDEV_COUNT_MAX];
+    u8 netdev_count;/*Number of netdevs*/
+
+    spinlock_t lock;
+};
+
+int sail_insert(struct sail *s, u32 key,
+        u8 prefix_len, struct net_device *dev);
+int sail_delete(struct sail *s, u32 key,
+        u8 prefix_len);
+int sail_flush(struct sail *s);
+int sail_lookup(const struct sail *s, const __be32 dest,
+        struct net_device **dev);
+#endif
+
 struct fib_nh_notifier_info {
     struct fib_notifier_info info; /* must be first */
     struct fib_nh *fib_nh;
@@ -219,6 +275,10 @@ struct fib_table {
     int            tb_num_default;
     struct rcu_head        rcu;
     unsigned long         *tb_data;
+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+    /*Each FIB table will have its own SAIL structure.*/
+    struct sail    sail;
+#endif
     unsigned long        __data[0];
 };

diff --git a/net/core/filter.c b/net/core/filter.c
index 5e00f2b..e89b4bb 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4236,6 +4236,49 @@ static int bpf_fib_set_fwd_params(struct
bpf_fib_lookup *params,
 }
 #endif

+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+static int sail_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
+               u32 flags, bool check_mtu)
+{
+    struct net_device *dev_in, *dev_out;
+    struct fib_table *tb;
+    struct neighbour *neigh;
+    u32 tbid;
+    int err;
+    u32 mtu;
+
+    if (flags & BPF_FIB_LOOKUP_DIRECT) {
+        dev_in = dev_get_by_index_rcu(net, params->ifindex);
+        if (unlikely(!dev_in))
+            return -ENODEV;
+        tbid = l3mdev_fib_table_rcu(dev_in) ? : RT_TABLE_MAIN;
+    } else {
+        tbid = RT_TABLE_MAIN;
+    }
+
+    tb = fib_get_table(net, tbid);
+    if (unlikely(!tb))
+        return BPF_FIB_LKUP_RET_NOT_FWDED;
+
+    err = sail_lookup(&tb->sail, params->ipv4_dst, &dev_out);
+    if (err)
+        return -ENOENT;
+
+    if (check_mtu) {
+        mtu = min(READ_ONCE(dev_out->mtu), IP_MAX_MTU);
+        if (params->tot_len > mtu)
+            return BPF_FIB_LKUP_RET_FRAG_NEEDED;
+    }
+
+    neigh = __ipv4_neigh_lookup_noref(dev_out,
+                      (__force u32)params->ipv4_dst);
+    if (!neigh)
+        return BPF_FIB_LKUP_RET_NO_NEIGH;
+
+    return bpf_fib_set_fwd_params(params, neigh, dev_out);
+}
+#endif
+
 #if IS_ENABLED(CONFIG_INET)
 static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
                    u32 flags, bool check_mtu)
@@ -4468,9 +4511,15 @@ BPF_CALL_4(bpf_xdp_fib_lookup, struct xdp_buff *, ctx,
     switch (params->family) {
 #if IS_ENABLED(CONFIG_INET)
     case AF_INET:
+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+        return sail_fib_lookup(dev_net(ctx->rxq->dev), params,
+                       flags, true);
+#else
         return bpf_ipv4_fib_lookup(dev_net(ctx->rxq->dev), params,
                        flags, true);
 #endif
+
+#endif
 #if IS_ENABLED(CONFIG_IPV6)
     case AF_INET6:
         return bpf_ipv6_fib_lookup(dev_net(ctx->rxq->dev), params,
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 32cae39..5c41071 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -52,6 +52,17 @@ config IP_ADVANCED_ROUTER

       If unsure, say N here.

+config FIB_SAIL_XDP
+    bool "SAIL based FIB lookup for XDP"
+    depends on !IP_ROUTE_MULTIPATH && !LWTUNNEL
+    default y
+    help
+      This option will enable SAIL based routing table lookup for XDP
+      forwarding. This will store FIB table as a SAIL (along with
+      LC-trie). Currently it only supports up to 255 ports. Currently
+      it does not support multi-path routing and light-weight
+      tunnels such as MPLS.
+
 config IP_FIB_TRIE_STATS
     bool "FIB TRIE statistics"
     depends on IP_ADVANCED_ROUTER
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 7446b98..55ff5e7 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
 obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
 obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
 obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
+obj-$(CONFIG_FIB_SAIL_XDP) += fib_sail_xdp.o

 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
               xfrm4_output.o xfrm4_protocol.o
diff --git a/net/ipv4/fib_sail_xdp.c b/net/ipv4/fib_sail_xdp.c
new file mode 100644
index 0000000..f3f56c5
--- /dev/null
+++ b/net/ipv4/fib_sail_xdp.c
@@ -0,0 +1,939 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018-19 MD Iftakharul Islam (Tamim) <mislam4@kent.edu>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version
+ *   2 of the License, or (at your option) any later version.
+ *
+ *
+ * This is SAIL_L based routing table lookup which was initially proposed in:
+ *
+ * Yang, Tong, Gaogang Xie, YanBiao Li, Qiaobin Fu, Alex X. Liu, Qi Li,
+ * and Laurent Mathy. "Guarantee IP lookup performance with FIB explosion."
+ * In ACM SIGCOMM Computer Communication Review, vol. 44, no. 4, pp. 39-50.
+ * ACM, 2014.
+ *
+ * It however deviates from the SAIL_L in three ways:
+ *
+ * 1. It pushes all the solid nodes in level 1~15 to level 16 whereas SAIL_L
+ * pushes them to either level 16, level 24 or level 32.
+ *
+ * 2. It pushes all the solid nodes in level 17~23 to level 24 whereas SAIL_L
+ * pushes them to either level 24 or level 32.
+ *
+ * 3. It adds a bitmap array, CK24 in addition to C24. This reduces the memory
+ * memory requirement of original C24 from 17.08 MB to 110KB for our example
+ * routing table.
+ */
+
+#include <net/ip_fib.h>
+
+/*The length of N16, P16 and C16 is 2^16*/
+#define LEVEL16_SIZE 65536
+
+/*Length of C24.*/
+#define C24_SIZE 1048576
+
+/*chunk size is 2^8*/
+#define CHUNK_SIZE 256
+
+/*Total number of chunks preallocated for level 24 and 32*/
+#define NUM_CHUNKS 16384
+
+/*Calculates the number of bits set to 1*/
+#define POPCNT(X) (hweight64(X))
+
+/*POPCNT of left-most N bits of X*/
+#define POPCNT_OFF(X, N) (hweight64(((1ULL << (N)) - 1) & (X)))
+
+/*Calculate index to C24 from CK26 chunk and chunk offset */
+static u64 calc_c24_idx(struct chunk c, u32 cnk_off)
+{
+    u8 part_idx, part_off;
+
+    part_idx = cnk_off / 64;
+    part_off = cnk_off % 64;
+
+    return c.start_index[part_idx] +
+        POPCNT_OFF(c.bitmap[part_idx], part_off);
+}
+
+/*Converts a net_device to corresponding netdev_index*/
+static u8 get_netdev_index(struct sail *s, struct net_device *dev)
+{
+    u8 i;
+
+    /*checks if the net_device is already seen; if yes then return the
+     *corresponding index
+     */
+    for (i = 0; i < s->netdev_count; i++) {
+        if (s->netdevs[i] == dev)
+            return i;
+    }
+    /*If the net_device is not previously seen, then add it to the array*/
+    s->netdevs[s->netdev_count++] = dev;
+    return s->netdev_count - 1;
+}
+
+/* Insert a new chunk to N24 and P24 at index chunk_id-1*/
+static int N24_insert(struct sail *s, u16 chunk_id)
+{
+    long long m;
+
+    if (chunk_id > (s->cnk24_count + 1) || chunk_id < 1) {
+        pr_err("Invalid chunk_id for level 26");
+        return -EINVAL;
+    }
+
+    if (s->cnk24_count >= NUM_CHUNKS) {
+        pr_err("Cannot insert a chunk. The chunk array is full");
+        return -EINVAL;
+    }
+
+    /*shift each element one step right to make
+     *space for the new one
+     */
+    m = (long long)s->cnk24_count * CHUNK_SIZE - 1;
+    for (; m >= (chunk_id - 1) * CHUNK_SIZE; m--) {
+        s->N24[m + CHUNK_SIZE] = s->N24[m];
+        s->P24[m + CHUNK_SIZE] = s->P24[m];
+    }
+
+    /*Reset the newly created chunk*/
+    m = (chunk_id - 1) * CHUNK_SIZE;
+    for (; m < chunk_id * CHUNK_SIZE; m++) {
+        s->N24[m] = 0;
+        s->P24[m] = 0;
+    }
+    return 0;
+}
+
+/* Insert a new chunk to CK24 at index chunk_id-1*/
+static int CK24_insert(struct sail *s, u16 chunk_id)
+{
+    long long m;
+
+    if (chunk_id > (s->cnk24_count + 1) || chunk_id < 1) {
+        pr_err("Invalid chunk_id for level 26");
+        return -EINVAL;
+    }
+
+    if (s->cnk24_count >= NUM_CHUNKS) {
+        pr_err("Cannot insert a chunk. The chunk array is full");
+        return -EINVAL;
+    }
+
+    /*shift each chunk one step right to make
+     *space for the new one
+     */
+    m = (long long)s->cnk24_count - 1;
+    for (; m >= (chunk_id - 1); m--)
+        s->CK24[m + 1] = s->CK24[m];
+
+    /*Reset the newly created empty chunk*/
+    for (m = 0; m < 4; m++) {
+        s->CK24[chunk_id - 1].bitmap[m] = 0;
+        s->CK24[chunk_id - 1].start_index[m] = 0;
+    }
+    return 0;
+}
+
+/* Insert a new chunk to level 24 at chunk_id-1. Note that Chunk ID
+ * starts from 1, not 0
+ */
+static int chunk24_insert(struct sail *s, u16 chunk_id)
+{
+    int err = 0;
+
+    err = N24_insert(s, chunk_id);
+    if (!err)
+        err = CK24_insert(s, chunk_id);
+    if (!err)
+        ++s->cnk24_count;
+    else
+        pr_err("Error in level 24 insertion");
+    return err;
+}
+
+/* Insert a new chunk to level 32 at chunk_id-1. Note that Chunk ID
+ * starts from 1, not 0
+ */
+static int chunk32_insert(struct sail *s, u32 chunk_id)
+{
+    long long m;
+
+    if (chunk_id > (s->cnk32_count + 1) || chunk_id < 1) {
+        pr_err("Invalid chunk_id for level 32");
+        return -EINVAL;
+    }
+
+    if (s->cnk32_count >= NUM_CHUNKS) {
+        pr_err("Cannot insert a new chunk. The chunk array is full");
+        return -EINVAL;
+    }
+
+    /*shift each element one step right to make
+     *space for the new one
+     */
+    m = (long long)s->cnk32_count * CHUNK_SIZE - 1;
+    for (; m >= (chunk_id - 1) * CHUNK_SIZE; m--) {
+        s->N32[m + CHUNK_SIZE] = s->N32[m];
+        s->P32[m + CHUNK_SIZE] = s->P32[m];
+    }
+
+    /*Reset the newly created empty chunk*/
+    m = (chunk_id - 1) * CHUNK_SIZE;
+    for (; m < chunk_id * CHUNK_SIZE; m++) {
+        s->N32[m] = 0;
+        s->P32[m] = 0;
+    }
+
+    ++s->cnk32_count;
+    return 0;
+}
+
+static int N24_delete(struct sail *s, u16 chunk_id)
+{
+    long long m;
+    u64 end_idx;
+
+    if (chunk_id > s->cnk24_count) {
+        pr_err("Invalid chunk_id to level 26");
+        return -EINVAL;
+    }
+
+    if (chunk_id < s->cnk24_count) {
+        /*shift each chunk one step left*/
+        m = (long long)chunk_id * CHUNK_SIZE;
+        end_idx = s->cnk24_count * CHUNK_SIZE - 1;
+        for (; m <= end_idx; m++) {
+            s->N24[m - CHUNK_SIZE] = s->N24[m];
+            s->P24[m - CHUNK_SIZE] = s->P24[m];
+        }
+    }
+
+    /*Reset the the last chunk*/
+    end_idx = s->cnk24_count * CHUNK_SIZE - 1;
+    m = (s->cnk24_count - 1) * CHUNK_SIZE;
+    for (; m <= end_idx; m++) {
+        s->N24[m] = 0;
+        s->P24[m] = 0;
+    }
+
+    return 0;
+}
+
+static int CK24_delete(struct sail *s, u16 chunk_id)
+{
+    long long m;
+
+    if (chunk_id > s->cnk24_count) {
+        pr_err("Invalid chunk_id to level 24");
+        return -EINVAL;
+    }
+
+    if (chunk_id < s->cnk24_count) {
+        /*shift each chunk one step left*/
+        m = (long long)chunk_id;
+        for (; m <= s->cnk24_count - 1; m++)
+            s->CK24[m - 1] = s->CK24[m];
+    }
+
+    /*Reset the the last chunk*/
+    for (m = 0; m < 4; m++) {
+        s->CK24[s->cnk24_count - 1].start_index[m] = 0;
+        s->CK24[s->cnk24_count - 1].bitmap[m] = 0;
+    }
+
+    return 0;
+}
+
+static int chunk24_delete(struct sail *s, u16 chunk_id)
+{
+    N24_delete(s, chunk_id);
+    CK24_delete(s, chunk_id);
+    --s->cnk24_count;
+    return 0;
+}
+
+static int chunk32_delete(struct sail *s, u32 chunk_id)
+{
+    long long m;
+    u64 end_idx;
+
+    if (chunk_id > s->cnk32_count) {
+        pr_err("Invalid chunk_id to level 32");
+        return -EINVAL;
+    }
+
+    if (chunk_id < s->cnk32_count) {
+        /*shift each chunk one step left*/
+        m = (long long)chunk_id * CHUNK_SIZE;
+        end_idx = s->cnk32_count * CHUNK_SIZE - 1;
+        for (; m <= end_idx; m++) {
+            s->N32[m - CHUNK_SIZE] = s->N32[m];
+            s->P32[m - CHUNK_SIZE] = s->P32[m];
+        }
+    }
+
+    /*Reset the the last chunk*/
+    end_idx = s->cnk32_count * CHUNK_SIZE - 1;
+    m = (s->cnk32_count - 1) * CHUNK_SIZE;
+    for (; m <= end_idx; m++) {
+        s->N32[m] = 0;
+        s->P32[m] = 0;
+    }
+
+    --s->cnk32_count;
+    return 0;
+}
+
+/*Calculate the chunk ID for level 24 based on C16*/
+static u16 calc_ckid24_from_C16(u16 *c16, u32 c16_size, u16 idx16)
+{
+    long long i;
+
+    if (idx16 >= c16_size) {
+        pr_err("Index needs to be smaller than arr_size");
+        return 0;
+    }
+
+    /*Find the first chunk ID to the left and increment that by 1*/
+    for (i = (long long)idx16 - 1; i >= 0; i--) {
+        if (c16[i] > 0)
+            return c16[i] + 1;
+    }
+
+    /*If there is no chunk to the left, then this is the first chunk*/
+    return 1;
+}
+
+/*Update C16 based on the newly inserted chunk*/
+static int update_C16(u16 *c16, u32 c16_size,
+              u16 idx16, u16 chunk_id)
+{
+    long long i;
+
+    if (idx16 >= c16_size) {
+        pr_err("Invalid index");
+        return -EINVAL;
+    }
+
+    c16[idx16] = chunk_id;
+
+    /* Increment chunk ID to the right */
+    for (i = idx16 + 1; i < c16_size; i++) {
+        if (c16[i] > 0)
+            c16[i]++;
+    }
+
+    return 0;
+}
+
+/*Remove Chunk ID for level 16*/
+static int C16_remove_chunkid(u16 *c16, u32 c16_size, u16 chunk_id)
+{
+    long long i;
+    bool found = false;
+
+    /*Check if the chunk ID already exists*/
+    for (i = 0; i < c16_size; i++) {
+        if (found && c16[i] > 0) {
+            c16[i]--;
+        } else if (c16[i] == chunk_id) {
+            c16[i] = 0;
+            found = true;
+        }
+    }
+
+    return 0;
+}
+
+static int C24_remove_chunkid(struct sail *s, u16 cnk_idx, u64 cnk_off)
+{
+    long long i;
+    bool found = false;
+    u32 chunk_id;
+    u8 part_idx, part_off;
+
+    part_idx = cnk_off / 64;
+    part_off = cnk_off % 64;
+
+    chunk_id = s->C24[calc_c24_idx(s->CK24[cnk_idx], cnk_off)];
+    s->CK24[cnk_idx].bitmap[part_idx] &= ~(1ULL << part_off);
+
+    for (i = 0; i < C24_SIZE; i++) {
+        if (s->C24[i] == chunk_id)
+            found = true;
+        else if (found && s->C24[i] > 0)
+            s->C24[i - 1] = s->C24[i];
+        else if (found && !s->C24[i])
+            break;
+    }
+
+    return 0;
+}
+
+ /* Check if a chunk in level 32 is being unused */
+static bool is_N32_chunk_unused(u8 *nh, u32 chunk_id)
+{
+    long long i;
+    long long start_index, end_index;
+
+    if (chunk_id < 1) {
+        pr_err("Invalid chunk ID");
+        return -EINVAL;
+    }
+
+    start_index = (long long)(chunk_id - 1) * CHUNK_SIZE;
+    end_index = (long long)chunk_id * CHUNK_SIZE - 1;
+    for (i = start_index; i <= end_index; i++) {
+        /*The chunk is being used*/
+        if (nh[i] > 0)
+            return false;
+    }
+
+    return true;
+}
+
+ /* Check if a chunk in level 24 is being unused*/
+static bool is_CK24_N24_chunk_unused(u8 *nh, struct chunk *ck, u16 chunk_id)
+{
+    long long i;
+    long long start_index, end_index;
+
+    if (chunk_id < 1) {
+        pr_err("Invalid chunk ID");
+        return -EINVAL;
+    }
+
+    start_index = (long long)(chunk_id - 1) * CHUNK_SIZE;
+    end_index = (long long)chunk_id * CHUNK_SIZE - 1;
+    for (i = start_index; i <= end_index; i++) {
+        /*The chunk is being used*/
+        if (nh[i] > 0)
+            return false;
+    }
+
+    if (ck->bitmap[0] || ck->bitmap[1] || ck->bitmap[2] || ck->bitmap[3])
+        return false;
+
+    return true;
+}
+
+/*Calculate the chunk ID for level 32 based on CK24 and C24*/
+static u32 calc_ckid32_from_ck24(struct chunk *ck24,
+                 u32 ck24_idx, u32 ck24_off, u32 *c24)
+{
+    long long i, j;
+    long long index = 0;
+    u8 part_idx, part_off;
+    struct chunk c;
+
+    part_idx = ck24_off / 64;
+    part_off = ck24_off % 64;
+    c = ck24[ck24_idx];
+
+    /*find the index to C24 where previous chunk ID would be found*/
+    if (c.bitmap[part_idx]) {
+        index = c.start_index[part_idx] +
+            POPCNT_OFF(c.bitmap[part_idx], part_off) - 1;
+        if (index >= 0)
+            goto index_found;
+    }
+
+    j = part_idx - 1;
+    for (i = (long long)ck24_idx; i >= 0; i--) {
+        for (; j >= 0; j--) {
+            if (ck24[i].bitmap[j]) {
+                index = ck24[i].start_index[j] +
+                    POPCNT(ck24[i].bitmap[j]) - 1;
+                goto index_found;
+            }
+        }
+        j = 3;
+    }
+
+    /*If there is no chunk to the left, then this is the first chunk*/
+    return 1;
+index_found:
+    if (index >= (C24_SIZE - 1)) {
+        pr_err("CK24 array is full. Cannot insert");
+        return 0;
+    } else if (c24[index] <= 0) {
+        pr_err("Invalid chunk ID");
+        return 0;
+    } else {
+        return c24[index] + 1;
+    }
+}
+
+/*Update CK24 and C24 based on the newly inserted chunk*/
+static int update_ck24_c24(struct chunk *ck24, u32 ck24_idx, u32 ck24_off,
+               u32 *c24, u32 cnk24_count, u32 chunk_id)
+{
+    long long i, j;
+    u64 index = 0;
+    u8 part_idx, part_off;
+
+    part_idx = ck24_off / 64;
+    part_off = ck24_off % 64;
+
+    if (ck24[ck24_idx].bitmap[part_idx] & (1ULL << part_off)) {
+        pr_err("Error: bitmap is already set");
+        return -EINVAL;
+    }
+
+    /*find the index where Chunk ID should be copied to*/
+    if (ck24[ck24_idx].bitmap[part_idx]) {
+        index = ck24[ck24_idx].start_index[part_idx] +
+            POPCNT_OFF(ck24[ck24_idx].bitmap[part_idx], part_off);
+        goto index_found;
+    }
+
+    /*Find a chunk to the left which is not empty*/
+    j = part_idx - 1;
+    for (i = (long long)ck24_idx; i >= 0; i--) {
+        for (; j >= 0; j--) {
+            if (ck24[i].bitmap[j]) {
+                index = ck24[i].start_index[j] +
+                    POPCNT(ck24[i].bitmap[j]);
+                goto index_found;
+            }
+        }
+        j = 3;
+    }
+
+index_found:
+    /* Move each element one step to the right to create a space for
+     * the new element. Also increment each element by 1
+     */
+    for (i = C24_SIZE - 2 ; i >= (long long)index; i--)
+        c24[i + 1] = (c24[i] > 0) ? c24[i] + 1 : c24[i];
+    /*Set the new Chunk ID*/
+    c24[index] = chunk_id;
+
+    /*This is the first element of this chunk*/
+    if (!ck24[ck24_idx].bitmap[part_idx])
+        ck24[ck24_idx].start_index[part_idx] = index;
+
+    ck24[ck24_idx].bitmap[part_idx] |= (1ULL << part_off);
+
+    /*Update offset of the chunks to the right*/
+    j = part_idx + 1;
+    for (i = (long long)ck24_idx; i < cnk24_count; i++) {
+        for (; j < 4; j++) {
+            if (ck24[i].bitmap[j])
+                ck24[i].start_index[j]++;
+        }
+        j = 0;
+    }
+
+    return 0;
+}
+
+int sail_insert(struct sail *s, u32 key, u8 prefix_len,
+        struct net_device *dev)
+{
+    int i;
+    u8 *n16, *p16, *n24, *p24, *n32, *p32;
+    u16 *c16;
+    u32 *c24;
+    struct chunk *ck24;
+    u16 chunk_id;
+    u16 n16_idx;/*Index to N16, P16 and C16*/
+    u64 n24_idx;/*Index to N24 and P24*/
+    u64 c24_idx;/*Index to C24*/
+    u32 ck24_idx;/*Index to CK24*/
+    u64 ck24_off;/*offset inside a chunk*/
+    u8 part_idx, part_off;
+    u64 n32_idx;/*Index to N32 and P32*/
+    u32 num_leafs;/*Number of leafs need to be inserted for this prefix*/
+    u8 netdev_index = get_netdev_index(s, dev);
+    int err = 0;
+
+    spin_lock(&s->lock);
+
+    /* Default route */
+    if (prefix_len == 0) {
+        s->def_nh = netdev_index;
+        goto finish;
+    }
+
+    /* Preallocate all the arrays at once*/
+    if (!s->N16) {
+        n16 = kcalloc(LEVEL16_SIZE, sizeof(*n16), GFP_ATOMIC);
+        p16 = kcalloc(LEVEL16_SIZE, sizeof(*p16), GFP_ATOMIC);
+        c16 = kcalloc(LEVEL16_SIZE, sizeof(*c16), GFP_ATOMIC);
+        n24 = kcalloc(NUM_CHUNKS * CHUNK_SIZE, sizeof(*n24),
+                  GFP_ATOMIC);
+        p24 = kcalloc(NUM_CHUNKS * CHUNK_SIZE, sizeof(*p24),
+                  GFP_ATOMIC);
+        ck24 = kcalloc(NUM_CHUNKS, sizeof(*ck24), GFP_ATOMIC);
+        c24 = kcalloc(C24_SIZE, sizeof(*c24), GFP_ATOMIC);
+        n32 = kcalloc(NUM_CHUNKS * CHUNK_SIZE, sizeof(*n32),
+                  GFP_ATOMIC);
+        p32 = kcalloc(NUM_CHUNKS * CHUNK_SIZE, sizeof(*p32),
+                  GFP_ATOMIC);
+
+        if (!n16 || !c16 || !p16 || !n24 || !p24 || !ck24 ||
+            !c24 || !n32 || !p32) {
+            kfree(n16);
+            kfree(c16);
+            kfree(p16);
+            kfree(n24);
+            kfree(p24);
+            kfree(ck24);
+            kfree(c24);
+            kfree(n32);
+            kfree(p32);
+            pr_err("Out of memory while preallocating  SAIL");
+            goto error;
+        }
+
+        RCU_INIT_POINTER(s->N16, n16);
+        RCU_INIT_POINTER(s->P16, p16);
+        RCU_INIT_POINTER(s->C16, c16);
+        RCU_INIT_POINTER(s->N24, n24);
+        RCU_INIT_POINTER(s->P24, p24);
+        RCU_INIT_POINTER(s->CK24, ck24);
+        RCU_INIT_POINTER(s->C24, c24);
+        RCU_INIT_POINTER(s->N32, n32);
+        RCU_INIT_POINTER(s->P32, p32);
+
+        synchronize_rcu();
+    }
+
+    /*Eextract 16 bits from LSB.*/
+    n16_idx = key >> 16;
+
+    if (prefix_len <= 16) {
+        /*All the leafs in level 1~16 will be stored in level 16.*/
+        num_leafs = 1U << (16 - prefix_len);
+        for (i = 0; i < num_leafs; i++) {
+            /*Longer prefix exists*/
+            if (s->P16[n16_idx + i] > prefix_len)
+                continue;
+            s->N16[n16_idx + i] = netdev_index;
+            s->P16[n16_idx + i] = prefix_len;
+        }
+        goto finish;
+    }
+
+    /* The length of the prefix is 21~32. So need to check if there is a
+     * chunk for this prefix in level 24. C16[..] = 0 indicates that there
+     * is no chunk, so need to insert one. The insertion works as
+     * following:
+     * 1. Calculate the chunk ID to level 24 from C16. The Chunk ID
+     * indicates where the new chunk should be inserted.
+     * 2. Insert a new chunk in level 24
+     * 3. Update the C16[] based on the newly inserted chunk
+     */
+    if (s->C16[n16_idx] == 0) {
+        /*Step 1*/
+        chunk_id = calc_ckid24_from_C16(s->C16, LEVEL16_SIZE, n16_idx);
+        if (!chunk_id)
+            goto error;
+        /*Step 2*/
+        err = chunk24_insert(s, chunk_id);
+        if (err)
+            goto error;
+        /*Step 3*/
+        err = update_C16(s->C16, LEVEL16_SIZE, n16_idx, chunk_id);
+        if (err)
+            goto error;
+    }
+
+    /*Extract bit 17~24 and calculate index to level 24*/
+    n24_idx = (s->C16[n16_idx] - 1) * CHUNK_SIZE + ((key & 65280) >> 8);
+    ck24_idx = s->C16[n16_idx] - 1;
+    ck24_off = (key & 65280) >> 8;
+
+    if (prefix_len <= 24) {
+        /*All the leafs in level 17~24 will be stored in level 24.*/
+        num_leafs = 1U << (24 - prefix_len);
+        for (i = 0; i < num_leafs; i++) {
+            /*Longer prefix exists*/
+            if (s->P24[n24_idx + i] > prefix_len)
+                continue;
+            s->N24[n24_idx + i] = netdev_index;
+            s->P24[n24_idx + i] = prefix_len;
+        }
+        goto finish;
+    }
+
+    /* The length of the prefix is 25~32, but there is no chunk for
+     * this prefix in level 32. So need to insert a new one.
+     * The insertion works as following:
+     * 1. Calculate the chunk ID to level 32 from CK24 and C24. The
+     * Chunk ID indicates where the new chunk should be inserted.
+     * 2. Insert a new chunk in level 32
+     * 3. Update the CK24 and C24 based on the newly inserted chunk
+     */
+    part_idx = ck24_off / 64;
+    part_off = ck24_off % 64;
+    if (!(s->CK24[ck24_idx].bitmap[part_idx] & (1ULL << part_off))) {
+        /*Step 1*/
+        chunk_id = calc_ckid32_from_ck24(s->CK24, ck24_idx,
+                         ck24_off, s->C24);
+        if (!chunk_id)
+            goto error;
+        /*Step 2*/
+        err = chunk32_insert(s, chunk_id);
+        if (err)
+            goto error;
+        /*Step 3*/
+        err = update_ck24_c24(s->CK24, ck24_idx, ck24_off,
+                      s->C24, s->cnk24_count, chunk_id);
+        if (err)
+            goto error;
+    }
+
+    c24_idx = calc_c24_idx(s->CK24[ck24_idx], ck24_off);
+    /*Extract 8 bit from MSB and calculate index to level 32*/
+    n32_idx = (s->C24[c24_idx] - 1) * CHUNK_SIZE + (key & 255);
+
+    if (prefix_len <= 32) {
+        /*All the leafs in level 25~32 will be stored in level 32.*/
+        num_leafs = 1U << (32 - prefix_len);
+        for (i = 0; i < num_leafs; i++) {
+            /*Longer prefix exists*/
+            if (s->P32[n32_idx + i] > prefix_len)
+                continue;
+            s->N32[n32_idx + i] = netdev_index;
+            s->P32[n32_idx + i] = prefix_len;
+        }
+        goto finish;
+    }
+
+error:
+    pr_err("Something went wrong in route insertion");
+finish:
+    spin_unlock(&s->lock);
+    return err;
+}
+
+int sail_delete(struct sail *s, u32 key, u8 prefix_len)
+{
+    int i;
+    u32 n16_idx;/*Index to N16, P16 and C16*/
+    u64 n24_idx;/*Index to level N24 and P24*/
+    u16 ck24_idx;/*Index to CK24*/
+    u64 ck24_off;/*Offset inside chunk in level 24*/
+    u64 n32_idx;/*Index to level N32 and P32*/
+    u32 consecutive_leafs;
+    int err = 0;
+    u32 chunkid_level32;
+    u8 part_idx, part_off;
+
+    spin_lock(&s->lock);
+
+    /* Simply ignore */
+    if (prefix_len == 0 || !s->N16)
+        goto error;
+
+    /*Eextract 16 bits from LSB.*/
+    n16_idx = key >> 16;
+
+    if (prefix_len <= 16) {
+        /*Level pushing*/
+        consecutive_leafs = 1U << (16 - prefix_len);
+        for (i = 0; i < consecutive_leafs; i++) {
+            /*Prefix len doesn't match*/
+            if (s->P16[n16_idx + i] != prefix_len)
+                continue;
+            s->N16[n16_idx + i] = 0;
+            s->P16[n16_idx + i] = 0;
+        }
+        goto finish;
+    }
+
+    /* The prefix_len is 17~32 but no chunk for the prefix*/
+    if (s->C16[n16_idx] == 0)
+        goto error;
+
+    ck24_idx = s->C16[n16_idx] - 1;
+    ck24_off = (key & 65280) >> 8;/*Extract bit 17~24 from the prefix*/
+    n24_idx = ck24_idx * CHUNK_SIZE + ck24_off;
+
+    if (prefix_len <= 24) {
+        /*Level pushing*/
+        consecutive_leafs = 1U << (24 - prefix_len);
+        for (i = 0; i < consecutive_leafs; i++) {
+            /*Prefix len doesn't match*/
+            if (s->P24[n24_idx + i] != prefix_len)
+                continue;
+            s->N24[n24_idx + i] = 0;
+            s->P24[n24_idx + i] = 0;
+        }
+        if (is_CK24_N24_chunk_unused(s->N24, &s->CK24[ck24_idx],
+                         s->C16[n16_idx])) {
+            chunk24_delete(s, s->C16[n16_idx]);
+            C16_remove_chunkid(s->C16, LEVEL16_SIZE,
+                       s->C16[n16_idx]);
+        }
+        goto finish;
+    }
+
+    part_idx = ck24_off / 64;
+    part_off = ck24_off % 64;
+    /* The prefix_len is 25~32. but no chunk for the prefix */
+    if (!(s->CK24[ck24_idx].bitmap[part_idx] & (1ULL << part_off)))
+        goto error;
+
+    chunkid_level32 = s->C24[calc_c24_idx(s->CK24[ck24_idx], ck24_off)];
+
+    /*Extract 8 bit from MSB and calculate index to level 32*/
+    n32_idx = (chunkid_level32 - 1) * CHUNK_SIZE + (key & 255);
+
+    if (prefix_len <= 32) {
+        /*Level pushing*/
+        consecutive_leafs = 1U << (32 - prefix_len);
+
+        for (i = 0; i < consecutive_leafs; i++) {
+            /*Prefix len doesn't match*/
+            if (s->P32[n32_idx + i] != prefix_len)
+                continue;
+            s->N32[n32_idx + i] = 0;
+            s->P32[n32_idx + i] = 0;
+        }
+        if (is_N32_chunk_unused(s->N32, chunkid_level32)) {
+            chunk32_delete(s, chunkid_level32);
+            C24_remove_chunkid(s, ck24_idx, ck24_off);
+        }
+        goto finish;
+    }
+
+/*The prefix was not found*/
+error:
+    err = -ENOENT;
+finish:
+    spin_unlock(&s->lock);
+    return err;
+}
+
+int sail_flush(struct sail *s)
+{
+    u8 *n16_old, *p16_old, *n24_old, *p24_old, *n32_old, *p32_old;
+    u16 *c16_old;
+    u32 *c24_old;
+    struct chunk *ck24_old;
+
+    spin_lock(&s->lock);
+
+    /*Save old pointers*/
+    n16_old = s->N16;
+    p16_old = s->P16;
+    c16_old = s->C16;
+    n24_old = s->N24;
+    p24_old = s->P24;
+    c24_old = s->C24;
+    ck24_old = s->CK24;
+    n32_old = s->N32;
+    p32_old = s->P32;
+
+    /*Set the counter before the chunk are deleted*/
+    s->cnk32_count = 0;
+    s->cnk24_count = 0;
+
+    /*Set the pointers to NULL*/
+    rcu_assign_pointer(s->N16, NULL);
+    rcu_assign_pointer(s->P16, NULL);
+    rcu_assign_pointer(s->C16, NULL);
+
+    rcu_assign_pointer(s->N24, NULL);
+    rcu_assign_pointer(s->P24, NULL);
+    rcu_assign_pointer(s->C24, NULL);
+    rcu_assign_pointer(s->CK24, NULL);
+
+    rcu_assign_pointer(s->N32, NULL);
+    rcu_assign_pointer(s->P32, NULL);
+
+    /* Wait for all references to be released */
+    synchronize_rcu();
+
+    /* Deallocate old references after setting them NULL*/
+    kfree(n16_old);
+    kfree(p16_old);
+    kfree(c16_old);
+    kfree(n24_old);
+    kfree(p24_old);
+    kfree(c24_old);
+    kfree(ck24_old);
+    kfree(n32_old);
+    kfree(p32_old);
+
+    spin_unlock(&s->lock);
+    return 0;
+}
+
+int sail_lookup(const struct sail *s,
+        const __be32 dest, struct net_device **dev)
+{
+    u8 *n16, *n24, *n32;
+    u16 *c16;
+    u32 *c24;
+    struct chunk *ck24;
+    const u32 key = ntohl(dest);
+    u8 netdev_index = s->def_nh;
+    u16 n16_idx;/*Index to N16 and C16*/
+    u64 n24_idx;/*Index to N24*/
+    u32 ck24_idx;/*Index to CK24*/
+    u64 ck24_off;/*Offset inside a chunk*/
+    u64 c24_idx;/*Index to C24*/
+    u64 n32_idx;/*Index to N32*/
+    u8 part_idx, part_off;
+
+    rcu_read_lock();
+
+    /*extract 16 bits from LSB*/
+    n16_idx = key >> 16;
+    n16 = rcu_dereference(s->N16);
+    if (unlikely(!n16))
+        goto finish;
+
+    if (likely(n16[n16_idx] != 0))
+        netdev_index = n16[n16_idx];
+
+    /*Check if there is a longer prefix; if yes, extract bit 17~24
+     *  and calculate index to N24
+     */
+    c16 = rcu_dereference(s->C16);
+    if (likely(c16[n16_idx] != 0)) {
+        ck24_idx = c16[n16_idx] - 1;
+        ck24_off = (key & 65280) >> 8;
+        n24_idx = ck24_idx * CHUNK_SIZE + ck24_off;
+    } else {
+        goto finish;
+    }
+
+    /*Find corresponding next-hop in level 24*/
+    n24 = rcu_dereference(s->N24);
+    if (likely(n24[n24_idx] != 0))
+        netdev_index = n24[n24_idx];
+
+    /*Check if there is a longer prefix; if yes, extract 8 bits
+     * from MSB and calculate index to N32
+     */
+    ck24 = rcu_dereference(s->CK24);
+    part_idx = ck24_off / 64;
+    part_off = ck24_off % 64;
+    if (likely(ck24[ck24_idx].bitmap[part_idx] & (1ULL << part_off))) {
+        c24 = rcu_dereference(s->C24);
+        c24_idx = ck24[ck24_idx].start_index[part_idx] +
+            POPCNT_OFF(ck24[ck24_idx].bitmap[part_idx], part_off);
+        n32_idx = (c24[c24_idx] - 1) * CHUNK_SIZE + (key & 255);
+    } else {
+        goto finish;
+    }
+
+    n32 = rcu_dereference(s->N32);
+    if (likely(n32[n32_idx] != 0))
+        netdev_index = n32[n32_idx];
+
+finish:
+    *dev = s->netdevs[netdev_index];
+    rcu_read_unlock();
+    return 0;
+}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 5bc0c89..d60fa45 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1280,6 +1280,10 @@ int fib_table_insert(struct net *net, struct
fib_table *tb,
     if (err)
         goto out_fib_notif;

+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+    sail_insert(&tb->sail, key, plen, fi->fib_dev);
+#endif
+
     if (!plen)
         tb->tb_num_default++;

@@ -1568,6 +1572,10 @@ int fib_table_delete(struct net *net, struct
fib_table *tb,

     pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);

+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+    sail_delete(&tb->sail, key, plen);
+#endif
+
     fa_to_delete = NULL;
     hlist_for_each_entry_from(fa, fa_list) {
         struct fib_info *fi = fa->fa_info;
@@ -1929,6 +1937,10 @@ int fib_table_flush(struct net *net, struct
fib_table *tb)
         }
     }

+#if IS_ENABLED(CONFIG_FIB_SAIL_XDP)
+    sail_flush(&tb->sail);
+#endif
+
     pr_debug("trie_flush found=%d\n", found);
     return found;
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCH 20/20] can: flexcan: use can_rx_offload_queue_sorted() for flexcan_irq_bus_*()
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Oleksij Rempel, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Oleksij Rempel <o.rempel@pengutronix.de>

Currently, in case of bus error, driver will generate error message and put
in the tail of the message queue. To avoid confusions, this change should
place the bus related messages in proper order.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 5923bd0ec118..75ce11395ee8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -561,9 +561,13 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_regs __iomem *regs = priv->regs;
 	struct sk_buff *skb;
 	struct can_frame *cf;
 	bool rx_errors = false, tx_errors = false;
+	u32 timestamp;
+
+	timestamp = priv->read(&regs->timer) << 16;
 
 	skb = alloc_can_err_skb(dev, &cf);
 	if (unlikely(!skb))
@@ -610,17 +614,21 @@ static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
 	if (tx_errors)
 		dev->stats.tx_errors++;
 
-	can_rx_offload_queue_tail(&priv->offload, skb);
+	can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
 }
 
 static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_regs __iomem *regs = priv->regs;
 	struct sk_buff *skb;
 	struct can_frame *cf;
 	enum can_state new_state, rx_state, tx_state;
 	int flt;
 	struct can_berr_counter bec;
+	u32 timestamp;
+
+	timestamp = priv->read(&regs->timer) << 16;
 
 	flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
 	if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
@@ -650,7 +658,7 @@ static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
 	if (unlikely(new_state == CAN_STATE_BUS_OFF))
 		can_bus_off(dev);
 
-	can_rx_offload_queue_tail(&priv->offload, skb);
+	can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
 }
 
 static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload)
-- 
2.19.1

^ permalink raw reply related

* [PATCH 19/20] can: rx-offload: rename can_rx_offload_irq_queue_err_skb() to can_rx_offload_queue_tail()
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Oleksij Rempel, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Oleksij Rempel <o.rempel@pengutronix.de>

This function has nothing todo with error.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c      | 4 ++--
 drivers/net/can/rx-offload.c   | 5 +++--
 include/linux/can/rx-offload.h | 3 ++-
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 41a175f80c4b..5923bd0ec118 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -610,7 +610,7 @@ static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
 	if (tx_errors)
 		dev->stats.tx_errors++;
 
-	can_rx_offload_irq_queue_err_skb(&priv->offload, skb);
+	can_rx_offload_queue_tail(&priv->offload, skb);
 }
 
 static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
@@ -650,7 +650,7 @@ static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
 	if (unlikely(new_state == CAN_STATE_BUS_OFF))
 		can_bus_off(dev);
 
-	can_rx_offload_irq_queue_err_skb(&priv->offload, skb);
+	can_rx_offload_queue_tail(&priv->offload, skb);
 }
 
 static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload)
diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/rx-offload.c
index c368686e2164..2ce4fa8698c7 100644
--- a/drivers/net/can/rx-offload.c
+++ b/drivers/net/can/rx-offload.c
@@ -257,7 +257,8 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb);
 
-int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb)
+int can_rx_offload_queue_tail(struct can_rx_offload *offload,
+			      struct sk_buff *skb)
 {
 	if (skb_queue_len(&offload->skb_queue) >
 	    offload->skb_queue_len_max)
@@ -268,7 +269,7 @@ int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_b
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(can_rx_offload_irq_queue_err_skb);
+EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
 
 static int can_rx_offload_init_queue(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight)
 {
diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h
index 01a7c9e5d8d8..8268811a697e 100644
--- a/include/linux/can/rx-offload.h
+++ b/include/linux/can/rx-offload.h
@@ -45,7 +45,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
 				struct sk_buff *skb, u32 timestamp);
 unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
 					 unsigned int idx, u32 timestamp);
-int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb);
+int can_rx_offload_queue_tail(struct can_rx_offload *offload,
+			      struct sk_buff *skb);
 void can_rx_offload_reset(struct can_rx_offload *offload);
 void can_rx_offload_del(struct can_rx_offload *offload);
 void can_rx_offload_enable(struct can_rx_offload *offload);
-- 
2.19.1

^ permalink raw reply related

* [PATCH 18/20] can: flexcan: handle tx-complete CAN frames via rx-offload infrastructure
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Oleksij Rempel, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Oleksij Rempel <o.rempel@pengutronix.de>

Current flexcan driver will put TX-ECHO in regular unsorted way, in
this case TX-ECHO can come after the response to the same TXed message.
In some cases, for example for J1939 stack, things will break.
This patch is using new rx-offload API to put the messages just in the
right place.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 68b46395c580..41a175f80c4b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -787,8 +787,11 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 
 	/* transmission complete interrupt */
 	if (reg_iflag2 & FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB)) {
+		u32 reg_ctrl = priv->read(&regs->mb[FLEXCAN_TX_MB].can_ctrl);
+
 		handled = IRQ_HANDLED;
-		stats->tx_bytes += can_get_echo_skb(dev, 0);
+		stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload,
+							       0, reg_ctrl << 16);
 		stats->tx_packets++;
 		can_led_event(dev, CAN_LED_EVENT_TX);
 
-- 
2.19.1

^ permalink raw reply related

* [PATCH 17/20] can: rx-offload: introduce can_rx_offload_get_echo_skb() and can_rx_offload_queue_sorted() functions
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Oleksij Rempel, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Oleksij Rempel <o.rempel@pengutronix.de>

Current CAN framework can't guarantee proper/chronological order
of RX and TX-ECHO messages. To make this possible, drivers should use
this functions instead of can_get_echo_skb().

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/rx-offload.c   | 46 ++++++++++++++++++++++++++++++++++
 include/linux/can/rx-offload.h |  4 +++
 2 files changed, 50 insertions(+)

diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/rx-offload.c
index c7d05027a7a0..c368686e2164 100644
--- a/drivers/net/can/rx-offload.c
+++ b/drivers/net/can/rx-offload.c
@@ -211,6 +211,52 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
 
+int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
+				struct sk_buff *skb, u32 timestamp)
+{
+	struct can_rx_offload_cb *cb;
+	unsigned long flags;
+
+	if (skb_queue_len(&offload->skb_queue) >
+	    offload->skb_queue_len_max)
+		return -ENOMEM;
+
+	cb = can_rx_offload_get_cb(skb);
+	cb->timestamp = timestamp;
+
+	spin_lock_irqsave(&offload->skb_queue.lock, flags);
+	__skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare);
+	spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
+
+	can_rx_offload_schedule(offload);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_queue_sorted);
+
+unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
+					 unsigned int idx, u32 timestamp)
+{
+	struct net_device *dev = offload->dev;
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	u8 len;
+	int err;
+
+	skb = __can_get_echo_skb(dev, idx, &len);
+	if (!skb)
+		return 0;
+
+	err = can_rx_offload_queue_sorted(offload, skb, timestamp);
+	if (err) {
+		stats->rx_errors++;
+		stats->tx_fifo_errors++;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb);
+
 int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb)
 {
 	if (skb_queue_len(&offload->skb_queue) >
diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h
index cb31683bbe15..01a7c9e5d8d8 100644
--- a/include/linux/can/rx-offload.h
+++ b/include/linux/can/rx-offload.h
@@ -41,6 +41,10 @@ int can_rx_offload_add_timestamp(struct net_device *dev, struct can_rx_offload *
 int can_rx_offload_add_fifo(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight);
 int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 reg);
 int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload);
+int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
+				struct sk_buff *skb, u32 timestamp);
+unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
+					 unsigned int idx, u32 timestamp);
 int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb);
 void can_rx_offload_reset(struct can_rx_offload *offload);
 void can_rx_offload_del(struct can_rx_offload *offload);
-- 
2.19.1

^ permalink raw reply related

* [PATCH 16/20] can: dev: __can_get_echo_skb(): print error message, if trying to echo non existing skb
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

Prior to echoing a successfully transmitted CAN frame (by calling
can_get_echo_skb()), CAN drivers have to put the CAN frame (by calling
can_put_echo_skb() in the transmit function). These put and get function
take an index as parameter, which is used to identify the CAN frame.

A driver calling can_get_echo_skb() with a index not pointing to a skb
is a BUG, so add an appropriate error message.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index c05e4d50d43d..3b3f88ffab53 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -480,6 +480,8 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 {
 	struct can_priv *priv = netdev_priv(dev);
+	struct sk_buff *skb = priv->echo_skb[idx];
+	struct canfd_frame *cf;
 
 	if (idx >= priv->echo_skb_max) {
 		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -487,21 +489,20 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
 		return NULL;
 	}
 
-	if (priv->echo_skb[idx]) {
-		/* Using "struct canfd_frame::len" for the frame
-		 * length is supported on both CAN and CANFD frames.
-		 */
-		struct sk_buff *skb = priv->echo_skb[idx];
-		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
-		u8 len = cf->len;
-
-		*len_ptr = len;
-		priv->echo_skb[idx] = NULL;
-
-		return skb;
+	if (!skb) {
+		netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
+			   __func__, idx);
+		return NULL;
 	}
 
-	return NULL;
+	/* Using "struct canfd_frame::len" for the frame
+	 * length is supported on both CAN and CANFD frames.
+	 */
+	cf = (struct canfd_frame *)skb->data;
+	*len_ptr = cf->len;
+	priv->echo_skb[idx] = NULL;
+
+	return skb;
 }
 
 /*
-- 
2.19.1

^ permalink raw reply related

* [PATCH 15/20] can: dev: __can_get_echo_skb(): Don't crash the kernel if can_priv::echo_skb is accessed out of bounds
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

If the "struct can_priv::echo_skb" is accessed out of bounds would lead
to a kernel crash. Better print a sensible warning message instead and
try to recover.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 46cc5fec4043..c05e4d50d43d 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -481,7 +481,11 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
 {
 	struct can_priv *priv = netdev_priv(dev);
 
-	BUG_ON(idx >= priv->echo_skb_max);
+	if (idx >= priv->echo_skb_max) {
+		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
+			   __func__, idx, priv->echo_skb_max);
+		return NULL;
+	}
 
 	if (priv->echo_skb[idx]) {
 		/* Using "struct canfd_frame::len" for the frame
-- 
2.19.1

^ permalink raw reply related

* [PATCH 14/20] can: dev: __can_get_echo_skb(): replace struct can_frame by canfd_frame to access frame length
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

This patch replaces the use of "struct can_frame::can_dlc" by "struct
canfd_frame::len" to access the frame's length. As it is ensured that
both structures have a compatible memory layout for this member this is
no functional change. Futher, this compatibility is documented in a
comment.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 80530ab37b1e..46cc5fec4043 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -484,11 +484,14 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
 	BUG_ON(idx >= priv->echo_skb_max);
 
 	if (priv->echo_skb[idx]) {
+		/* Using "struct canfd_frame::len" for the frame
+		 * length is supported on both CAN and CANFD frames.
+		 */
 		struct sk_buff *skb = priv->echo_skb[idx];
-		struct can_frame *cf = (struct can_frame *)skb->data;
-		u8 dlc = cf->can_dlc;
+		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+		u8 len = cf->len;
 
-		*len_ptr = dlc;
+		*len_ptr = len;
 		priv->echo_skb[idx] = NULL;
 
 		return skb;
-- 
2.19.1

^ permalink raw reply related

* [PATCH 12/20] can: flexcan: remove not needed struct flexcan_priv::tx_mb and struct flexcan_priv::tx_mb_idx
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

The previous patch changes the TX path to always use the last mailbox
regardless of the used offload scheme (rx-fifo or timestamp based). This
means members "tx_mb" and "tx_mb_idx" of the struct flexcan_priv don't
depend on the offload scheme, so replace them by compile time constants.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 677c41701cf3..68b46395c580 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -258,9 +258,7 @@ struct flexcan_priv {
 	struct can_rx_offload offload;
 
 	struct flexcan_regs __iomem *regs;
-	struct flexcan_mb __iomem *tx_mb;
 	struct flexcan_mb __iomem *tx_mb_reserved;
-	u8 tx_mb_idx;
 	u32 reg_ctrl_default;
 	u32 reg_imask1_default;
 	u32 reg_imask2_default;
@@ -514,6 +512,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
 static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_regs __iomem *regs = priv->regs;
 	struct can_frame *cf = (struct can_frame *)skb->data;
 	u32 can_id;
 	u32 data;
@@ -536,17 +535,17 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 
 	if (cf->can_dlc > 0) {
 		data = be32_to_cpup((__be32 *)&cf->data[0]);
-		priv->write(data, &priv->tx_mb->data[0]);
+		priv->write(data, &regs->mb[FLEXCAN_TX_MB].data[0]);
 	}
 	if (cf->can_dlc > 4) {
 		data = be32_to_cpup((__be32 *)&cf->data[4]);
-		priv->write(data, &priv->tx_mb->data[1]);
+		priv->write(data, &regs->mb[FLEXCAN_TX_MB].data[1]);
 	}
 
 	can_put_echo_skb(skb, dev, 0);
 
-	priv->write(can_id, &priv->tx_mb->can_id);
-	priv->write(ctrl, &priv->tx_mb->can_ctrl);
+	priv->write(can_id, &regs->mb[FLEXCAN_TX_MB].can_id);
+	priv->write(ctrl, &regs->mb[FLEXCAN_TX_MB].can_ctrl);
 
 	/* Errata ERR005829 step8:
 	 * Write twice INACTIVE(0x8) code to first MB.
@@ -737,7 +736,7 @@ static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)
 	u32 iflag1, iflag2;
 
 	iflag2 = priv->read(&regs->iflag2) & priv->reg_imask2_default &
-		~FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
+		~FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);
 	iflag1 = priv->read(&regs->iflag1) & priv->reg_imask1_default;
 
 	return (u64)iflag2 << 32 | iflag1;
@@ -787,7 +786,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	reg_iflag2 = priv->read(&regs->iflag2);
 
 	/* transmission complete interrupt */
-	if (reg_iflag2 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) {
+	if (reg_iflag2 & FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB)) {
 		handled = IRQ_HANDLED;
 		stats->tx_bytes += can_get_echo_skb(dev, 0);
 		stats->tx_packets++;
@@ -795,8 +794,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 
 		/* after sending a RTR frame MB is in RX mode */
 		priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
-			    &priv->tx_mb->can_ctrl);
-		priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), &regs->iflag2);
+			    &regs->mb[FLEXCAN_TX_MB].can_ctrl);
+		priv->write(FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB), &regs->iflag2);
 		netif_wake_queue(dev);
 	}
 
@@ -938,7 +937,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
 	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
 		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ |
-		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_MB);
 
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
 		reg_mcr &= ~FLEXCAN_MCR_FEN;
@@ -1006,7 +1005,7 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	/* mark TX mailbox as INACTIVE */
 	priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		    &priv->tx_mb->can_ctrl);
+		    &regs->mb[FLEXCAN_TX_MB].can_ctrl);
 
 	/* acceptance mask/acceptance code (accept everything) */
 	priv->write(0x0, &regs->rxgmask);
@@ -1365,11 +1364,9 @@ static int flexcan_probe(struct platform_device *pdev)
 		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP];
 	else
 		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_FIFO];
-	priv->tx_mb_idx = FLEXCAN_TX_MB;
-	priv->tx_mb = &regs->mb[priv->tx_mb_idx];
 
 	priv->reg_imask1_default = 0;
-	priv->reg_imask2_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
+	priv->reg_imask2_default = FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);
 
 	priv->offload.mailbox_read = flexcan_mailbox_read;
 
-- 
2.19.1

^ permalink raw reply related

* [PATCH 11/20] can: flexcan: Always use last mailbox for TX
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Alexander Stein, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Alexander Stein <alexander.stein@systec-electronic.com>

Essentially this patch moves the TX mailbox to position 63, regardless
of timestamp based offloading or RX FIFO. So mainly the iflag register
usage regarding TX has changed. The rest is consolidating RX FIFO and
timestamp offloading as they now use both the same TX mailbox.

The reason is a very annoying behavior regarding sending RTR frames when
_not_ using RX FIFO:

If a TX mailbox sent a RTR frame it becomes a RX mailbox. For that
reason flexcan_irq disables the TX mailbox again. But if during the time
the RTR was sent and the TX mailbox is disabled a new CAN frames is
received, it is lost without notice. The reason is that so-called
"Move-in" process starts from the lowest mailbox which happen to be a TX
mailbox set to EMPTY.

Steps to reproduce (I used an imx7d):
1. generate regular bursts of messages
2. send a RTR from flexcan with higher priority than burst messages every
   1ms, e.g. cangen -I 0x100 -L 0 -g 1 -R can0
3. notice a lost message without notification after some seconds

When running an iperf in parallel this problem is occurring even more
frequently. Using filters is not possible as at least one single CAN-ID
is allowed. Handling the TX MB during RX is also not possible as there
is no race-free disable of RX MB.

There is still a slight window when the described problem can occur. But
for that all RX MB must be in use which is essentially next to an
overrun. Still there will be no indication if it ever occurs.

Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 67 +++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 34 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 0431f8d05518..677c41701cf3 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -135,13 +135,12 @@
 
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 /* Errata ERR005829 step7: Reserve first valid MB */
-#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO	8
-#define FLEXCAN_TX_MB_OFF_FIFO		9
+#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO		8
 #define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP	0
-#define FLEXCAN_TX_MB_OFF_TIMESTAMP		1
-#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST	(FLEXCAN_TX_MB_OFF_TIMESTAMP + 1)
-#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST	63
-#define FLEXCAN_IFLAG_MB(x)		BIT(x)
+#define FLEXCAN_TX_MB				63
+#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST	(FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1)
+#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST	(FLEXCAN_TX_MB - 1)
+#define FLEXCAN_IFLAG_MB(x)		BIT(x & 0x1f)
 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW	BIT(7)
 #define FLEXCAN_IFLAG_RX_FIFO_WARN	BIT(6)
 #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE	BIT(5)
@@ -737,9 +736,9 @@ static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)
 	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 iflag1, iflag2;
 
-	iflag2 = priv->read(&regs->iflag2) & priv->reg_imask2_default;
-	iflag1 = priv->read(&regs->iflag1) & priv->reg_imask1_default &
+	iflag2 = priv->read(&regs->iflag2) & priv->reg_imask2_default &
 		~FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
+	iflag1 = priv->read(&regs->iflag1) & priv->reg_imask1_default;
 
 	return (u64)iflag2 << 32 | iflag1;
 }
@@ -751,11 +750,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->regs;
 	irqreturn_t handled = IRQ_NONE;
-	u32 reg_iflag1, reg_esr;
+	u32 reg_iflag2, reg_esr;
 	enum can_state last_state = priv->can.state;
 
-	reg_iflag1 = priv->read(&regs->iflag1);
-
 	/* reception interrupt */
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
 		u64 reg_iflag;
@@ -769,6 +766,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 				break;
 		}
 	} else {
+		u32 reg_iflag1;
+
+		reg_iflag1 = priv->read(&regs->iflag1);
 		if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) {
 			handled = IRQ_HANDLED;
 			can_rx_offload_irq_offload_fifo(&priv->offload);
@@ -784,8 +784,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 		}
 	}
 
+	reg_iflag2 = priv->read(&regs->iflag2);
+
 	/* transmission complete interrupt */
-	if (reg_iflag1 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) {
+	if (reg_iflag2 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) {
 		handled = IRQ_HANDLED;
 		stats->tx_bytes += can_get_echo_skb(dev, 0);
 		stats->tx_packets++;
@@ -794,7 +796,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 		/* after sending a RTR frame MB is in RX mode */
 		priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
 			    &priv->tx_mb->can_ctrl);
-		priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), &regs->iflag1);
+		priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), &regs->iflag2);
 		netif_wake_queue(dev);
 	}
 
@@ -936,15 +938,13 @@ static int flexcan_chip_start(struct net_device *dev)
 	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
 	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
 		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ |
-		FLEXCAN_MCR_IDAM_C;
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
 
-	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
 		reg_mcr &= ~FLEXCAN_MCR_FEN;
-		reg_mcr |= FLEXCAN_MCR_MAXMB(priv->offload.mb_last);
-	} else {
-		reg_mcr |= FLEXCAN_MCR_FEN |
-			FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
-	}
+	else
+		reg_mcr |= FLEXCAN_MCR_FEN;
+
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	priv->write(reg_mcr, &regs->mcr);
 
@@ -987,16 +987,17 @@ static int flexcan_chip_start(struct net_device *dev)
 		priv->write(reg_ctrl2, &regs->ctrl2);
 	}
 
-	/* clear and invalidate all mailboxes first */
-	for (i = priv->tx_mb_idx; i < ARRAY_SIZE(regs->mb); i++) {
-		priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
-			    &regs->mb[i].can_ctrl);
-	}
-
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
-		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++)
+		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {
 			priv->write(FLEXCAN_MB_CODE_RX_EMPTY,
 				    &regs->mb[i].can_ctrl);
+		}
+	} else {
+		/* clear and invalidate unused mailboxes first */
+		for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= ARRAY_SIZE(regs->mb); i++) {
+			priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
+				    &regs->mb[i].can_ctrl);
+		}
 	}
 
 	/* Errata ERR005829: mark first TX mailbox as INACTIVE */
@@ -1360,17 +1361,15 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->devtype_data = devtype_data;
 	priv->reg_xceiver = reg_xceiver;
 
-	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
-		priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_TIMESTAMP;
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
 		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP];
-	} else {
-		priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_FIFO;
+	else
 		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_FIFO];
-	}
+	priv->tx_mb_idx = FLEXCAN_TX_MB;
 	priv->tx_mb = &regs->mb[priv->tx_mb_idx];
 
-	priv->reg_imask1_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
-	priv->reg_imask2_default = 0;
+	priv->reg_imask1_default = 0;
+	priv->reg_imask2_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
 
 	priv->offload.mailbox_read = flexcan_mailbox_read;
 
-- 
2.19.1

^ permalink raw reply related

* [PATCH 09/20] can: hi311x: Use level-triggered interrupt
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Lukas Wunner, Mathias Duckeck,
	Akshay Bhat, Casey Fitzpatrick, linux-stable, Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Lukas Wunner <lukas@wunner.de>

If the hi3110 shares the SPI bus with another traffic-intensive device
and packets are received in high volume (by a separate machine sending
with "cangen -g 0 -i -x"), reception stops after a few minutes and the
counter in /proc/interrupts stops incrementing.  Bus state is "active".
Bringing the interface down and back up reconvenes the reception.  The
issue is not observed when the hi3110 is the sole device on the SPI bus.

Using a level-triggered interrupt makes the issue go away and lets the
hi3110 successfully receive 2 GByte over the course of 5 days while a
ks8851 Ethernet chip on the same SPI bus handles 6 GByte of traffic.

Unfortunately the hi3110 datasheet is mum on the trigger type.  The pin
description on page 3 only specifies the polarity (active high):
http://www.holtic.com/documents/371-hi-3110_v-rev-kpdf.do

Cc: Mathias Duckeck <m.duckeck@kunbus.de>
Cc: Akshay Bhat <akshay.bhat@timesys.com>
Cc: Casey Fitzpatrick <casey.fitzpatrick@timesys.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 Documentation/devicetree/bindings/net/can/holt_hi311x.txt | 2 +-
 drivers/net/can/spi/hi311x.c                              | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/can/holt_hi311x.txt b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
index 903a78da65be..3a9926f99937 100644
--- a/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
+++ b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
@@ -17,7 +17,7 @@ Example:
 		reg = <1>;
 		clocks = <&clk32m>;
 		interrupt-parent = <&gpio4>;
-		interrupts = <13 IRQ_TYPE_EDGE_RISING>;
+		interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
 		vdd-supply = <&reg5v0>;
 		xceiver-supply = <&reg5v0>;
 	};
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index 53e320c92a8b..ddaf46239e39 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -760,7 +760,7 @@ static int hi3110_open(struct net_device *net)
 {
 	struct hi3110_priv *priv = netdev_priv(net);
 	struct spi_device *spi = priv->spi;
-	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
+	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_HIGH;
 	int ret;
 
 	ret = open_candev(net);
-- 
2.19.1

^ permalink raw reply related

* [PATCH 03/20] can: kvaser_usb: Fix accessing freed memory in kvaser_usb_start_xmit()
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Jimmy Assarsson, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Jimmy Assarsson <jimmyassarsson@gmail.com>

The call to can_put_echo_skb() may result in the skb being freed. The skb
is later used in the call to dev->ops->dev_frame_to_cmd().

This is avoided by moving the call to can_put_echo_skb() after
dev->ops->dev_frame_to_cmd().

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jimmy Assarsson <jimmyassarsson@gmail.com>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index b939a4c10b84..c89c7d4900d7 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -528,7 +528,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 			context = &priv->tx_contexts[i];
 
 			context->echo_index = i;
-			can_put_echo_skb(skb, netdev, context->echo_index);
 			++priv->active_tx_contexts;
 			if (priv->active_tx_contexts >= (int)dev->max_tx_urbs)
 				netif_stop_queue(netdev);
@@ -553,7 +552,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 		dev_kfree_skb(skb);
 		spin_lock_irqsave(&priv->tx_contexts_lock, flags);
 
-		can_free_echo_skb(netdev, context->echo_index);
 		context->echo_index = dev->max_tx_urbs;
 		--priv->active_tx_contexts;
 		netif_wake_queue(netdev);
@@ -564,6 +562,8 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 
 	context->priv = priv;
 
+	can_put_echo_skb(skb, netdev, context->echo_index);
+
 	usb_fill_bulk_urb(urb, dev->udev,
 			  usb_sndbulkpipe(dev->udev,
 					  dev->bulk_out->bEndpointAddress),
-- 
2.19.1

^ permalink raw reply related

* [PATCH 02/20] can: kvaser_usb: Fix potential uninitialized variable use
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Jimmy Assarsson, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Jimmy Assarsson <jimmyassarsson@gmail.com>

If alloc_can_err_skb() fails, cf is never initialized.
Move assignment of cf inside check.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jimmy Assarsson <jimmyassarsson@gmail.com>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index c084bae5ec0a..5fc0be564274 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -1019,6 +1019,11 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
 					new_state : CAN_STATE_ERROR_ACTIVE;
 
 			can_change_state(netdev, cf, tx_state, rx_state);
+
+			if (priv->can.restart_ms &&
+			    old_state >= CAN_STATE_BUS_OFF &&
+			    new_state < CAN_STATE_BUS_OFF)
+				cf->can_id |= CAN_ERR_RESTARTED;
 		}
 
 		if (new_state == CAN_STATE_BUS_OFF) {
@@ -1028,11 +1033,6 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
 
 			can_bus_off(netdev);
 		}
-
-		if (priv->can.restart_ms &&
-		    old_state >= CAN_STATE_BUS_OFF &&
-		    new_state < CAN_STATE_BUS_OFF)
-			cf->can_id |= CAN_ERR_RESTARTED;
 	}
 
 	if (!skb) {
-- 
2.19.1

^ permalink raw reply related

* [PATCH 01/20] can: raw: check for CAN FD capable netdev in raw_sendmsg()
From: Marc Kleine-Budde @ 2018-11-12 11:57 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, Oliver Hartkopp, linux-stable,
	Marc Kleine-Budde
In-Reply-To: <20181112115728.18331-1-mkl@pengutronix.de>

From: Oliver Hartkopp <socketcan@hartkopp.net>

When the socket is CAN FD enabled it can handle CAN FD frame
transmissions.  Add an additional check in raw_sendmsg() as a CAN2.0 CAN
driver (non CAN FD) should never see a CAN FD frame. Due to the commonly
used can_dropped_invalid_skb() function the CAN 2.0 driver would drop
that CAN FD frame anyway - but with this patch the user gets a proper
-EINVAL return code.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 net/can/raw.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/net/can/raw.c b/net/can/raw.c
index 1051eee82581..3aab7664933f 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -745,18 +745,19 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 	} else
 		ifindex = ro->ifindex;
 
-	if (ro->fd_frames) {
+	dev = dev_get_by_index(sock_net(sk), ifindex);
+	if (!dev)
+		return -ENXIO;
+
+	err = -EINVAL;
+	if (ro->fd_frames && dev->mtu == CANFD_MTU) {
 		if (unlikely(size != CANFD_MTU && size != CAN_MTU))
-			return -EINVAL;
+			goto put_dev;
 	} else {
 		if (unlikely(size != CAN_MTU))
-			return -EINVAL;
+			goto put_dev;
 	}
 
-	dev = dev_get_by_index(sock_net(sk), ifindex);
-	if (!dev)
-		return -ENXIO;
-
 	skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
 				  msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
-- 
2.19.1

^ permalink raw reply related

* Re: [RFC] mm: Replace all open encodings for NUMA_NO_NODE
From: Anshuman Khandual @ 2018-11-12 11:47 UTC (permalink / raw)
  To: Hans Verkuil, linux-mm, linux-kernel
  Cc: ocfs2-devel, linux-fbdev, dri-devel, netdev, intel-wired-lan,
	linux-media, iommu, linux-rdma, dmaengine, linux-block,
	sparclinux, linuxppc-dev, linux-ia64, linux-alpha
In-Reply-To: <de754de5-cdf9-87d2-7ab2-a3630c034121@xs4all.nl>



On 11/12/2018 02:13 PM, Hans Verkuil wrote:
> On 11/12/2018 03:41 AM, Anshuman Khandual wrote:
>> At present there are multiple places where invalid node number is encoded
>> as -1. Even though implicitly understood it is always better to have macros
>> in there. Replace these open encodings for an invalid node number with the
>> global macro NUMA_NO_NODE. This helps remove NUMA related assumptions like
>> 'invalid node' from various places redirecting them to a common definition.
>>
>> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
>> ---
>> Build tested this with multiple cross compiler options like alpha, sparc,
>> arm64, x86, powerpc64le etc with their default config which might not have
>> compiled tested all driver related changes. I will appreciate folks giving
>> this a test in their respective build environment.
>>
>> All these places for replacement were found by running the following grep
>> patterns on the entire kernel code. Please let me know if this might have
>> missed some instances. This might also have replaced some false positives.
>> I will appreciate suggestions, inputs and review.
> The 'node' in the drivers/media and the drivers/video sources has nothing to
> do with numa. It's an index for a framebuffer instead (i.e. the X in /dev/fbX).

Thanks for the input. Will drop the changes there.

^ permalink raw reply

* Re: [PATCH v2 4/5] phy: mvebu-cp110-comphy: convert to use eth phy mode and submode
From: Kishon Vijay Abraham I @ 2018-11-12 10:48 UTC (permalink / raw)
  To: Grygorii Strashko, David S. Miller, Russell King - ARM Linux,
	Antoine Tenart
  Cc: netdev, Sekhar Nori, linux-kernel, linux-arm-kernel,
	Tony Lindgren, linux-amlogic, linux-mediatek, Alexandre Belloni,
	Quentin Schulz, Vivek Gautam, Maxime Ripard, Chen-Yu Tsai,
	Carlo Caione, Chunfeng Yun, Matthias Brugger, Manu Gautam
In-Reply-To: <20181109234755.21687-5-grygorii.strashko@ti.com>

Hi Antoine, David Miller

Please ACK this patch if it looks okay.

Thanks
Kishon

On 10/11/18 5:17 AM, Grygorii Strashko wrote:
> Convert mvebu-cp110-comphy PHY driver to use recently introduced
> PHY_MODE_ETHERNET and phy_set_mode_ext().
> 
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
>  drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 19 +-----
>  drivers/phy/marvell/phy-mvebu-cp110-comphy.c    | 83 ++++++++++++++-----------
>  2 files changed, 48 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
> index 7a37a37..731793a 100644
> --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
> +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
> @@ -1165,28 +1165,13 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port)
>   */
>  static int mvpp22_comphy_init(struct mvpp2_port *port)
>  {
> -	enum phy_mode mode;
>  	int ret;
>  
>  	if (!port->comphy)
>  		return 0;
>  
> -	switch (port->phy_interface) {
> -	case PHY_INTERFACE_MODE_SGMII:
> -	case PHY_INTERFACE_MODE_1000BASEX:
> -		mode = PHY_MODE_SGMII;
> -		break;
> -	case PHY_INTERFACE_MODE_2500BASEX:
> -		mode = PHY_MODE_2500SGMII;
> -		break;
> -	case PHY_INTERFACE_MODE_10GKR:
> -		mode = PHY_MODE_10GKR;
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -
> -	ret = phy_set_mode(port->comphy, mode);
> +	ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET,
> +			       port->phy_interface);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> index 79b52c3..7dee72b 100644
> --- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> @@ -9,6 +9,7 @@
>  #include <linux/iopoll.h>
>  #include <linux/mfd/syscon.h>
>  #include <linux/module.h>
> +#include <linux/phy.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
> @@ -131,26 +132,26 @@ struct mvebu_comhy_conf {
>  
>  static const struct mvebu_comhy_conf mvebu_comphy_cp110_modes[] = {
>  	/* lane 0 */
> -	MVEBU_COMPHY_CONF(0, 1, PHY_MODE_SGMII, 0x1),
> -	MVEBU_COMPHY_CONF(0, 1, PHY_MODE_2500SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1),
>  	/* lane 1 */
> -	MVEBU_COMPHY_CONF(1, 2, PHY_MODE_SGMII, 0x1),
> -	MVEBU_COMPHY_CONF(1, 2, PHY_MODE_2500SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1),
>  	/* lane 2 */
> -	MVEBU_COMPHY_CONF(2, 0, PHY_MODE_SGMII, 0x1),
> -	MVEBU_COMPHY_CONF(2, 0, PHY_MODE_2500SGMII, 0x1),
> -	MVEBU_COMPHY_CONF(2, 0, PHY_MODE_10GKR, 0x1),
> +	MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_2500BASEX, 0x1),
> +	MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_10GKR, 0x1),
>  	/* lane 3 */
> -	MVEBU_COMPHY_CONF(3, 1, PHY_MODE_SGMII, 0x2),
> -	MVEBU_COMPHY_CONF(3, 1, PHY_MODE_2500SGMII, 0x2),
> +	MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_SGMII, 0x2),
> +	MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_2500BASEX, 0x2),
>  	/* lane 4 */
> -	MVEBU_COMPHY_CONF(4, 0, PHY_MODE_SGMII, 0x2),
> -	MVEBU_COMPHY_CONF(4, 0, PHY_MODE_2500SGMII, 0x2),
> -	MVEBU_COMPHY_CONF(4, 0, PHY_MODE_10GKR, 0x2),
> -	MVEBU_COMPHY_CONF(4, 1, PHY_MODE_SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_SGMII, 0x2),
> +	MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_2500BASEX, 0x2),
> +	MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_10GKR, 0x2),
> +	MVEBU_COMPHY_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1),
>  	/* lane 5 */
> -	MVEBU_COMPHY_CONF(5, 2, PHY_MODE_SGMII, 0x1),
> -	MVEBU_COMPHY_CONF(5, 2, PHY_MODE_2500SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_SGMII, 0x1),
> +	MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1),
>  };
>  
>  struct mvebu_comphy_priv {
> @@ -163,10 +164,12 @@ struct mvebu_comphy_lane {
>  	struct mvebu_comphy_priv *priv;
>  	unsigned id;
>  	enum phy_mode mode;
> +	int submode;
>  	int port;
>  };
>  
> -static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode)
> +static int mvebu_comphy_get_mux(int lane, int port,
> +				enum phy_mode mode, int submode)
>  {
>  	int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes);
>  
> @@ -177,7 +180,7 @@ static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode)
>  	for (i = 0; i < n; i++) {
>  		if (mvebu_comphy_cp110_modes[i].lane == lane &&
>  		    mvebu_comphy_cp110_modes[i].port == port &&
> -		    mvebu_comphy_cp110_modes[i].mode == mode)
> +		    mvebu_comphy_cp110_modes[i].mode == submode)
>  			break;
>  	}
>  
> @@ -187,8 +190,7 @@ static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode)
>  	return mvebu_comphy_cp110_modes[i].mux;
>  }
>  
> -static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane,
> -					     enum phy_mode mode)
> +static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane)
>  {
>  	struct mvebu_comphy_priv *priv = lane->priv;
>  	u32 val;
> @@ -206,14 +208,14 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane,
>  		 MVEBU_COMPHY_SERDES_CFG0_HALF_BUS |
>  		 MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) |
>  		 MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf));
> -	if (mode == PHY_MODE_10GKR)
> +	if (lane->submode == PHY_INTERFACE_MODE_10GKR)
>  		val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) |
>  		       MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe);
> -	else if (mode == PHY_MODE_2500SGMII)
> +	else if (lane->submode == PHY_INTERFACE_MODE_2500BASEX)
>  		val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x8) |
>  		       MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x8) |
>  		       MVEBU_COMPHY_SERDES_CFG0_HALF_BUS;
> -	else if (mode == PHY_MODE_SGMII)
> +	else if (lane->submode == PHY_INTERFACE_MODE_SGMII)
>  		val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) |
>  		       MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) |
>  		       MVEBU_COMPHY_SERDES_CFG0_HALF_BUS;
> @@ -243,7 +245,7 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane,
>  	/* refclk selection */
>  	val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
>  	val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL;
> -	if (mode == PHY_MODE_10GKR)
> +	if (lane->submode == PHY_INTERFACE_MODE_10GKR)
>  		val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE;
>  	writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
>  
> @@ -261,8 +263,7 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane,
>  	writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
>  }
>  
> -static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane,
> -				  enum phy_mode mode)
> +static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane)
>  {
>  	struct mvebu_comphy_priv *priv = lane->priv;
>  	u32 val;
> @@ -303,13 +304,13 @@ static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane,
>  	return 0;
>  }
>  
> -static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode)
> +static int mvebu_comphy_set_mode_sgmii(struct phy *phy)
>  {
>  	struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
>  	struct mvebu_comphy_priv *priv = lane->priv;
>  	u32 val;
>  
> -	mvebu_comphy_ethernet_init_reset(lane, mode);
> +	mvebu_comphy_ethernet_init_reset(lane);
>  
>  	val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
>  	val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
> @@ -330,7 +331,7 @@ static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode)
>  	val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1);
>  	writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
>  
> -	return mvebu_comphy_init_plls(lane, PHY_MODE_SGMII);
> +	return mvebu_comphy_init_plls(lane);
>  }
>  
>  static int mvebu_comphy_set_mode_10gkr(struct phy *phy)
> @@ -339,7 +340,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy)
>  	struct mvebu_comphy_priv *priv = lane->priv;
>  	u32 val;
>  
> -	mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_10GKR);
> +	mvebu_comphy_ethernet_init_reset(lane);
>  
>  	val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
>  	val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL |
> @@ -469,7 +470,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy)
>  	val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a);
>  	writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
>  
> -	return mvebu_comphy_init_plls(lane, PHY_MODE_10GKR);
> +	return mvebu_comphy_init_plls(lane);
>  }
>  
>  static int mvebu_comphy_power_on(struct phy *phy)
> @@ -479,7 +480,8 @@ static int mvebu_comphy_power_on(struct phy *phy)
>  	int ret, mux;
>  	u32 val;
>  
> -	mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode);
> +	mux = mvebu_comphy_get_mux(lane->id, lane->port,
> +				   lane->mode, lane->submode);
>  	if (mux < 0)
>  		return -ENOTSUPP;
>  
> @@ -492,12 +494,12 @@ static int mvebu_comphy_power_on(struct phy *phy)
>  	val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id);
>  	regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
>  
> -	switch (lane->mode) {
> -	case PHY_MODE_SGMII:
> -	case PHY_MODE_2500SGMII:
> -		ret = mvebu_comphy_set_mode_sgmii(phy, lane->mode);
> +	switch (lane->submode) {
> +	case PHY_INTERFACE_MODE_SGMII:
> +	case PHY_INTERFACE_MODE_2500BASEX:
> +		ret = mvebu_comphy_set_mode_sgmii(phy);
>  		break;
> -	case PHY_MODE_10GKR:
> +	case PHY_INTERFACE_MODE_10GKR:
>  		ret = mvebu_comphy_set_mode_10gkr(phy);
>  		break;
>  	default:
> @@ -517,10 +519,17 @@ static int mvebu_comphy_set_mode(struct phy *phy,
>  {
>  	struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
>  
> -	if (mvebu_comphy_get_mux(lane->id, lane->port, mode) < 0)
> +	if (mode != PHY_MODE_ETHERNET)
> +		return -EINVAL;
> +
> +	if (submode == PHY_INTERFACE_MODE_1000BASEX)
> +		submode = PHY_INTERFACE_MODE_SGMII;
> +
> +	if (mvebu_comphy_get_mux(lane->id, lane->port, mode, submode) < 0)
>  		return -EINVAL;
>  
>  	lane->mode = mode;
> +	lane->submode = submode;
>  	return 0;
>  }
>  
> 

^ permalink raw reply

* Re: [PATCH v2 3/5] phy: ocelot-serdes: convert to use eth phy mode and submode
From: Kishon Vijay Abraham I @ 2018-11-12 10:42 UTC (permalink / raw)
  To: Grygorii Strashko, David S. Miller, Russell King - ARM Linux,
	Quentin Schulz
  Cc: netdev, Sekhar Nori, linux-kernel, linux-arm-kernel,
	Tony Lindgren, linux-amlogic, linux-mediatek, Alexandre Belloni,
	Antoine Tenart, Vivek Gautam, Maxime Ripard, Chen-Yu Tsai,
	Carlo Caione, Chunfeng Yun, Matthias Brugger, Manu Gautam,
	Gustavo A. R. Silva
In-Reply-To: <20181109234755.21687-4-grygorii.strashko@ti.com>

Hi Quentin, David Miller

Need your ACK on this patch.

Thanks
Kishon

On 10/11/18 5:17 AM, Grygorii Strashko wrote:
> Convert ocelot-serdes PHY driver to use recently introduced
> PHY_MODE_ETHERNET and phy_set_mode_ext().
> 
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
>  drivers/net/ethernet/mscc/ocelot.c   |  9 ++-------
>  drivers/phy/mscc/phy-ocelot-serdes.c | 14 ++++++++++----
>  2 files changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
> index 3238b9e..3edb608 100644
> --- a/drivers/net/ethernet/mscc/ocelot.c
> +++ b/drivers/net/ethernet/mscc/ocelot.c
> @@ -472,7 +472,6 @@ static int ocelot_port_open(struct net_device *dev)
>  {
>  	struct ocelot_port *port = netdev_priv(dev);
>  	struct ocelot *ocelot = port->ocelot;
> -	enum phy_mode phy_mode;
>  	int err;
>  
>  	/* Enable receiving frames on the port, and activate auto-learning of
> @@ -484,12 +483,8 @@ static int ocelot_port_open(struct net_device *dev)
>  			 ANA_PORT_PORT_CFG, port->chip_port);
>  
>  	if (port->serdes) {
> -		if (port->phy_mode == PHY_INTERFACE_MODE_SGMII)
> -			phy_mode = PHY_MODE_SGMII;
> -		else
> -			phy_mode = PHY_MODE_QSGMII;
> -
> -		err = phy_set_mode(port->serdes, phy_mode);
> +		err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET,
> +				       port->phy_mode);
>  		if (err) {
>  			netdev_err(dev, "Could not set mode of SerDes\n");
>  			return err;
> diff --git a/drivers/phy/mscc/phy-ocelot-serdes.c b/drivers/phy/mscc/phy-ocelot-serdes.c
> index c61a9890..f525a21 100644
> --- a/drivers/phy/mscc/phy-ocelot-serdes.c
> +++ b/drivers/phy/mscc/phy-ocelot-serdes.c
> @@ -11,6 +11,7 @@
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_platform.h>
> +#include <linux/phy.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
> @@ -116,8 +117,10 @@ struct serdes_mux {
>  	.mux = _mux,						\
>  }
>  
> -#define SERDES_MUX_SGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_SGMII, m, c)
> -#define SERDES_MUX_QSGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_QSGMII, m, c)
> +#define SERDES_MUX_SGMII(i, p, m, c) \
> +	SERDES_MUX(i, p, PHY_INTERFACE_MODE_SGMII, m, c)
> +#define SERDES_MUX_QSGMII(i, p, m, c) \
> +	SERDES_MUX(i, p, PHY_INTERFACE_MODE_QSGMII, m, c)
>  
>  static const struct serdes_mux ocelot_serdes_muxes[] = {
>  	SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0),
> @@ -164,12 +167,15 @@ static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
>  	unsigned int i;
>  	int ret;
>  
> +	if (mode != PHY_MODE_ETHERNET)
> +		return -EINVAL;
> +
>  	for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) {
>  		if (macro->idx != ocelot_serdes_muxes[i].idx ||
> -		    mode != ocelot_serdes_muxes[i].mode)
> +		    submode != ocelot_serdes_muxes[i].mode)
>  			continue;
>  
> -		if (mode != PHY_MODE_QSGMII &&
> +		if (submode != PHY_INTERFACE_MODE_QSGMII &&
>  		    macro->port != ocelot_serdes_muxes[i].port)
>  			continue;
>  
> 

^ permalink raw reply

* Re: [PATCH v3 1/2] kretprobe: produce sane stack traces
From: Aleksa Sarai @ 2018-11-12 10:38 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Aleksa Sarai, Steven Rostedt, Naveen N. Rao, Anil S Keshavamurthy,
	David S. Miller, Jonathan Corbet, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
	Namhyung Kim, Shuah Khan, Alexei Starovoitov, Daniel Borkmann,
	Brendan Gregg, Christian Brauner, netdev, linux-doc, linux-kernel
In-Reply-To: <20181111003137.c9df7a077d983cde57c06ee8@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 1982 bytes --]

On 2018-11-11, Masami Hiramatsu <mhiramat@kernel.org> wrote:
> > > > +		addr = kretprobe_ret_addr(current, addr, stack_addr(regs));
> > > 
> > > But since kretprobe will be an event, which can kick the stackdump.
> > > BTW, from kretprobe, regs->ip should always be the trampoline handler, 
> > > see arch/x86/kernel/kprobes/core.c:772 :-)
> > > So it must be fixed always.
> > 
> > Right, but kretprobe_ret_addr() is returning the *original* return
> > address (and we need to do an (addr == kretprobe_trampoline)). The
> > real problem is that stack_addr(regs) isn't the same as it is during
> > kretprobe setup (but kretprobe_ret_addr() works everywhere else).
> 
> I think stack_addr(regs) should be same when this is called from kretprobe
> handler context. Otherwise, yes, it is not same, but in that case, regs->ip
> is not kretprobe_trampoline too.

I figured it out.

It should be (regs->sp - 1) (just like it is inside the relevant
unwinder function for ORC). I now have a prototype which works under the
frame unwinder[*] -- however under ORC you can only see the top-most
function (the unwinder doesn't see the other function calls). I'm
playing with ORC hints with kretprobe_trampoline to try to improve
things but it's still a bit screwy.


[*]: However, I've noticed that the stack traces between the two traces
	 no longer match. On kprobe you get function_name+1, but on
	 kretprobe you get function_caller+foo. Obviously it's working but
	 the return address results in slightly different stack traces. This
	 means that stack trace aggregation between kprobe and kretprobe
	 won't work anymore -- at least not like it did in my original
	 patch. So I'm really not sure where to go from here.

I can send around another patchset to illustrate the problem if you like
(as well as show how the current unwinding code works).

-- 
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
<https://www.cyphar.com/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* RE:(2) [PATCH net] ip: hash fragments consistently
From: 배석진 @ 2018-11-12  0:40 UTC (permalink / raw)
  To: Eric Dumazet, Paolo Abeni, netdev@vger.kernel.org; +Cc: David S. Miller
In-Reply-To: <e9e9703f-8fbe-4d81-4bb1-1cdafd0a4955@gmail.com>

> Also we might note that flow dissector itself is buggy as
> found by Soukjin Bae ( https://patchwork.ozlabs.org/patch/994601/ )
> 
> I will send a v2 of his patch with a different changelog.
>  
> Defrag is fixed [1] but the bug in flow dissector is adding
> extra work and hash inconsistencies.
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/?id=0d5b9311baf27bb545f187f12ecfd558220c607d


Dear all,

it's good news to mee too.
thanks for accept my work :)

 

^ permalink raw reply

* Price enquiry
From: Daniel Murray @ 2018-11-11 14:56 UTC (permalink / raw)
  To: netdev

Hi,friend,
 
This is Daniel Murray and i am from Sinara Group Co.Ltd Group Co.,LTD in Russia.
We are glad to know about your company from the web and we are interested in your products.
Could you kindly send us your Latest catalog and price list for our trial order.
 
Best Regards,
 
Daniel Murray
Purchasing Manager

^ permalink raw reply

* Re: [RFC] mm: Replace all open encodings for NUMA_NO_NODE
From: Hans Verkuil @ 2018-11-12  8:43 UTC (permalink / raw)
  To: Anshuman Khandual, linux-mm, linux-kernel
  Cc: linux-fbdev, linux-ia64, linux-rdma, netdev, dri-devel,
	linux-block, sparclinux, iommu, intel-wired-lan, linux-alpha,
	dmaengine, linuxppc-dev, ocfs2-devel, linux-media
In-Reply-To: <1541990515-11670-1-git-send-email-anshuman.khandual@arm.com>

On 11/12/2018 03:41 AM, Anshuman Khandual wrote:
> At present there are multiple places where invalid node number is encoded
> as -1. Even though implicitly understood it is always better to have macros
> in there. Replace these open encodings for an invalid node number with the
> global macro NUMA_NO_NODE. This helps remove NUMA related assumptions like
> 'invalid node' from various places redirecting them to a common definition.
> 
> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> Build tested this with multiple cross compiler options like alpha, sparc,
> arm64, x86, powerpc64le etc with their default config which might not have
> compiled tested all driver related changes. I will appreciate folks giving
> this a test in their respective build environment.
> 
> All these places for replacement were found by running the following grep
> patterns on the entire kernel code. Please let me know if this might have
> missed some instances. This might also have replaced some false positives.
> I will appreciate suggestions, inputs and review.

The 'node' in the drivers/media and the drivers/video sources has nothing to
do with numa. It's an index for a framebuffer instead (i.e. the X in /dev/fbX).

Regards,

	Hans

> 
> 1. git grep "nid == -1"
> 2. git grep "node == -1"
> 3. git grep "nid = -1"
> 4. git grep "node = -1"
> 
>  arch/alpha/include/asm/topology.h             |  2 +-
>  arch/ia64/kernel/numa.c                       |  2 +-
>  arch/ia64/mm/discontig.c                      |  6 +++---
>  arch/ia64/sn/kernel/io_common.c               |  2 +-
>  arch/powerpc/include/asm/pci-bridge.h         |  2 +-
>  arch/powerpc/kernel/paca.c                    |  2 +-
>  arch/powerpc/kernel/pci-common.c              |  2 +-
>  arch/powerpc/mm/numa.c                        | 14 +++++++-------
>  arch/powerpc/platforms/powernv/memtrace.c     |  4 ++--
>  arch/sparc/kernel/auxio_32.c                  |  2 +-
>  arch/sparc/kernel/pci_fire.c                  |  2 +-
>  arch/sparc/kernel/pci_schizo.c                |  2 +-
>  arch/sparc/kernel/pcic.c                      |  6 +++---
>  arch/sparc/kernel/psycho_common.c             |  2 +-
>  arch/sparc/kernel/sbus.c                      |  2 +-
>  arch/sparc/mm/init_64.c                       |  6 +++---
>  arch/sparc/prom/init_32.c                     |  2 +-
>  arch/sparc/prom/init_64.c                     |  4 ++--
>  arch/sparc/prom/tree_32.c                     | 12 ++++++------
>  arch/sparc/prom/tree_64.c                     | 18 +++++++++---------
>  arch/x86/include/asm/pci.h                    |  2 +-
>  arch/x86/kernel/apic/x2apic_uv_x.c            |  6 +++---
>  arch/x86/kernel/smpboot.c                     |  2 +-
>  arch/x86/platform/olpc/olpc_dt.c              | 16 ++++++++--------
>  drivers/block/mtip32xx/mtip32xx.c             |  4 ++--
>  drivers/dma/dmaengine.c                       |  3 ++-
>  drivers/infiniband/hw/hfi1/affinity.c         |  2 +-
>  drivers/infiniband/hw/hfi1/init.c             |  2 +-
>  drivers/iommu/dmar.c                          |  4 ++--
>  drivers/iommu/intel-iommu.c                   |  2 +-
>  drivers/media/pci/ivtv/ivtvfb.c               |  2 +-
>  drivers/media/platform/vivid/vivid-osd.c      |  2 +-
>  drivers/misc/sgi-xp/xpc_uv.c                  |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  4 ++--
>  drivers/video/fbdev/mmp/fb/mmpfb.c            |  2 +-
>  drivers/video/fbdev/pxa168fb.c                |  2 +-
>  drivers/video/fbdev/w100fb.c                  |  2 +-
>  fs/ocfs2/dlm/dlmcommon.h                      |  2 +-
>  fs/ocfs2/dlm/dlmdomain.c                      | 10 +++++-----
>  fs/ocfs2/dlm/dlmmaster.c                      |  2 +-
>  fs/ocfs2/dlm/dlmrecovery.c                    |  2 +-
>  fs/ocfs2/stack_user.c                         |  6 +++---
>  init/init_task.c                              |  2 +-
>  kernel/kthread.c                              |  2 +-
>  kernel/sched/fair.c                           | 15 ++++++++-------
>  lib/cpumask.c                                 |  2 +-
>  mm/huge_memory.c                              | 12 ++++++------
>  mm/hugetlb.c                                  |  2 +-
>  mm/ksm.c                                      |  2 +-
>  mm/memory.c                                   |  6 +++---
>  mm/memory_hotplug.c                           | 12 ++++++------
>  mm/mempolicy.c                                |  2 +-
>  mm/page_alloc.c                               |  4 ++--
>  mm/page_ext.c                                 |  2 +-
>  net/core/pktgen.c                             |  2 +-
>  net/qrtr/qrtr.c                               |  2 +-
>  tools/perf/bench/numa.c                       |  6 +++---
>  57 files changed, 125 insertions(+), 123 deletions(-)
> 
> diff --git a/arch/alpha/include/asm/topology.h b/arch/alpha/include/asm/topology.h
> index e6e13a8..f6dc89c 100644
> --- a/arch/alpha/include/asm/topology.h
> +++ b/arch/alpha/include/asm/topology.h
> @@ -29,7 +29,7 @@ static const struct cpumask *cpumask_of_node(int node)
>  {
>  	int cpu;
>  
> -	if (node == -1)
> +	if (node == NUMA_NO_NODE)
>  		return cpu_all_mask;
>  
>  	cpumask_clear(&node_to_cpumask_map[node]);
> diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
> index 92c3762..1315da6 100644
> --- a/arch/ia64/kernel/numa.c
> +++ b/arch/ia64/kernel/numa.c
> @@ -74,7 +74,7 @@ void __init build_cpu_to_node_map(void)
>  		cpumask_clear(&node_to_cpu_mask[node]);
>  
>  	for_each_possible_early_cpu(cpu) {
> -		node = -1;
> +		node = NUMA_NO_NODE;
>  		for (i = 0; i < NR_CPUS; ++i)
>  			if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
>  				node = node_cpuid[i].nid;
> diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
> index 8a96578..f9c3675 100644
> --- a/arch/ia64/mm/discontig.c
> +++ b/arch/ia64/mm/discontig.c
> @@ -227,7 +227,7 @@ void __init setup_per_cpu_areas(void)
>  	 * CPUs are put into groups according to node.  Walk cpu_map
>  	 * and create new groups at node boundaries.
>  	 */
> -	prev_node = -1;
> +	prev_node = NUMA_NO_NODE;
>  	ai->nr_groups = 0;
>  	for (unit = 0; unit < nr_units; unit++) {
>  		cpu = cpu_map[unit];
> @@ -435,7 +435,7 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
>  {
>  	void *ptr = NULL;
>  	u8 best = 0xff;
> -	int bestnode = -1, node, anynode = 0;
> +	int bestnode = NUMA_NO_NODE, node, anynode = 0;
>  
>  	for_each_online_node(node) {
>  		if (node_isset(node, memory_less_mask))
> @@ -447,7 +447,7 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
>  		anynode = node;
>  	}
>  
> -	if (bestnode == -1)
> +	if (bestnode == NUMA_NO_NODE)
>  		bestnode = anynode;
>  
>  	ptr = memblock_alloc_try_nid(pernodesize, PERCPU_PAGE_SIZE,
> diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
> index 8df13d0..86b3fcb 100644
> --- a/arch/ia64/sn/kernel/io_common.c
> +++ b/arch/ia64/sn/kernel/io_common.c
> @@ -344,7 +344,7 @@ sn_common_bus_fixup(struct pci_bus *bus,
>  		printk(KERN_WARNING "on node %d but only %d nodes online."
>  		       "Association set to undetermined.\n",
>  		       controller->node, num_online_nodes());
> -		controller->node = -1;
> +		controller->node = NUMA_NO_NODE;
>  	}
>  }
>  
> diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
> index 94d4490..25a9e33 100644
> --- a/arch/powerpc/include/asm/pci-bridge.h
> +++ b/arch/powerpc/include/asm/pci-bridge.h
> @@ -264,7 +264,7 @@ extern int pcibios_map_io_space(struct pci_bus *bus);
>  #ifdef CONFIG_NUMA
>  #define PHB_SET_NODE(PHB, NODE)		((PHB)->node = (NODE))
>  #else
> -#define PHB_SET_NODE(PHB, NODE)		((PHB)->node = -1)
> +#define PHB_SET_NODE(PHB, NODE)		((PHB)->node = NUMA_NO_NODE)
>  #endif
>  
>  #endif	/* CONFIG_PPC64 */
> diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
> index 913bfca..6a0bd51 100644
> --- a/arch/powerpc/kernel/paca.c
> +++ b/arch/powerpc/kernel/paca.c
> @@ -36,7 +36,7 @@ static void *__init alloc_paca_data(unsigned long size, unsigned long align,
>  	 * which will put its paca in the right place.
>  	 */
>  	if (cpu == boot_cpuid) {
> -		nid = -1;
> +		nid = NUMA_NO_NODE;
>  		memblock_set_bottom_up(true);
>  	} else {
>  		nid = early_cpu_to_node(cpu);
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> index 88e4f69..14c33a9 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -132,7 +132,7 @@ struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
>  		int nid = of_node_to_nid(dev);
>  
>  		if (nid < 0 || !node_online(nid))
> -			nid = -1;
> +			nid = NUMA_NO_NODE;
>  
>  		PHB_SET_NODE(phb, nid);
>  	}
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index 3a048e9..77808a2 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -215,7 +215,7 @@ static void initialize_distance_lookup_table(int nid,
>   */
>  static int associativity_to_nid(const __be32 *associativity)
>  {
> -	int nid = -1;
> +	int nid = NUMA_NO_NODE;
>  
>  	if (min_common_depth == -1)
>  		goto out;
> @@ -225,7 +225,7 @@ static int associativity_to_nid(const __be32 *associativity)
>  
>  	/* POWER4 LPAR uses 0xffff as invalid node */
>  	if (nid == 0xffff || nid >= MAX_NUMNODES)
> -		nid = -1;
> +		nid = NUMA_NO_NODE;
>  
>  	if (nid > 0 &&
>  		of_read_number(associativity, 1) >= distance_ref_points_depth) {
> @@ -244,7 +244,7 @@ static int associativity_to_nid(const __be32 *associativity)
>   */
>  static int of_node_to_nid_single(struct device_node *device)
>  {
> -	int nid = -1;
> +	int nid = NUMA_NO_NODE;
>  	const __be32 *tmp;
>  
>  	tmp = of_get_associativity(device);
> @@ -256,7 +256,7 @@ static int of_node_to_nid_single(struct device_node *device)
>  /* Walk the device tree upwards, looking for an associativity id */
>  int of_node_to_nid(struct device_node *device)
>  {
> -	int nid = -1;
> +	int nid = NUMA_NO_NODE;
>  
>  	of_node_get(device);
>  	while (device) {
> @@ -454,7 +454,7 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb)
>   */
>  static int numa_setup_cpu(unsigned long lcpu)
>  {
> -	int nid = -1;
> +	int nid = NUMA_NO_NODE;
>  	struct device_node *cpu;
>  
>  	/*
> @@ -930,7 +930,7 @@ static int hot_add_drconf_scn_to_nid(unsigned long scn_addr)
>  {
>  	struct drmem_lmb *lmb;
>  	unsigned long lmb_size;
> -	int nid = -1;
> +	int nid = NUMA_NO_NODE;
>  
>  	lmb_size = drmem_lmb_size();
>  
> @@ -960,7 +960,7 @@ static int hot_add_drconf_scn_to_nid(unsigned long scn_addr)
>  static int hot_add_node_scn_to_nid(unsigned long scn_addr)
>  {
>  	struct device_node *memory;
> -	int nid = -1;
> +	int nid = NUMA_NO_NODE;
>  
>  	for_each_node_by_type(memory, "memory") {
>  		unsigned long start, size;
> diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c
> index 84d038e..1ce3bfc 100644
> --- a/arch/powerpc/platforms/powernv/memtrace.c
> +++ b/arch/powerpc/platforms/powernv/memtrace.c
> @@ -223,7 +223,7 @@ static int memtrace_online(void)
>  		ent = &memtrace_array[i];
>  
>  		/* We have onlined this chunk previously */
> -		if (ent->nid == -1)
> +		if (ent->nid == NUMA_NO_NODE)
>  			continue;
>  
>  		/* Remove from io mappings */
> @@ -257,7 +257,7 @@ static int memtrace_online(void)
>  		 */
>  		debugfs_remove_recursive(ent->dir);
>  		pr_info("Added trace memory back to node %d\n", ent->nid);
> -		ent->size = ent->start = ent->nid = -1;
> +		ent->size = ent->start = ent->nid = NUMA_NO_NODE;
>  	}
>  	if (ret)
>  		return ret;
> diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
> index a32d588..39f6c59 100644
> --- a/arch/sparc/kernel/auxio_32.c
> +++ b/arch/sparc/kernel/auxio_32.c
> @@ -120,7 +120,7 @@ void __init auxio_power_probe(void)
>  	node = prom_searchsiblings(node, "obio");
>  	node = prom_getchild(node);
>  	node = prom_searchsiblings(node, "power");
> -	if (node == 0 || (s32)node == -1)
> +	if (node == 0 || (s32)node == NUMA_NO_NODE)
>  		return;
>  
>  	/* Map the power control register. */
> diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c
> index be71ae0..474d3be 100644
> --- a/arch/sparc/kernel/pci_fire.c
> +++ b/arch/sparc/kernel/pci_fire.c
> @@ -416,7 +416,7 @@ static int pci_fire_pbm_init(struct pci_pbm_info *pbm,
>  	struct device_node *dp = op->dev.of_node;
>  	int err;
>  
> -	pbm->numa_node = -1;
> +	pbm->numa_node = NUMA_NO_NODE;
>  
>  	pbm->pci_ops = &sun4u_pci_ops;
>  	pbm->config_space_reg_bits = 12;
> diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c
> index 934b97c..87bb231 100644
> --- a/arch/sparc/kernel/pci_schizo.c
> +++ b/arch/sparc/kernel/pci_schizo.c
> @@ -1347,7 +1347,7 @@ static int schizo_pbm_init(struct pci_pbm_info *pbm,
>  	pbm->next = pci_pbm_root;
>  	pci_pbm_root = pbm;
>  
> -	pbm->numa_node = -1;
> +	pbm->numa_node = NUMA_NO_NODE;
>  
>  	pbm->pci_ops = &sun4u_pci_ops;
>  	pbm->config_space_reg_bits = 8;
> diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
> index ee4c9a9..d5fe898 100644
> --- a/arch/sparc/kernel/pcic.c
> +++ b/arch/sparc/kernel/pcic.c
> @@ -476,7 +476,7 @@ static void pcic_map_pci_device(struct linux_pcic *pcic,
>  	unsigned long flags;
>  	int j;
>  
> -	if (node == 0 || node == -1) {
> +	if (node == 0 || node == NUMA_NO_NODE) {
>  		strcpy(namebuf, "???");
>  	} else {
>  		prom_getstring(node, "name", namebuf, 63); namebuf[63] = 0;
> @@ -535,7 +535,7 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
>  	int i, ivec;
>  	char namebuf[64];
>  
> -	if (node == 0 || node == -1) {
> +	if (node == 0 || node == NUMA_NO_NODE) {
>  		strcpy(namebuf, "???");
>  	} else {
>  		prom_getstring(node, "name", namebuf, sizeof(namebuf));
> @@ -625,7 +625,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
>  	list_for_each_entry(dev, &bus->devices, bus_list) {
>  		node = pdev_to_pnode(&pcic->pbm, dev);
>  		if(node == 0)
> -			node = -1;
> +			node = NUMA_NO_NODE;
>  
>  		/* cookies */
>  		pcp = pci_devcookie_alloc();
> diff --git a/arch/sparc/kernel/psycho_common.c b/arch/sparc/kernel/psycho_common.c
> index 81aa91e..dcbf492 100644
> --- a/arch/sparc/kernel/psycho_common.c
> +++ b/arch/sparc/kernel/psycho_common.c
> @@ -454,7 +454,7 @@ void psycho_pbm_init_common(struct pci_pbm_info *pbm, struct platform_device *op
>  	struct device_node *dp = op->dev.of_node;
>  
>  	pbm->name = dp->full_name;
> -	pbm->numa_node = -1;
> +	pbm->numa_node = NUMA_NO_NODE;
>  	pbm->chip_type = chip_type;
>  	pbm->chip_version = of_getintprop_default(dp, "version#", 0);
>  	pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0);
> diff --git a/arch/sparc/kernel/sbus.c b/arch/sparc/kernel/sbus.c
> index c133dfc..28a4aa9 100644
> --- a/arch/sparc/kernel/sbus.c
> +++ b/arch/sparc/kernel/sbus.c
> @@ -561,7 +561,7 @@ static void __init sbus_iommu_init(struct platform_device *op)
>  
>  	op->dev.archdata.iommu = iommu;
>  	op->dev.archdata.stc = strbuf;
> -	op->dev.archdata.numa_node = -1;
> +	op->dev.archdata.numa_node = NUMA_NO_NODE;
>  
>  	reg_base = regs + SYSIO_IOMMUREG_BASE;
>  	iommu->iommu_control = reg_base + IOMMU_CONTROL;
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 3c8aac2..cb1bed1 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -976,13 +976,13 @@ static u64 __init memblock_nid_range_sun4u(u64 start, u64 end, int *nid)
>  {
>  	int prev_nid, new_nid;
>  
> -	prev_nid = -1;
> +	prev_nid = NUMA_NO_NODE;
>  	for ( ; start < end; start += PAGE_SIZE) {
>  		for (new_nid = 0; new_nid < num_node_masks; new_nid++) {
>  			struct node_mem_mask *p = &node_masks[new_nid];
>  
>  			if ((start & p->mask) == p->match) {
> -				if (prev_nid == -1)
> +				if (prev_nid == NUMA_NO_NODE)
>  					prev_nid = new_nid;
>  				break;
>  			}
> @@ -1208,7 +1208,7 @@ int of_node_to_nid(struct device_node *dp)
>  	md = mdesc_grab();
>  
>  	count = 0;
> -	nid = -1;
> +	nid = NUMA_NO_NODE;
>  	mdesc_for_each_node_by_name(md, grp, "group") {
>  		if (!scan_arcs_for_cfg_handle(md, grp, cfg_handle)) {
>  			nid = count;
> diff --git a/arch/sparc/prom/init_32.c b/arch/sparc/prom/init_32.c
> index d204701..4c6e540 100644
> --- a/arch/sparc/prom/init_32.c
> +++ b/arch/sparc/prom/init_32.c
> @@ -58,7 +58,7 @@ void __init prom_init(struct linux_romvec *rp)
>  	prom_nodeops = romvec->pv_nodeops;
>  
>  	prom_root_node = prom_getsibling(0);
> -	if ((prom_root_node == 0) || ((s32)prom_root_node == -1))
> +	if ((prom_root_node == 0) || ((s32)prom_root_node == NUMA_NO_NODE))
>  		prom_halt();
>  
>  	if((((unsigned long) prom_nodeops) == 0) || 
> diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c
> index 103aa91..85669c0 100644
> --- a/arch/sparc/prom/init_64.c
> +++ b/arch/sparc/prom/init_64.c
> @@ -36,13 +36,13 @@ void __init prom_init(void *cif_handler)
>  	prom_cif_init(cif_handler);
>  
>  	prom_chosen_node = prom_finddevice(prom_chosen_path);
> -	if (!prom_chosen_node || (s32)prom_chosen_node == -1)
> +	if (!prom_chosen_node || (s32)prom_chosen_node == NUMA_NO_NODE)
>  		prom_halt();
>  
>  	prom_stdout = prom_getint(prom_chosen_node, "stdout");
>  
>  	node = prom_finddevice("/openprom");
> -	if (!node || (s32)node == -1)
> +	if (!node || (s32)node == NUMA_NO_NODE)
>  		prom_halt();
>  
>  	prom_getstring(node, "version", prom_version, sizeof(prom_version));
> diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c
> index 0fed893..2d0a204 100644
> --- a/arch/sparc/prom/tree_32.c
> +++ b/arch/sparc/prom/tree_32.c
> @@ -41,11 +41,11 @@ phandle prom_getchild(phandle node)
>  {
>  	phandle cnode;
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  
>  	cnode = __prom_getchild(node);
> -	if (cnode == 0 || (s32)cnode == -1)
> +	if (cnode == 0 || (s32)cnode == NUMA_NO_NODE)
>  		return 0;
>  
>  	return cnode;
> @@ -73,11 +73,11 @@ phandle prom_getsibling(phandle node)
>  {
>  	phandle sibnode;
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  
>  	sibnode = __prom_getsibling(node);
> -	if (sibnode == 0 || (s32)sibnode == -1)
> +	if (sibnode == 0 || (s32)sibnode == NUMA_NO_NODE)
>  		return 0;
>  
>  	return sibnode;
> @@ -220,7 +220,7 @@ static char *__prom_nextprop(phandle node, char * oprop)
>   */
>  char *prom_nextprop(phandle node, char *oprop, char *buffer)
>  {
> -	if (node == 0 || (s32)node == -1)
> +	if (node == 0 || (s32)node == NUMA_NO_NODE)
>  		return "";
>  
>  	return __prom_nextprop(node, oprop);
> @@ -304,7 +304,7 @@ phandle prom_inst2pkg(int inst)
>  	node = (*romvec->pv_v2devops.v2_inst2pkg)(inst);
>  	restore_current();
>  	spin_unlock_irqrestore(&prom_lock, flags);
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  	return node;
>  }
> diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c
> index 989e799..2b4c515 100644
> --- a/arch/sparc/prom/tree_64.c
> +++ b/arch/sparc/prom/tree_64.c
> @@ -44,10 +44,10 @@ phandle prom_getchild(phandle node)
>  {
>  	phandle cnode;
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  	cnode = __prom_getchild(node);
> -	if ((s32)cnode == -1)
> +	if ((s32)cnode == NUMA_NO_NODE)
>  		return 0;
>  	return cnode;
>  }
> @@ -57,10 +57,10 @@ inline phandle prom_getparent(phandle node)
>  {
>  	phandle cnode;
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  	cnode = prom_node_to_node("parent", node);
> -	if ((s32)cnode == -1)
> +	if ((s32)cnode == NUMA_NO_NODE)
>  		return 0;
>  	return cnode;
>  }
> @@ -77,10 +77,10 @@ phandle prom_getsibling(phandle node)
>  {
>  	phandle sibnode;
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  	sibnode = __prom_getsibling(node);
> -	if ((s32)sibnode == -1)
> +	if ((s32)sibnode == NUMA_NO_NODE)
>  		return 0;
>  
>  	return sibnode;
> @@ -241,7 +241,7 @@ char *prom_firstprop(phandle node, char *buffer)
>  	unsigned long args[7];
>  
>  	*buffer = 0;
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return buffer;
>  
>  	args[0] = (unsigned long) prom_nextprop_name;
> @@ -267,7 +267,7 @@ char *prom_nextprop(phandle node, const char *oprop, char *buffer)
>  	unsigned long args[7];
>  	char buf[32];
>  
> -	if ((s32)node == -1) {
> +	if ((s32)node == NUMA_NO_NODE) {
>  		*buffer = 0;
>  		return buffer;
>  	}
> @@ -370,7 +370,7 @@ inline phandle prom_inst2pkg(int inst)
>  	p1275_cmd_direct(args);
>  
>  	node = (int) args[4];
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  	return node;
>  }
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index 6629636..dee2a31 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -141,7 +141,7 @@ cpumask_of_pcibus(const struct pci_bus *bus)
>  	int node;
>  
>  	node = __pcibus_to_node(bus);
> -	return (node == -1) ? cpu_online_mask :
> +	return (node == NUMA_NO_NODE) ? cpu_online_mask :
>  			      cpumask_of_node(node);
>  }
>  #endif
> diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
> index 391f358..3c3378a 100644
> --- a/arch/x86/kernel/apic/x2apic_uv_x.c
> +++ b/arch/x86/kernel/apic/x2apic_uv_x.c
> @@ -1390,7 +1390,7 @@ static void __init build_socket_tables(void)
>  	}
>  
>  	/* Set socket -> node values: */
> -	lnid = -1;
> +	lnid = NUMA_NO_NODE;
>  	for_each_present_cpu(cpu) {
>  		int nid = cpu_to_node(cpu);
>  		int apicid, sockid;
> @@ -1521,7 +1521,7 @@ static void __init uv_system_init_hub(void)
>  			new_hub->pnode = 0xffff;
>  
>  		new_hub->numa_blade_id = uv_node_to_blade_id(nodeid);
> -		new_hub->memory_nid = -1;
> +		new_hub->memory_nid = NUMA_NO_NODE;
>  		new_hub->nr_possible_cpus = 0;
>  		new_hub->nr_online_cpus = 0;
>  	}
> @@ -1538,7 +1538,7 @@ static void __init uv_system_init_hub(void)
>  
>  		uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid);
>  		uv_cpu_info_per(cpu)->blade_cpu_id = uv_cpu_hub_info(cpu)->nr_possible_cpus++;
> -		if (uv_cpu_hub_info(cpu)->memory_nid == -1)
> +		if (uv_cpu_hub_info(cpu)->memory_nid == NUMA_NO_NODE)
>  			uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu);
>  
>  		/* Init memoryless node: */
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index a9134d1..c1d45dc 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -841,7 +841,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
>  /* reduce the number of lines printed when booting a large cpu count system */
>  static void announce_cpu(int cpu, int apicid)
>  {
> -	static int current_node = -1;
> +	static int current_node = NUMA_NO_NODE;
>  	int node = early_cpu_to_node(cpu);
>  	static int width, node_width;
>  
> diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c
> index 24d2175..7098127 100644
> --- a/arch/x86/platform/olpc/olpc_dt.c
> +++ b/arch/x86/platform/olpc/olpc_dt.c
> @@ -29,10 +29,10 @@ static phandle __init olpc_dt_getsibling(phandle node)
>  	const void *args[] = { (void *)node };
>  	void *res[] = { &node };
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  
> -	if (olpc_ofw("peer", args, res) || (s32)node == -1)
> +	if (olpc_ofw("peer", args, res) || (s32)node == NUMA_NO_NODE)
>  		return 0;
>  
>  	return node;
> @@ -43,10 +43,10 @@ static phandle __init olpc_dt_getchild(phandle node)
>  	const void *args[] = { (void *)node };
>  	void *res[] = { &node };
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return 0;
>  
> -	if (olpc_ofw("child", args, res) || (s32)node == -1) {
> +	if (olpc_ofw("child", args, res) || (s32)node == NUMA_NO_NODE) {
>  		pr_err("PROM: %s: fetching child failed!\n", __func__);
>  		return 0;
>  	}
> @@ -60,7 +60,7 @@ static int __init olpc_dt_getproplen(phandle node, const char *prop)
>  	int len;
>  	void *res[] = { &len };
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return -1;
>  
>  	if (olpc_ofw("getproplen", args, res)) {
> @@ -100,7 +100,7 @@ static int __init olpc_dt_nextprop(phandle node, char *prev, char *buf)
>  
>  	buf[0] = '\0';
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return -1;
>  
>  	if (olpc_ofw("nextprop", args, res) || success != 1)
> @@ -115,7 +115,7 @@ static int __init olpc_dt_pkg2path(phandle node, char *buf,
>  	const void *args[] = { (void *)node, buf, (void *)buflen };
>  	void *res[] = { len };
>  
> -	if ((s32)node == -1)
> +	if ((s32)node == NUMA_NO_NODE)
>  		return -1;
>  
>  	if (olpc_ofw("package-to-path", args, res) || *len < 1)
> @@ -176,7 +176,7 @@ static phandle __init olpc_dt_finddevice(const char *path)
>  		return 0;
>  	}
>  
> -	if ((s32) node == -1)
> +	if ((s32) node == NUMA_NO_NODE)
>  		return 0;
>  
>  	return node;
> diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
> index a7daa8a..b889452 100644
> --- a/drivers/block/mtip32xx/mtip32xx.c
> +++ b/drivers/block/mtip32xx/mtip32xx.c
> @@ -4084,9 +4084,9 @@ static int get_least_used_cpu_on_node(int node)
>  /* Helper for selecting a node in round robin mode */
>  static inline int mtip_get_next_rr_node(void)
>  {
> -	static int next_node = -1;
> +	static int next_node = NUMA_NO_NODE;
>  
> -	if (next_node == -1) {
> +	if (next_node == NUMA_NO_NODE) {
>  		next_node = first_online_node;
>  		return next_node;
>  	}
> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
> index f1a441ab..1aeefc7 100644
> --- a/drivers/dma/dmaengine.c
> +++ b/drivers/dma/dmaengine.c
> @@ -386,7 +386,8 @@ EXPORT_SYMBOL(dma_issue_pending_all);
>  static bool dma_chan_is_local(struct dma_chan *chan, int cpu)
>  {
>  	int node = dev_to_node(chan->device->dev);
> -	return node == -1 || cpumask_test_cpu(cpu, cpumask_of_node(node));
> +	return node == NUMA_NO_NODE ||
> +		cpumask_test_cpu(cpu, cpumask_of_node(node));
>  }
>  
>  /**
> diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c
> index 2baf38c..3e8acb8 100644
> --- a/drivers/infiniband/hw/hfi1/affinity.c
> +++ b/drivers/infiniband/hw/hfi1/affinity.c
> @@ -777,7 +777,7 @@ void hfi1_dev_affinity_clean_up(struct hfi1_devdata *dd)
>  	_dev_comp_vect_cpu_mask_clean_up(dd, entry);
>  unlock:
>  	mutex_unlock(&node_affinity.lock);
> -	dd->node = -1;
> +	dd->node = NUMA_NO_NODE;
>  }
>  
>  /*
> diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
> index 0904490..0bf4577 100644
> --- a/drivers/infiniband/hw/hfi1/init.c
> +++ b/drivers/infiniband/hw/hfi1/init.c
> @@ -1303,7 +1303,7 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev,
>  		dd->unit = ret;
>  		list_add(&dd->list, &hfi1_dev_list);
>  	}
> -	dd->node = -1;
> +	dd->node = NUMA_NO_NODE;
>  
>  	spin_unlock_irqrestore(&hfi1_devs_lock, flags);
>  	idr_preload_end();
> diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
> index d9c748b..86a9c19 100644
> --- a/drivers/iommu/dmar.c
> +++ b/drivers/iommu/dmar.c
> @@ -477,7 +477,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
>  			int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
>  
>  			if (!node_online(node))
> -				node = -1;
> +				node = NUMA_NO_NODE;
>  			drhd->iommu->node = node;
>  			return 0;
>  		}
> @@ -1062,7 +1062,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
>  	iommu->msagaw = msagaw;
>  	iommu->segment = drhd->segment;
>  
> -	iommu->node = -1;
> +	iommu->node = NUMA_NO_NODE;
>  
>  	ver = readl(iommu->reg + DMAR_VER_REG);
>  	pr_info("%s: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index f3ccf02..9f6fb13 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -1772,7 +1772,7 @@ static struct dmar_domain *alloc_domain(int flags)
>  		return NULL;
>  
>  	memset(domain, 0, sizeof(*domain));
> -	domain->nid = -1;
> +	domain->nid = NUMA_NO_NODE;
>  	domain->flags = flags;
>  	domain->has_iotlb_device = false;
>  	INIT_LIST_HEAD(&domain->devices);
> diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
> index 3e02de0..81bd41c 100644
> --- a/drivers/media/pci/ivtv/ivtvfb.c
> +++ b/drivers/media/pci/ivtv/ivtvfb.c
> @@ -1054,7 +1054,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
>  
>  	/* Generate valid fb_info */
>  
> -	oi->ivtvfb_info.node = -1;
> +	oi->ivtvfb_info.node = NUMA_NO_NODE;
>  	oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
>  	oi->ivtvfb_info.fbops = &ivtvfb_ops;
>  	oi->ivtvfb_info.par = itv;
> diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c
> index 1a89593..56a2d41 100644
> --- a/drivers/media/platform/vivid/vivid-osd.c
> +++ b/drivers/media/platform/vivid/vivid-osd.c
> @@ -309,7 +309,7 @@ static int vivid_fb_init_vidmode(struct vivid_dev *dev)
>  
>  	/* Generate valid fb_info */
>  
> -	dev->fb_info.node = -1;
> +	dev->fb_info.node = NUMA_NO_NODE;
>  	dev->fb_info.flags = FBINFO_FLAG_DEFAULT;
>  	dev->fb_info.fbops = &vivid_fb_ops;
>  	dev->fb_info.par = dev;
> diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
> index 0441abe..eef36dd 100644
> --- a/drivers/misc/sgi-xp/xpc_uv.c
> +++ b/drivers/misc/sgi-xp/xpc_uv.c
> @@ -61,7 +61,7 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
>  					 XPC_NOTIFY_MSG_SIZE_UV)
>  #define XPC_NOTIFY_IRQ_NAME		"xpc_notify"
>  
> -static int xpc_mq_node = -1;
> +static int xpc_mq_node = NUMA_NO_NODE;
>  
>  static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
>  static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index 113b38e..4fae85c 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -6414,7 +6414,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
>  {
>  	struct device *dev = tx_ring->dev;
>  	int orig_node = dev_to_node(dev);
> -	int ring_node = -1;
> +	int ring_node = NUMA_NO_NODE;
>  	int size;
>  
>  	size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
> @@ -6508,7 +6508,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
>  {
>  	struct device *dev = rx_ring->dev;
>  	int orig_node = dev_to_node(dev);
> -	int ring_node = -1;
> +	int ring_node = NUMA_NO_NODE;
>  	int size;
>  
>  	size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
> diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c
> index ee212be..298be9b 100644
> --- a/drivers/video/fbdev/mmp/fb/mmpfb.c
> +++ b/drivers/video/fbdev/mmp/fb/mmpfb.c
> @@ -519,7 +519,7 @@ static int fb_info_setup(struct fb_info *info,
>  	/* Initialise static fb parameters.*/
>  	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
>  		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
> -	info->node = -1;
> +	info->node = NUMA_NO_NODE;
>  	strcpy(info->fix.id, fbi->name);
>  	info->fix.type = FB_TYPE_PACKED_PIXELS;
>  	info->fix.type_aux = 0;
> diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c
> index e31340f..7d775de 100644
> --- a/drivers/video/fbdev/pxa168fb.c
> +++ b/drivers/video/fbdev/pxa168fb.c
> @@ -649,7 +649,7 @@ static int pxa168fb_probe(struct platform_device *pdev)
>  	 */
>  	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
>  		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
> -	info->node = -1;
> +	info->node = NUMA_NO_NODE;
>  	strlcpy(info->fix.id, mi->id, 16);
>  	info->fix.type = FB_TYPE_PACKED_PIXELS;
>  	info->fix.type_aux = 0;
> diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c
> index 696106e..8b0f20c 100644
> --- a/drivers/video/fbdev/w100fb.c
> +++ b/drivers/video/fbdev/w100fb.c
> @@ -703,7 +703,7 @@ int w100fb_probe(struct platform_device *pdev)
>  	info->fbops = &w100fb_ops;
>  	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
>  		FBINFO_HWACCEL_FILLRECT;
> -	info->node = -1;
> +	info->node = NUMA_NO_NODE;
>  	info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
>  	info->screen_size = REMAPPED_FB_LEN;
>  
> diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
> index d06e27e..11111f6 100644
> --- a/fs/ocfs2/dlm/dlmcommon.h
> +++ b/fs/ocfs2/dlm/dlmcommon.h
> @@ -1121,7 +1121,7 @@ static inline void dlm_node_iter_init(unsigned long *map,
>  				      struct dlm_node_iter *iter)
>  {
>  	memcpy(iter->node_map, map, sizeof(iter->node_map));
> -	iter->curnode = -1;
> +	iter->curnode = NUMA_NO_NODE;
>  }
>  
>  static inline int dlm_node_iter_next(struct dlm_node_iter *iter)
> diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
> index 2acd58b..381a323 100644
> --- a/fs/ocfs2/dlm/dlmdomain.c
> +++ b/fs/ocfs2/dlm/dlmdomain.c
> @@ -546,7 +546,7 @@ static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm)
>  
>  static void __dlm_print_nodes(struct dlm_ctxt *dlm)
>  {
> -	int node = -1, num = 0;
> +	int node = NUMA_NO_NODE, num = 0;
>  
>  	assert_spin_locked(&dlm->spinlock);
>  
> @@ -613,7 +613,7 @@ static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, u32 msg_type,
>  
>  static void dlm_begin_exit_domain(struct dlm_ctxt *dlm)
>  {
> -	int node = -1;
> +	int node = NUMA_NO_NODE;
>  
>  	/* Support for begin exit domain was added in 1.2 */
>  	if (dlm->dlm_locking_proto.pv_major == 1 &&
> @@ -1407,7 +1407,7 @@ static int dlm_send_join_cancels(struct dlm_ctxt *dlm,
>  	}
>  
>  	status = 0;
> -	node = -1;
> +	node = NUMA_NO_NODE;
>  	while ((node = find_next_bit(node_map, O2NM_MAX_NODES,
>  				     node + 1)) < O2NM_MAX_NODES) {
>  		if (node == dlm->node_num)
> @@ -1547,7 +1547,7 @@ static void dlm_send_join_asserts(struct dlm_ctxt *dlm,
>  	int status, node, live;
>  
>  	status = 0;
> -	node = -1;
> +	node = NUMA_NO_NODE;
>  	while ((node = find_next_bit(node_map, O2NM_MAX_NODES,
>  				     node + 1)) < O2NM_MAX_NODES) {
>  		if (node == dlm->node_num)
> @@ -1631,7 +1631,7 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
>  
>  	spin_unlock(&dlm->spinlock);
>  
> -	node = -1;
> +	node = NUMA_NO_NODE;
>  	while ((node = find_next_bit(ctxt->live_map, O2NM_MAX_NODES,
>  				     node + 1)) < O2NM_MAX_NODES) {
>  		if (node == dlm->node_num)
> diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
> index 826f056..e54bbbc 100644
> --- a/fs/ocfs2/dlm/dlmmaster.c
> +++ b/fs/ocfs2/dlm/dlmmaster.c
> @@ -1183,7 +1183,7 @@ static void dlm_bitmap_diff_iter_init(struct dlm_bitmap_diff_iter *iter,
>  	unsigned long p1, p2;
>  	int i;
>  
> -	iter->curnode = -1;
> +	iter->curnode = NUMA_NO_NODE;
>  	iter->orig_bm = orig_bm;
>  	iter->cur_bm = cur_bm;
>  
> diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
> index 802636d5..704fa8b 100644
> --- a/fs/ocfs2/dlm/dlmrecovery.c
> +++ b/fs/ocfs2/dlm/dlmrecovery.c
> @@ -2903,7 +2903,7 @@ static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm)
>  	}
>  	if (stage == 1) {
>  		/* reset the node_iter back to the top and send finalize2 */
> -		iter.curnode = -1;
> +		iter.curnode = NUMA_NO_NODE;
>  		stage = 2;
>  		goto stage2;
>  	}
> diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
> index d2fb97b..a673efa 100644
> --- a/fs/ocfs2/stack_user.c
> +++ b/fs/ocfs2/stack_user.c
> @@ -171,7 +171,7 @@ union ocfs2_control_message {
>  static struct ocfs2_stack_plugin ocfs2_user_plugin;
>  
>  static atomic_t ocfs2_control_opened;
> -static int ocfs2_control_this_node = -1;
> +static int ocfs2_control_this_node = NUMA_NO_NODE;
>  static struct ocfs2_protocol_version running_proto;
>  
>  static LIST_HEAD(ocfs2_live_connection_list);
> @@ -589,7 +589,7 @@ static int ocfs2_control_release(struct inode *inode, struct file *file)
>  		 * Last valid close clears the node number and resets
>  		 * the locking protocol version
>  		 */
> -		ocfs2_control_this_node = -1;
> +		ocfs2_control_this_node = NUMA_NO_NODE;
>  		running_proto.pv_major = 0;
>  		running_proto.pv_minor = 0;
>  	}
> @@ -612,7 +612,7 @@ static int ocfs2_control_open(struct inode *inode, struct file *file)
>  	p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
>  	if (!p)
>  		return -ENOMEM;
> -	p->op_this_node = -1;
> +	p->op_this_node = NUMA_NO_NODE;
>  
>  	mutex_lock(&ocfs2_control_lock);
>  	file->private_data = p;
> diff --git a/init/init_task.c b/init/init_task.c
> index 5aebe3b..6641836 100644
> --- a/init/init_task.c
> +++ b/init/init_task.c
> @@ -154,7 +154,7 @@ struct task_struct init_task
>  	.vtime.state	= VTIME_SYS,
>  #endif
>  #ifdef CONFIG_NUMA_BALANCING
> -	.numa_preferred_nid = -1,
> +	.numa_preferred_nid = NUMA_NO_NODE,
>  	.numa_group	= NULL,
>  	.numa_faults	= NULL,
>  #endif
> diff --git a/kernel/kthread.c b/kernel/kthread.c
> index 087d18d..77f3d94 100644
> --- a/kernel/kthread.c
> +++ b/kernel/kthread.c
> @@ -675,7 +675,7 @@ __kthread_create_worker(int cpu, unsigned int flags,
>  {
>  	struct kthread_worker *worker;
>  	struct task_struct *task;
> -	int node = -1;
> +	int node = NUMA_NO_NODE;
>  
>  	worker = kzalloc(sizeof(*worker), GFP_KERNEL);
>  	if (!worker)
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index ee271bb..d830fa7 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -1161,7 +1161,7 @@ void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
>  
>  	/* New address space, reset the preferred nid */
>  	if (!(clone_flags & CLONE_VM)) {
> -		p->numa_preferred_nid = -1;
> +		p->numa_preferred_nid = NUMA_NO_NODE;
>  		return;
>  	}
>  
> @@ -1181,13 +1181,13 @@ void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
>  
>  static void account_numa_enqueue(struct rq *rq, struct task_struct *p)
>  {
> -	rq->nr_numa_running += (p->numa_preferred_nid != -1);
> +	rq->nr_numa_running += (p->numa_preferred_nid != NUMA_NO_NODE);
>  	rq->nr_preferred_running += (p->numa_preferred_nid == task_node(p));
>  }
>  
>  static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
>  {
> -	rq->nr_numa_running -= (p->numa_preferred_nid != -1);
> +	rq->nr_numa_running -= (p->numa_preferred_nid != NUMA_NO_NODE);
>  	rq->nr_preferred_running -= (p->numa_preferred_nid == task_node(p));
>  }
>  
> @@ -1401,7 +1401,7 @@ bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
>  	 * two full passes of the "multi-stage node selection" test that is
>  	 * executed below.
>  	 */
> -	if ((p->numa_preferred_nid == -1 || p->numa_scan_seq <= 4) &&
> +	if ((p->numa_preferred_nid == NUMA_NO_NODE || p->numa_scan_seq <= 4) &&
>  	    (cpupid_pid_unset(last_cpupid) || cpupid_match_pid(p, last_cpupid)))
>  		return true;
>  
> @@ -1849,7 +1849,7 @@ static void numa_migrate_preferred(struct task_struct *p)
>  	unsigned long interval = HZ;
>  
>  	/* This task has no NUMA fault statistics yet */
> -	if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults))
> +	if (unlikely(p->numa_preferred_nid == NUMA_NO_NODE || !p->numa_faults))
>  		return;
>  
>  	/* Periodically retry migrating the task to the preferred node */
> @@ -2096,7 +2096,7 @@ static int preferred_group_nid(struct task_struct *p, int nid)
>  
>  static void task_numa_placement(struct task_struct *p)
>  {
> -	int seq, nid, max_nid = -1;
> +	int seq, nid, max_nid = NUMA_NO_NODE;
>  	unsigned long max_faults = 0;
>  	unsigned long fault_types[2] = { 0, 0 };
>  	unsigned long total_faults;
> @@ -2639,7 +2639,8 @@ static void update_scan_period(struct task_struct *p, int new_cpu)
>  		 * the preferred node.
>  		 */
>  		if (dst_nid == p->numa_preferred_nid ||
> -		    (p->numa_preferred_nid != -1 && src_nid != p->numa_preferred_nid))
> +		    (p->numa_preferred_nid != NUMA_NO_NODE &&
> +			src_nid != p->numa_preferred_nid))
>  			return;
>  	}
>  
> diff --git a/lib/cpumask.c b/lib/cpumask.c
> index 8d666ab..a089c3f 100644
> --- a/lib/cpumask.c
> +++ b/lib/cpumask.c
> @@ -206,7 +206,7 @@ unsigned int cpumask_local_spread(unsigned int i, int node)
>  	/* Wrap: we always want a cpu. */
>  	i %= num_online_cpus();
>  
> -	if (node == -1) {
> +	if (node == NUMA_NO_NODE) {
>  		for_each_cpu(cpu, cpu_online_mask)
>  			if (i-- == 0)
>  				return cpu;
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 55478ab..5ccf89e 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1480,7 +1480,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
>  	struct anon_vma *anon_vma = NULL;
>  	struct page *page;
>  	unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
> -	int page_nid = -1, this_nid = numa_node_id();
> +	int page_nid = NUMA_NO_NODE, this_nid = numa_node_id();
>  	int target_nid, last_cpupid = -1;
>  	bool page_locked;
>  	bool migrated = false;
> @@ -1526,7 +1526,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
>  	 */
>  	page_locked = trylock_page(page);
>  	target_nid = mpol_misplaced(page, vma, haddr);
> -	if (target_nid == -1) {
> +	if (target_nid == NUMA_NO_NODE) {
>  		/* If the page was locked, there are no parallel migrations */
>  		if (page_locked)
>  			goto clear_pmdnuma;
> @@ -1534,7 +1534,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
>  
>  	/* Migration could have started since the pmd_trans_migrating check */
>  	if (!page_locked) {
> -		page_nid = -1;
> +		page_nid = NUMA_NO_NODE;
>  		if (!get_page_unless_zero(page))
>  			goto out_unlock;
>  		spin_unlock(vmf->ptl);
> @@ -1556,14 +1556,14 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
>  	if (unlikely(!pmd_same(pmd, *vmf->pmd))) {
>  		unlock_page(page);
>  		put_page(page);
> -		page_nid = -1;
> +		page_nid = NUMA_NO_NODE;
>  		goto out_unlock;
>  	}
>  
>  	/* Bail if we fail to protect against THP splits for any reason */
>  	if (unlikely(!anon_vma)) {
>  		put_page(page);
> -		page_nid = -1;
> +		page_nid = NUMA_NO_NODE;
>  		goto clear_pmdnuma;
>  	}
>  
> @@ -1625,7 +1625,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
>  	if (anon_vma)
>  		page_unlock_anon_vma_read(anon_vma);
>  
> -	if (page_nid != -1)
> +	if (page_nid != NUMA_NO_NODE)
>  		task_numa_fault(last_cpupid, page_nid, HPAGE_PMD_NR,
>  				flags);
>  
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index c007fb5..b769db7 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -887,7 +887,7 @@ static struct page *dequeue_huge_page_nodemask(struct hstate *h, gfp_t gfp_mask,
>  	struct zonelist *zonelist;
>  	struct zone *zone;
>  	struct zoneref *z;
> -	int node = -1;
> +	int node = NUMA_NO_NODE;
>  
>  	zonelist = node_zonelist(nid, gfp_mask);
>  
> diff --git a/mm/ksm.c b/mm/ksm.c
> index 5b0894b..d5f8834 100644
> --- a/mm/ksm.c
> +++ b/mm/ksm.c
> @@ -597,7 +597,7 @@ static struct stable_node *alloc_stable_node_chain(struct stable_node *dup,
>  		chain->chain_prune_time = jiffies;
>  		chain->rmap_hlist_len = STABLE_NODE_CHAIN;
>  #if defined (CONFIG_DEBUG_VM) && defined(CONFIG_NUMA)
> -		chain->nid = -1; /* debug */
> +		chain->nid = NUMA_NO_NODE; /* debug */
>  #endif
>  		ksm_stable_node_chains++;
>  
> diff --git a/mm/memory.c b/mm/memory.c
> index 4ad2d29..c0e0348 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -3564,7 +3564,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
>  {
>  	struct vm_area_struct *vma = vmf->vma;
>  	struct page *page = NULL;
> -	int page_nid = -1;
> +	int page_nid = NUMA_NO_NODE;
>  	int last_cpupid;
>  	int target_nid;
>  	bool migrated = false;
> @@ -3631,7 +3631,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
>  	target_nid = numa_migrate_prep(page, vma, vmf->address, page_nid,
>  			&flags);
>  	pte_unmap_unlock(vmf->pte, vmf->ptl);
> -	if (target_nid == -1) {
> +	if (target_nid == NUMA_NO_NODE) {
>  		put_page(page);
>  		goto out;
>  	}
> @@ -3645,7 +3645,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
>  		flags |= TNF_MIGRATE_FAIL;
>  
>  out:
> -	if (page_nid != -1)
> +	if (page_nid != NUMA_NO_NODE)
>  		task_numa_fault(last_cpupid, page_nid, 1, flags);
>  	return 0;
>  }
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 2b2b3cc..70e02f8 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -688,9 +688,9 @@ static void node_states_check_changes_online(unsigned long nr_pages,
>  {
>  	int nid = zone_to_nid(zone);
>  
> -	arg->status_change_nid = -1;
> -	arg->status_change_nid_normal = -1;
> -	arg->status_change_nid_high = -1;
> +	arg->status_change_nid = NUMA_NO_NODE;
> +	arg->status_change_nid_normal = NUMA_NO_NODE;
> +	arg->status_change_nid_high = NUMA_NO_NODE;
>  
>  	if (!node_state(nid, N_MEMORY))
>  		arg->status_change_nid = nid;
> @@ -1484,9 +1484,9 @@ static void node_states_check_changes_offline(unsigned long nr_pages,
>  	unsigned long present_pages = 0;
>  	enum zone_type zt;
>  
> -	arg->status_change_nid = -1;
> -	arg->status_change_nid_normal = -1;
> -	arg->status_change_nid_high = -1;
> +	arg->status_change_nid = NUMA_NO_NODE;
> +	arg->status_change_nid_normal = NUMA_NO_NODE;
> +	arg->status_change_nid_high = NUMA_NO_NODE;
>  
>  	/*
>  	 * Check whether node_states[N_NORMAL_MEMORY] will be changed.
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 5837a06..e4f8248 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2278,7 +2278,7 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
>  	unsigned long pgoff;
>  	int thiscpu = raw_smp_processor_id();
>  	int thisnid = cpu_to_node(thiscpu);
> -	int polnid = -1;
> +	int polnid = NUMA_NO_NODE;
>  	int ret = -1;
>  
>  	pol = get_vma_policy(vma, addr);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index a919ba5..9d38d9c 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -5846,7 +5846,7 @@ int __meminit __early_pfn_to_nid(unsigned long pfn,
>  		return state->last_nid;
>  
>  	nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn);
> -	if (nid != -1) {
> +	if (nid != NUMA_NO_NODE) {
>  		state->last_start = start_pfn;
>  		state->last_end = end_pfn;
>  		state->last_nid = nid;
> @@ -6607,7 +6607,7 @@ unsigned long __init node_map_pfn_alignment(void)
>  {
>  	unsigned long accl_mask = 0, last_end = 0;
>  	unsigned long start, end, mask;
> -	int last_nid = -1;
> +	int last_nid = NUMA_NO_NODE;
>  	int i, nid;
>  
>  	for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid) {
> diff --git a/mm/page_ext.c b/mm/page_ext.c
> index ae44f7a..dfb0206 100644
> --- a/mm/page_ext.c
> +++ b/mm/page_ext.c
> @@ -300,7 +300,7 @@ static int __meminit online_page_ext(unsigned long start_pfn,
>  	start = SECTION_ALIGN_DOWN(start_pfn);
>  	end = SECTION_ALIGN_UP(start_pfn + nr_pages);
>  
> -	if (nid == -1) {
> +	if (nid == NUMA_NO_NODE) {
>  		/*
>  		 * In this case, "nid" already exists and contains valid memory.
>  		 * "start_pfn" passed to us is a pfn which is an arg for
> diff --git a/net/core/pktgen.c b/net/core/pktgen.c
> index 6ac9198..af3a746 100644
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -3625,7 +3625,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
>  	pkt_dev->svlan_cfi = 0;
>  	pkt_dev->svlan_id = 0xffff;
>  	pkt_dev->burst = 1;
> -	pkt_dev->node = -1;
> +	pkt_dev->node = NUMA_NO_NODE;
>  
>  	err = pktgen_setup_dev(t->net, pkt_dev, ifname);
>  	if (err)
> diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
> index 86e1e37..0c56ae2 100644
> --- a/net/qrtr/qrtr.c
> +++ b/net/qrtr/qrtr.c
> @@ -101,7 +101,7 @@ static inline struct qrtr_sock *qrtr_sk(struct sock *sk)
>  	return container_of(sk, struct qrtr_sock, sk);
>  }
>  
> -static unsigned int qrtr_local_nid = -1;
> +static unsigned int qrtr_local_nid = NUMA_NO_NODE;
>  
>  /* for node ids */
>  static RADIX_TREE(qrtr_nodes, GFP_KERNEL);
> diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
> index 4419551..e0ad5f1 100644
> --- a/tools/perf/bench/numa.c
> +++ b/tools/perf/bench/numa.c
> @@ -298,7 +298,7 @@ static cpu_set_t bind_to_node(int target_node)
>  
>  	CPU_ZERO(&mask);
>  
> -	if (target_node == -1) {
> +	if (target_node == NUMA_NO_NODE) {
>  		for (cpu = 0; cpu < g->p.nr_cpus; cpu++)
>  			CPU_SET(cpu, &mask);
>  	} else {
> @@ -339,7 +339,7 @@ static void bind_to_memnode(int node)
>  	unsigned long nodemask;
>  	int ret;
>  
> -	if (node == -1)
> +	if (node == NUMA_NO_NODE)
>  		return;
>  
>  	BUG_ON(g->p.nr_nodes > (int)sizeof(nodemask)*8);
> @@ -1363,7 +1363,7 @@ static void init_thread_data(void)
>  		int cpu;
>  
>  		/* Allow all nodes by default: */
> -		td->bind_node = -1;
> +		td->bind_node = NUMA_NO_NODE;
>  
>  		/* Allow all CPUs by default: */
>  		CPU_ZERO(&td->bind_cpumask);
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: KASAN: use-after-free Read in nbp_vlan_rcu_free
From: nikolay @ 2018-11-12  8:32 UTC (permalink / raw)
  To: syzbot, bridge, davem, linux-kernel, netdev, roopa,
	syzkaller-bugs
In-Reply-To: <00000000000047feb5057a714975@google.com>

On 12 November 2018 06:51:02 CET, syzbot <syzbot+04681da557a0e49a52e5@syzkaller.appspotmail.com> wrote:
>Hello,
>
>syzbot found the following crash on:
>
>HEAD commit:    e12e00e388de Merge tag 'kbuild-fixes-v4.20' of
>git://git.k..
>git tree:       upstream
>console output:
>https://syzkaller.appspot.com/x/log.txt?x=14cdb6f5400000
>kernel config: 
>https://syzkaller.appspot.com/x/.config?x=8f215f21f041a0d7
>dashboard link:
>https://syzkaller.appspot.com/bug?extid=04681da557a0e49a52e5
>compiler:       gcc (GCC) 8.0.1 20180413 (experimental)
>
>Unfortunately, I don't have any reproducer for this crash yet.
>
>IMPORTANT: if you fix the bug, please add the following tag to the
>commit:
>Reported-by: syzbot+04681da557a0e49a52e5@syzkaller.appspotmail.com

Thanks, I'm about to fly out for LPC. Will take a look in a day.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox