* Re: [PATCH] can: fix warning in bcm_connect/proc_register
From: Cong Wang @ 2016-10-24 20:10 UTC (permalink / raw)
To: Oliver Hartkopp
Cc: Andrey Konovalov, David Miller, linux-can,
Linux Kernel Network Developers, LKML, syzkaller,
Kostya Serebryany, Alexander Potapenko, Dmitry Vyukov,
Eric Dumazet
In-Reply-To: <20161024191126.30256-1-socketcan@hartkopp.net>
On Mon, Oct 24, 2016 at 12:11 PM, Oliver Hartkopp
<socketcan@hartkopp.net> wrote:
> if (proc_dir) {
> /* unique socket address as filename */
> sprintf(bo->procname, "%lu", sock_i_ino(sk));
> bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
> proc_dir,
> &bcm_proc_fops, sk);
> + if (!bo->bcm_proc_read) {
> + ret = -ENOMEM;
> + goto fail;
> + }
Well, I meant we need to call proc_create_data() once per socket,
so we need a check before proc_create_data() too.
Thanks.
^ permalink raw reply
* Re: [PATCH] netfilter: ip_vs_sync: fix bogus maybe-uninitialized warning
From: Julian Anastasov @ 2016-10-24 19:47 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Wensong Zhang, Simon Horman, Pablo Neira Ayuso, Patrick McHardy,
Jozsef Kadlecsik, David S. Miller, Quentin Armitage, netdev,
lvs-devel, netfilter-devel, coreteam, linux-kernel
In-Reply-To: <20161024153454.2766113-1-arnd@arndb.de>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 3770 bytes --]
Hello,
On Mon, 24 Oct 2016, Arnd Bergmann wrote:
> Building the ip_vs_sync code with CONFIG_OPTIMIZE_INLINING on x86
> confuses the compiler to the point where it produces a rather
> dubious warning message:
>
> net/netfilter/ipvs/ip_vs_sync.c:1073:33: error: ‘opt.init_seq’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
> struct ip_vs_sync_conn_options opt;
> ^~~
> net/netfilter/ipvs/ip_vs_sync.c:1073:33: error: ‘opt.delta’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
> net/netfilter/ipvs/ip_vs_sync.c:1073:33: error: ‘opt.previous_delta’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
> net/netfilter/ipvs/ip_vs_sync.c:1073:33: error: ‘*((void *)&opt+12).init_seq’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
> net/netfilter/ipvs/ip_vs_sync.c:1073:33: error: ‘*((void *)&opt+12).delta’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
> net/netfilter/ipvs/ip_vs_sync.c:1073:33: error: ‘*((void *)&opt+12).previous_delta’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
>
> The problem appears to be a combination of a number of factors, including
> the __builtin_bswap32 compiler builtin being slightly odd, having a large
> amount of code inlined into a single function, and the way that some
> functions only get partially inlined here.
>
> I've spent way too much time trying to work out a way to improve the
> code, but the best I've come up with is to add an explicit memset
> right before the ip_vs_seq structure is first initialized here. When
> the compiler works correctly, this has absolutely no effect, but in the
> case that produces the warning, the warning disappears.
>
> In the process of analysing this warning, I also noticed that
> we use memcpy to copy the larger ip_vs_sync_conn_options structure
> over two members of the ip_vs_conn structure. This works because
> the layout is identical, but seems error-prone, so I'm changing
> this in the process to directly copy the two members. This change
> seemed to have no effect on the object code or the warning, but
> it deals with the same data, so I kept the two changes together.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
OK,
Acked-by: Julian Anastasov <ja@ssi.bg>
I guess, Simon will take the patch for ipvs-next.
> ---
> net/netfilter/ipvs/ip_vs_sync.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
> index 1b07578bedf3..9350530c16c1 100644
> --- a/net/netfilter/ipvs/ip_vs_sync.c
> +++ b/net/netfilter/ipvs/ip_vs_sync.c
> @@ -283,6 +283,7 @@ struct ip_vs_sync_buff {
> */
> static void ntoh_seq(struct ip_vs_seq *no, struct ip_vs_seq *ho)
> {
> + memset(ho, 0, sizeof(*ho));
> ho->init_seq = get_unaligned_be32(&no->init_seq);
> ho->delta = get_unaligned_be32(&no->delta);
> ho->previous_delta = get_unaligned_be32(&no->previous_delta);
So, now there is a double write here?
What about such constructs?:
*ho = (struct ip_vs_seq) {
.init_seq = get_unaligned_be32(&no->init_seq),
...
};
Any difference in the compiled code or warnings?
> @@ -917,8 +918,10 @@ static void ip_vs_proc_conn(struct netns_ipvs *ipvs, struct ip_vs_conn_param *pa
> kfree(param->pe_data);
> }
>
> - if (opt)
> - memcpy(&cp->in_seq, opt, sizeof(*opt));
> + if (opt) {
> + cp->in_seq = opt->in_seq;
> + cp->out_seq = opt->out_seq;
This fix is fine.
> + }
> atomic_set(&cp->in_pkts, sysctl_sync_threshold(ipvs));
> cp->state = state;
> cp->old_state = cp->state;
> --
> 2.9.0
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* Re: net/sctp: slab-out-of-bounds in sctp_sf_ootb
From: Marcelo Ricardo Leitner @ 2016-10-24 19:44 UTC (permalink / raw)
To: Andrey Konovalov
Cc: Vlad Yasevich, Neil Horman, David S. Miller, linux-sctp, netdev,
LKML, syzkaller, Kostya Serebryany, Alexander Potapenko,
Eric Dumazet, Dmitry Vyukov
In-Reply-To: <CAAeHK+xqO0gVjOMMLUksUF7oaQgzE+vr5cdUJa1Oa0r89FM7eQ@mail.gmail.com>
Hi Andrey,
On Mon, Oct 24, 2016 at 05:30:04PM +0200, Andrey Konovalov wrote:
> The problem is that sctp_walk_errors walks the chunk before its length
> is checked for overflow.
Exactly. The check is done too late, for the 2nd and subsequent chunks
only.
Please try the following patch, thanks. Note: not even compile tested.
---8<---
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 026e3bca4a94..8ec20a64a3f8 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3422,6 +3422,12 @@ sctp_disposition_t sctp_sf_ootb(struct net *net,
return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
commands);
+ /* Report violation if chunk len overflows */
+ ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
+ if (ch_end > skb_tail_pointer(skb))
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+ commands);
+
/* Now that we know we at least have a chunk header,
* do things that are type appropriate.
*/
@@ -3453,12 +3459,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net,
}
}
- /* Report violation if chunk len overflows */
- ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
- if (ch_end > skb_tail_pointer(skb))
- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
- commands);
-
ch = (sctp_chunkhdr_t *) ch_end;
} while (ch_end < skb_tail_pointer(skb));
^ permalink raw reply related
* [PATCH] net: ipv6: Do not consider link state for nexthop validation
From: David Ahern @ 2016-10-24 19:27 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
Similar to IPv4, do not consider link state when validating next hops.
Currently, if the link is down default routes can fail to insert:
$ ip -6 ro add vrf blue default via 2100:2::64 dev eth2
RTNETLINK answers: No route to host
With this patch the command succeeds.
Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
include/net/ip6_route.h | 1 +
net/ipv6/route.c | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index e0cd318d5103..f83e78d071a3 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -32,6 +32,7 @@ struct route_info {
#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008
#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
+#define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040
/* We do not (yet ?) support IPv6 jumbograms (RFC 2675)
* Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 3ac19eb81a86..947ed1ded026 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -658,7 +658,8 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
struct net_device *dev = rt->dst.dev;
if (dev && !netif_carrier_ok(dev) &&
- idev->cnf.ignore_routes_with_linkdown)
+ idev->cnf.ignore_routes_with_linkdown &&
+ !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
goto out;
if (rt6_check_expired(rt))
@@ -1052,6 +1053,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
int strict = 0;
strict |= flags & RT6_LOOKUP_F_IFACE;
+ strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
if (net->ipv6.devconf_all->forwarding == 0)
strict |= RT6_LOOKUP_F_REACHABLE;
@@ -1791,7 +1793,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
};
struct fib6_table *table;
struct rt6_info *rt;
- int flags = RT6_LOOKUP_F_IFACE;
+ int flags = RT6_LOOKUP_F_IFACE | RT6_LOOKUP_F_IGNORE_LINKSTATE;
table = fib6_get_table(net, cfg->fc_table);
if (!table)
--
2.1.4
^ permalink raw reply related
* Re: [net-next PATCH RFC 19/26] arch/sparc: Add option to skip DMA sync as a part of map and unmap
From: Alexander Duyck @ 2016-10-24 19:24 UTC (permalink / raw)
To: David Miller
Cc: Duyck, Alexander H, Netdev, linux-kernel@vger.kernel.org,
linux-mm, sparclinux, Jesper Dangaard Brouer
In-Reply-To: <20161024.142730.1316656811538193943.davem@davemloft.net>
On Mon, Oct 24, 2016 at 11:27 AM, David Miller <davem@davemloft.net> wrote:
> From: Alexander Duyck <alexander.h.duyck@intel.com>
> Date: Mon, 24 Oct 2016 08:06:07 -0400
>
>> This change allows us to pass DMA_ATTR_SKIP_CPU_SYNC which allows us to
>> avoid invoking cache line invalidation if the driver will just handle it
>> via a sync_for_cpu or sync_for_device call.
>>
>> Cc: "David S. Miller" <davem@davemloft.net>
>> Cc: sparclinux@vger.kernel.org
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>
> This is fine for avoiding the flush for performance reasons, but the
> chip isn't going to write anything back unless the device wrote into
> the area.
That is mostly what I am doing here. The original implementation was
mostly for performance. I am trying to take the attribute that was
already in place for ARM and apply it to all the other architectures.
So what will be happening now is that we call the map function with
this attribute set and then use the sync functions to map it to the
device and then pull the mapping later.
The idea is that if Jesper does his page pool stuff it would be
calling the map/unmap functions and then the drivers would be doing
the sync_for_cpu/sync_for_device. I want to make sure the map is
cheap and we will have to call sync_for_cpu from the drivers anyway
since there is no guarantee if we will have a new page or be reusing
an existing one.
- Alex
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [net-next PATCH RFC 02/26] swiotlb: Add support for DMA_ATTR_SKIP_CPU_SYNC
From: Alexander Duyck @ 2016-10-24 19:16 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: Alexander Duyck, Netdev, linux-kernel@vger.kernel.org, linux-mm,
Jesper Dangaard Brouer, David Miller
In-Reply-To: <20161024180934.GA24840@char.us.oracle.com>
On Mon, Oct 24, 2016 at 11:09 AM, Konrad Rzeszutek Wilk
<konrad.wilk@oracle.com> wrote:
> On Mon, Oct 24, 2016 at 08:04:37AM -0400, Alexander Duyck wrote:
>> As a first step to making DMA_ATTR_SKIP_CPU_SYNC apply to architectures
>> beyond just ARM I need to make it so that the swiotlb will respect the
>> flag. In order to do that I also need to update the swiotlb-xen since it
>> heavily makes use of the functionality.
>>
>> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>> ---
>> drivers/xen/swiotlb-xen.c | 40 ++++++++++++++++++++++----------------
>> include/linux/swiotlb.h | 6 ++++--
>> lib/swiotlb.c | 48 +++++++++++++++++++++++++++------------------
>> 3 files changed, 56 insertions(+), 38 deletions(-)
>>
>> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
>> index 87e6035..cf047d8 100644
>> --- a/drivers/xen/swiotlb-xen.c
>> +++ b/drivers/xen/swiotlb-xen.c
>> @@ -405,7 +405,8 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>> */
>> trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
>>
>> - map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir);
>> + map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir,
>> + attrs);
>> if (map == SWIOTLB_MAP_ERROR)
>> return DMA_ERROR_CODE;
>>
>> @@ -416,11 +417,13 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>> /*
>> * Ensure that the address returned is DMA'ble
>> */
>> - if (!dma_capable(dev, dev_addr, size)) {
>> - swiotlb_tbl_unmap_single(dev, map, size, dir);
>> - dev_addr = 0;
>> - }
>> - return dev_addr;
>> + if (dma_capable(dev, dev_addr, size))
>> + return dev_addr;
>> +
>> + swiotlb_tbl_unmap_single(dev, map, size, dir,
>> + attrs | DMA_ATTR_SKIP_CPU_SYNC);
>> +
>> + return DMA_ERROR_CODE;
>
> Why? This change (re-ordering the code - and returning DMA_ERROR_CODE instead
> of 0) does not have anything to do with the title.
>
> If you really feel strongly about it - then please send it as a seperate patch.
Okay I can do that. This was mostly just to clean up the formatting
because I was over 80 characters when I added the attribute. Changing
the return value to DMA_ERROR_CODE from 0 was based on the fact that
earlier in the function that is the value you return if there is a
mapping error.
>> }
>> EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
>>
>> @@ -444,7 +447,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
>>
>> /* NOTE: We use dev_addr here, not paddr! */
>> if (is_xen_swiotlb_buffer(dev_addr)) {
>> - swiotlb_tbl_unmap_single(hwdev, paddr, size, dir);
>> + swiotlb_tbl_unmap_single(hwdev, paddr, size, dir, attrs);
>> return;
>> }
>>
>> @@ -557,16 +560,9 @@ void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
>> start_dma_addr,
>> sg_phys(sg),
>> sg->length,
>> - dir);
>> - if (map == SWIOTLB_MAP_ERROR) {
>> - dev_warn(hwdev, "swiotlb buffer is full\n");
>> - /* Don't panic here, we expect map_sg users
>> - to do proper error handling. */
>> - xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
>> - attrs);
>> - sg_dma_len(sgl) = 0;
>> - return 0;
>> - }
>> + dir, attrs);
>> + if (map == SWIOTLB_MAP_ERROR)
>> + goto map_error;
>> xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
>> dev_addr,
>> map & ~PAGE_MASK,
>> @@ -589,6 +585,16 @@ void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
>> sg_dma_len(sg) = sg->length;
>> }
>> return nelems;
>> +map_error:
>> + dev_warn(hwdev, "swiotlb buffer is full\n");
>> + /*
>> + * Don't panic here, we expect map_sg users
>> + * to do proper error handling.
>> + */
>> + xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
>> + attrs | DMA_ATTR_SKIP_CPU_SYNC);
>> + sg_dma_len(sgl) = 0;
>> + return 0;
>> }
>
> This too. Why can't that be part of the existing code that was there?
Once again it was a formatting thing. I was indented too far and
adding the attribute pushed me over 80 characters so I broke it out to
a label to avoid the problem.
- Alex
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH] can: fix warning in bcm_connect/proc_register
From: Oliver Hartkopp @ 2016-10-24 19:11 UTC (permalink / raw)
To: andreyknvl, xiyou.wangcong, davem
Cc: linux-can, netdev, linux-kernel, syzkaller, kcc, glider, dvyukov,
edumazet, Oliver Hartkopp
Andrey Konovalov reported an issue with proc_register in bcm.c.
As suggested by Cong Wang this patch adds a lock_sock() protection and
a check for unsuccessful proc_create_data() in bcm_connect().
Reference: http://marc.info/?l=linux-netdev&m=147732648731237
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
net/can/bcm.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 8e999ff..8af9d25 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1549,24 +1549,31 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
struct sock *sk = sock->sk;
struct bcm_sock *bo = bcm_sk(sk);
+ int ret = 0;
if (len < sizeof(*addr))
return -EINVAL;
- if (bo->bound)
- return -EISCONN;
+ lock_sock(sk);
+
+ if (bo->bound) {
+ ret = -EISCONN;
+ goto fail;
+ }
/* bind a device to this socket */
if (addr->can_ifindex) {
struct net_device *dev;
dev = dev_get_by_index(&init_net, addr->can_ifindex);
- if (!dev)
- return -ENODEV;
-
+ if (!dev) {
+ ret = -ENODEV;
+ goto fail;
+ }
if (dev->type != ARPHRD_CAN) {
dev_put(dev);
- return -ENODEV;
+ ret = -ENODEV;
+ goto fail;
}
bo->ifindex = dev->ifindex;
@@ -1577,17 +1584,24 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
bo->ifindex = 0;
}
- bo->bound = 1;
-
if (proc_dir) {
/* unique socket address as filename */
sprintf(bo->procname, "%lu", sock_i_ino(sk));
bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
proc_dir,
&bcm_proc_fops, sk);
+ if (!bo->bcm_proc_read) {
+ ret = -ENOMEM;
+ goto fail;
+ }
}
- return 0;
+ bo->bound = 1;
+
+fail:
+ release_sock(sk);
+
+ return ret;
}
static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
--
2.9.3
^ permalink raw reply related
* Re: [net-next PATCH RFC 05/26] arch/avr32: Add option to skip sync on DMA map
From: Hans-Christian Noren Egtvedt @ 2016-10-24 18:27 UTC (permalink / raw)
To: Alexander Duyck
Cc: netdev, linux-kernel, linux-mm, brouer, Haavard Skinnemoen, davem
In-Reply-To: <20161024120452.16276.9594.stgit@ahduyck-blue-test.jf.intel.com>
Around Mon 24 Oct 2016 08:04:53 -0400 or thereabout, Alexander Duyck wrote:
> The use of DMA_ATTR_SKIP_CPU_SYNC was not consistent across all of the DMA
> APIs in the arch/arm folder. This change is meant to correct that so that
> we get consistent behavior.
Looks good (-:
> Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
> Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Acked-by: Hans-Christian Noren Egtvedt <egtvedt@samfundet.no>
> ---
> arch/avr32/mm/dma-coherent.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
> index 58610d0..54534e5 100644
> --- a/arch/avr32/mm/dma-coherent.c
> +++ b/arch/avr32/mm/dma-coherent.c
> @@ -146,7 +146,8 @@ static dma_addr_t avr32_dma_map_page(struct device *dev, struct page *page,
> {
> void *cpu_addr = page_address(page) + offset;
>
> - dma_cache_sync(dev, cpu_addr, size, direction);
> + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
> + dma_cache_sync(dev, cpu_addr, size, direction);
> return virt_to_bus(cpu_addr);
> }
>
> @@ -162,6 +163,10 @@ static int avr32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
>
> sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset;
> virt = sg_virt(sg);
> +
> + if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
> + continue;
> +
> dma_cache_sync(dev, virt, sg->length, direction);
> }
>
--
mvh
Hans-Christian Noren Egtvedt
^ permalink raw reply
* Re: [net-next PATCH RFC 19/26] arch/sparc: Add option to skip DMA sync as a part of map and unmap
From: David Miller @ 2016-10-24 18:27 UTC (permalink / raw)
To: alexander.h.duyck; +Cc: netdev, linux-kernel, linux-mm, sparclinux, brouer
In-Reply-To: <20161024120607.16276.5989.stgit@ahduyck-blue-test.jf.intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
Date: Mon, 24 Oct 2016 08:06:07 -0400
> This change allows us to pass DMA_ATTR_SKIP_CPU_SYNC which allows us to
> avoid invoking cache line invalidation if the driver will just handle it
> via a sync_for_cpu or sync_for_device call.
>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: sparclinux@vger.kernel.org
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
This is fine for avoiding the flush for performance reasons, but the
chip isn't going to write anything back unless the device wrote into
the area.
^ permalink raw reply
* Re: net/can: warning in bcm_connect/proc_register
From: Oliver Hartkopp @ 2016-10-24 18:23 UTC (permalink / raw)
To: Andrey Konovalov, Cong Wang
Cc: Marc Kleine-Budde, David S. Miller, linux-can, netdev, LKML,
syzkaller, Kostya Serebryany, Alexander Potapenko, Dmitry Vyukov,
Eric Dumazet
In-Reply-To: <CAAeHK+xPUAcao+xufvBfLRZcCR4oDY-WfV-CJspYqArh0cqYUg@mail.gmail.com>
Hello Andrey, hello Cong,
thanks for catching this issue.
I added lock_sock() and a check for a failing proc_create_data() below.
Can you please check if it solved the issue?
I tested the patched version with the stress tool as advised by Andrey
and did not see any problems in dmesg anymore.
If ok I can provide a proper patch.
Many thanks,
Oliver
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 8e999ff..8af9d25 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1549,24 +1549,31 @@ static int bcm_connect(struct socket *sock,
struct sockaddr *uaddr, int len,
struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
struct sock *sk = sock->sk;
struct bcm_sock *bo = bcm_sk(sk);
+ int ret = 0;
if (len < sizeof(*addr))
return -EINVAL;
- if (bo->bound)
- return -EISCONN;
+ lock_sock(sk);
+
+ if (bo->bound) {
+ ret = -EISCONN;
+ goto fail;
+ }
/* bind a device to this socket */
if (addr->can_ifindex) {
struct net_device *dev;
dev = dev_get_by_index(&init_net, addr->can_ifindex);
- if (!dev)
- return -ENODEV;
-
+ if (!dev) {
+ ret = -ENODEV;
+ goto fail;
+ }
if (dev->type != ARPHRD_CAN) {
dev_put(dev);
- return -ENODEV;
+ ret = -ENODEV;
+ goto fail;
}
bo->ifindex = dev->ifindex;
@@ -1577,17 +1584,24 @@ static int bcm_connect(struct socket *sock,
struct sockaddr *uaddr, int len,
bo->ifindex = 0;
}
- bo->bound = 1;
-
if (proc_dir) {
/* unique socket address as filename */
sprintf(bo->procname, "%lu", sock_i_ino(sk));
bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
proc_dir,
&bcm_proc_fops, sk);
+ if (!bo->bcm_proc_read) {
+ ret = -ENOMEM;
+ goto fail;
+ }
}
- return 0;
+ bo->bound = 1;
+
+fail:
+ release_sock(sk);
+
+ return ret;
}
static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t
size,
On 10/24/2016 07:31 PM, Andrey Konovalov wrote:
> Hi Cong,
>
> I'm able to reproduce it by running
> https://gist.github.com/xairy/33f2eb6bf807b004e643bae36c3d02d7 in a
> tight parallel loop with stress
> (https://godoc.org/golang.org/x/tools/cmd/stress):
> $ gcc -lpthread tmp.c
> $ ./stress ./a.out
>
> The C program was generated from the following syzkaller prog:
> mmap(&(0x7f0000000000/0x991000)=nil, (0x991000), 0x3, 0x32,
> 0xffffffffffffffff, 0x0)
> socket(0x1d, 0x80002, 0x2)
> r0 = socket(0x1d, 0x80002, 0x2)
> connect$nfc_llcp(r0, &(0x7f000000c000)={0x27, 0x100000000, 0x0, 0x5,
> 0x100000000, 0x1,
> "341b3a01b257849ca1d7d1ff9f999d8127b185f88d1d775d59c88a3aa6a8ddacdf2bdc324ea6578a21b85114610186c3817c34b05eaffd2c3f54f57fa81ba0",
> 0x1ff}, 0x60)
> connect$nfc_llcp(r0, &(0x7f0000991000-0x60)={0x27, 0x100000000, 0x1,
> 0x5, 0xfffffffffffffffd, 0x0,
> "341b3a01b257849ca1d7d1ff9f999d8127b185f88d1d775dbec88a3aa6a8ddacdf2bdc324ea6578a21b85114610186c3817c34b05eaffd2c3f54f57fa81ba0",
> 0x1ff}, 0x60)
>
> Unfortunately I wasn't able to create a simpler reproducer.
>
> Thanks!
>
> On Mon, Oct 24, 2016 at 6:58 PM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
>> On Mon, Oct 24, 2016 at 9:21 AM, Andrey Konovalov <andreyknvl@google.com> wrote:
>>> Hi,
>>>
>>> I've got the following error report while running the syzkaller fuzzer:
>>>
>>> WARNING: CPU: 0 PID: 32451 at fs/proc/generic.c:345 proc_register+0x25e/0x300
>>> proc_dir_entry 'can-bcm/249757' already registered
>>> Kernel panic - not syncing: panic_on_warn set ...
>>
>> Looks like we have two problems here:
>>
>> 1) A check for bo->bcm_proc_read != NULL seems missing
>> 2) We need to lock the sock in bcm_connect().
>>
>> I will work on a patch. Meanwhile, it would help a lot if you could provide
>> a reproducer.
>>
>> Thanks!
^ permalink raw reply related
* Re: [net-next PATCH RFC 01/26] swiotlb: Drop unused function swiotlb_map_sg
From: Konrad Rzeszutek Wilk @ 2016-10-24 18:10 UTC (permalink / raw)
To: Alexander Duyck; +Cc: netdev, linux-kernel, linux-mm, brouer, davem
In-Reply-To: <20161024120431.16276.89246.stgit@ahduyck-blue-test.jf.intel.com>
On Mon, Oct 24, 2016 at 08:04:31AM -0400, Alexander Duyck wrote:
> There are no users for swiotlb_map_sg so we might as well just drop it.
>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thought I swear I saw a familiar patch by Christopher Hellwig at some point..
but maybe that patchset had been dropped.
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
> include/linux/swiotlb.h | 4 ----
> lib/swiotlb.c | 8 --------
> 2 files changed, 12 deletions(-)
>
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 5f81f8a..e237b6f 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -72,10 +72,6 @@ extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
> size_t size, enum dma_data_direction dir,
> unsigned long attrs);
>
> -extern int
> -swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
> - enum dma_data_direction dir);
> -
> extern void
> swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
> enum dma_data_direction dir);
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 22e13a0..47aad37 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -910,14 +910,6 @@ void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
> }
> EXPORT_SYMBOL(swiotlb_map_sg_attrs);
>
> -int
> -swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
> - enum dma_data_direction dir)
> -{
> - return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, 0);
> -}
> -EXPORT_SYMBOL(swiotlb_map_sg);
> -
> /*
> * Unmap a set of streaming mode DMA translations. Again, cpu read rules
> * concerning calls here are the same as for swiotlb_unmap_page() above.
>
^ permalink raw reply
* Re: [net-next PATCH RFC 02/26] swiotlb: Add support for DMA_ATTR_SKIP_CPU_SYNC
From: Konrad Rzeszutek Wilk @ 2016-10-24 18:09 UTC (permalink / raw)
To: Alexander Duyck; +Cc: netdev, linux-kernel, linux-mm, brouer, davem
In-Reply-To: <20161024120437.16276.68349.stgit@ahduyck-blue-test.jf.intel.com>
On Mon, Oct 24, 2016 at 08:04:37AM -0400, Alexander Duyck wrote:
> As a first step to making DMA_ATTR_SKIP_CPU_SYNC apply to architectures
> beyond just ARM I need to make it so that the swiotlb will respect the
> flag. In order to do that I also need to update the swiotlb-xen since it
> heavily makes use of the functionality.
>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
> drivers/xen/swiotlb-xen.c | 40 ++++++++++++++++++++++----------------
> include/linux/swiotlb.h | 6 ++++--
> lib/swiotlb.c | 48 +++++++++++++++++++++++++++------------------
> 3 files changed, 56 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
> index 87e6035..cf047d8 100644
> --- a/drivers/xen/swiotlb-xen.c
> +++ b/drivers/xen/swiotlb-xen.c
> @@ -405,7 +405,8 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
> */
> trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
>
> - map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir);
> + map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir,
> + attrs);
> if (map == SWIOTLB_MAP_ERROR)
> return DMA_ERROR_CODE;
>
> @@ -416,11 +417,13 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
> /*
> * Ensure that the address returned is DMA'ble
> */
> - if (!dma_capable(dev, dev_addr, size)) {
> - swiotlb_tbl_unmap_single(dev, map, size, dir);
> - dev_addr = 0;
> - }
> - return dev_addr;
> + if (dma_capable(dev, dev_addr, size))
> + return dev_addr;
> +
> + swiotlb_tbl_unmap_single(dev, map, size, dir,
> + attrs | DMA_ATTR_SKIP_CPU_SYNC);
> +
> + return DMA_ERROR_CODE;
Why? This change (re-ordering the code - and returning DMA_ERROR_CODE instead
of 0) does not have anything to do with the title.
If you really feel strongly about it - then please send it as a seperate patch.
> }
> EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
>
> @@ -444,7 +447,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
>
> /* NOTE: We use dev_addr here, not paddr! */
> if (is_xen_swiotlb_buffer(dev_addr)) {
> - swiotlb_tbl_unmap_single(hwdev, paddr, size, dir);
> + swiotlb_tbl_unmap_single(hwdev, paddr, size, dir, attrs);
> return;
> }
>
> @@ -557,16 +560,9 @@ void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
> start_dma_addr,
> sg_phys(sg),
> sg->length,
> - dir);
> - if (map == SWIOTLB_MAP_ERROR) {
> - dev_warn(hwdev, "swiotlb buffer is full\n");
> - /* Don't panic here, we expect map_sg users
> - to do proper error handling. */
> - xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
> - attrs);
> - sg_dma_len(sgl) = 0;
> - return 0;
> - }
> + dir, attrs);
> + if (map == SWIOTLB_MAP_ERROR)
> + goto map_error;
> xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
> dev_addr,
> map & ~PAGE_MASK,
> @@ -589,6 +585,16 @@ void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
> sg_dma_len(sg) = sg->length;
> }
> return nelems;
> +map_error:
> + dev_warn(hwdev, "swiotlb buffer is full\n");
> + /*
> + * Don't panic here, we expect map_sg users
> + * to do proper error handling.
> + */
> + xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
> + attrs | DMA_ATTR_SKIP_CPU_SYNC);
> + sg_dma_len(sgl) = 0;
> + return 0;
> }
This too. Why can't that be part of the existing code that was there?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [net-next PATCH RFC 26/26] igb: Revert "igb: Revert support for build_skb in igb"
From: Alexander Duyck @ 2016-10-24 12:06 UTC (permalink / raw)
To: netdev, linux-kernel, linux-mm; +Cc: davem, brouer
In-Reply-To: <20161024115737.16276.71059.stgit@ahduyck-blue-test.jf.intel.com>
This reverts commit f9d40f6a9921 ("igb: Revert support for build_skb in
igb") and adds a few changes to update it to work with the latest version
of igb. We are now able to revert the removal of this due to the fact
that with the recent changes to the page count and the use of
DMA_ATTR_SKIP_CPU_SYNC we can make the pages writable so we should not be
invalidating the additional data added when we call build_skb.
The biggest risk with this change is that we are now not able to support
full jumbo frames when using build_skb. Instead we can only support up to
2K minus the skb overhead and padding offset.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ethernet/intel/igb/igb.h | 29 ++++++
drivers/net/ethernet/intel/igb/igb_main.c | 130 ++++++++++++++++++++++++++---
2 files changed, 142 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index acbc3ab..c3420f3 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -145,6 +145,10 @@ struct vf_data_storage {
#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
#define IGB_RX_BUFSZ IGB_RXBUFFER_2048
+#define IGB_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
+#define IGB_MAX_BUILD_SKB_SIZE \
+ (SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) - (IGB_SKB_PAD + IGB_TS_HDR_LEN))
+
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */
@@ -301,12 +305,29 @@ struct igb_q_vector {
};
enum e1000_ring_flags_t {
- IGB_RING_FLAG_RX_SCTP_CSUM,
- IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
- IGB_RING_FLAG_TX_CTX_IDX,
- IGB_RING_FLAG_TX_DETECT_HANG
+ IGB_RING_FLAG_RX_SCTP_CSUM = 0,
+#if (NET_IP_ALIGN != 0)
+ IGB_RING_FLAG_RX_BUILD_SKB_ENABLED = 1,
+#endif
+ IGB_RING_FLAG_RX_LB_VLAN_BSWAP = 2,
+ IGB_RING_FLAG_TX_CTX_IDX = 3,
+ IGB_RING_FLAG_TX_DETECT_HANG = 4,
+#if (NET_IP_ALIGN == 0)
+#if (L1_CACHE_SHIFT < 5)
+ IGB_RING_FLAG_RX_BUILD_SKB_ENABLED = 5,
+#else
+ IGB_RING_FLAG_RX_BUILD_SKB_ENABLED = L1_CACHE_SHIFT,
+#endif
+#endif
};
+#define ring_uses_build_skb(ring) \
+ test_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+#define set_ring_build_skb_enabled(ring) \
+ set_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+#define clear_ring_build_skb_enabled(ring) \
+ clear_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+
#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
#define IGB_RX_DESC(R, i) \
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 83fdef6..7674a50 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3761,6 +3761,16 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
wr32(E1000_RXDCTL(reg_idx), rxdctl);
}
+static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
+ struct igb_ring *rx_ring)
+{
+ /* set build_skb flag */
+ if (adapter->max_frame_size <= IGB_MAX_BUILD_SKB_SIZE)
+ set_ring_build_skb_enabled(rx_ring);
+ else
+ clear_ring_build_skb_enabled(rx_ring);
+}
+
/**
* igb_configure_rx - Configure receive Unit after Reset
* @adapter: board private structure
@@ -3778,8 +3788,12 @@ static void igb_configure_rx(struct igb_adapter *adapter)
/* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring
*/
- for (i = 0; i < adapter->num_rx_queues; i++)
- igb_configure_rx_ring(adapter, adapter->rx_ring[i]);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct igb_ring *rx_ring = adapter->rx_ring[i];
+
+ igb_set_rx_buffer_len(adapter, rx_ring);
+ igb_configure_rx_ring(adapter, rx_ring);
+ }
}
/**
@@ -4238,7 +4252,7 @@ static void igb_set_rx_mode(struct net_device *netdev)
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
unsigned int vfn = adapter->vfs_allocated_count;
- u32 rctl = 0, vmolr = 0;
+ u32 rctl = 0, vmolr = 0, rlpml = MAX_JUMBO_FRAME_SIZE;
int count;
/* Check for Promiscuous and All Multicast modes */
@@ -4310,12 +4324,18 @@ static void igb_set_rx_mode(struct net_device *netdev)
vmolr |= rd32(E1000_VMOLR(vfn)) &
~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE);
- /* enable Rx jumbo frames, no need for restriction */
+ /* enable Rx jumbo frames, restrict as needed to support build_skb */
vmolr &= ~E1000_VMOLR_RLPML_MASK;
- vmolr |= MAX_JUMBO_FRAME_SIZE | E1000_VMOLR_LPE;
+ vmolr |= E1000_VMOLR_LPE;
+ vmolr |= (adapter->max_frame_size <= IGB_MAX_BUILD_SKB_SIZE) ?
+ IGB_MAX_BUILD_SKB_SIZE : MAX_JUMBO_FRAME_SIZE;
+
+ if (!adapter->vfs_allocated_count &&
+ (adapter->max_frame_size <= IGB_MAX_BUILD_SKB_SIZE))
+ rlpml = IGB_MAX_BUILD_SKB_SIZE;
wr32(E1000_VMOLR(vfn), vmolr);
- wr32(E1000_RLPML, MAX_JUMBO_FRAME_SIZE);
+ wr32(E1000_RLPML, rlpml);
igb_restore_vf_multicasts(adapter);
}
@@ -5046,9 +5066,9 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
}
#define IGB_SET_FLAG(_input, _flag, _result) \
- ((_flag <= _result) ? \
- ((u32)(_input & _flag) * (_result / _flag)) : \
- ((u32)(_input & _flag) / (_flag / _result)))
+ (((_flag) <= (_result)) ? \
+ ((u32)(_input & (_flag)) * ((_result) / (_flag))) : \
+ ((u32)(_input & (_flag)) / ((_flag) / (_result))))
static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags)
{
@@ -6829,7 +6849,7 @@ static inline bool igb_page_is_reserved(struct page *page)
static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,
struct page *page,
- unsigned int truesize)
+ const unsigned int truesize)
{
unsigned int pagecnt_bias = rx_buffer->pagecnt_bias--;
@@ -6888,7 +6908,7 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,
struct page *page = rx_buffer->page;
unsigned char *va = page_address(page) + rx_buffer->page_offset;
#if (PAGE_SIZE < 8192)
- unsigned int truesize = IGB_RX_BUFSZ;
+ const unsigned int truesize = IGB_RX_BUFSZ;
#else
unsigned int truesize = SKB_DATA_ALIGN(size);
#endif
@@ -6933,6 +6953,78 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,
return igb_can_reuse_rx_page(rx_buffer, page, truesize);
}
+static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc)
+{
+ unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
+ struct igb_rx_buffer *rx_buffer;
+ struct sk_buff *skb;
+ struct page *page;
+ void *va;
+#if (PAGE_SIZE < 8192)
+ const unsigned int truesize = IGB_RX_BUFSZ;
+#else
+ unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+ SKB_DATA_ALIGN(NET_SKB_PAD +
+ NET_IP_ALIGN +
+ size);
+#endif
+
+ rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+ page = rx_buffer->page;
+ prefetchw(page);
+
+ /* we are reusing so sync this buffer for CPU use */
+ dma_sync_single_range_for_cpu(rx_ring->dev,
+ rx_buffer->dma,
+ rx_buffer->page_offset + IGB_SKB_PAD,
+ size,
+ DMA_FROM_DEVICE);
+
+ va = page_address(page) + rx_buffer->page_offset;
+
+ /* prefetch first cache line of first page */
+ prefetch(va + IGB_SKB_PAD);
+#if L1_CACHE_BYTES < 128
+ prefetch(va + L1_CACHE_BYTES + IGB_SKB_PAD);
+#endif
+
+ /* build an skb to around the page buffer */
+ skb = build_skb(va, truesize);
+ if (unlikely(!skb)) {
+ rx_ring->rx_stats.alloc_failed++;
+ return NULL;
+ }
+
+ /* update pointers within the skb to store the data */
+ skb_reserve(skb, IGB_SKB_PAD);
+ __skb_put(skb, size);
+
+ /* pull timestamp out of packet data */
+ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+ igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb);
+ __skb_pull(skb, IGB_TS_HDR_LEN);
+ }
+
+ if (igb_can_reuse_rx_page(rx_buffer, page, truesize)) {
+ /* hand second half of page back to the ring */
+ igb_reuse_rx_page(rx_ring, rx_buffer);
+ } else {
+ /* We are not reusing the buffer so unmap it and free
+ * any references we are holding to it
+ */
+ dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
+ PAGE_SIZE, DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ __page_frag_drain(page, 0, rx_buffer->pagecnt_bias);
+ }
+
+ /* clear contents of rx_buffer */
+ rx_buffer->page = NULL;
+
+ return skb;
+}
+
static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -7178,7 +7270,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
dma_rmb();
/* retrieve a buffer from the ring */
- skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
+ if (ring_uses_build_skb(rx_ring))
+ skb = igb_build_rx_buffer(rx_ring, rx_desc);
+ else
+ skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
/* exit if we failed to retrieve a buffer */
if (!skb)
@@ -7266,6 +7361,13 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
return true;
}
+static inline unsigned int igb_rx_offset(struct igb_ring *rx_ring)
+{
+ return IGB_SET_FLAG(rx_ring->flags,
+ 1 << IGB_RING_FLAG_RX_BUILD_SKB_ENABLED,
+ IGB_SKB_PAD);
+}
+
/**
* igb_alloc_rx_buffers - Replace used receive buffers; packet split
* @adapter: address of board private structure
@@ -7297,7 +7399,9 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
/* Refresh the desc even if buffer_addrs didn't change
* because each write-back erases this info.
*/
- rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma +
+ bi->page_offset +
+ igb_rx_offset(rx_ring));
rx_desc++;
bi++;
^ permalink raw reply related
* [net-next PATCH RFC 03/26] arch/arc: Add option to skip sync on DMA mapping
From: Alexander Duyck @ 2016-10-24 12:04 UTC (permalink / raw)
To: netdev, linux-kernel, linux-mm
Cc: Vineet Gupta, linux-snps-arc, davem, brouer
In-Reply-To: <20161024115737.16276.71059.stgit@ahduyck-blue-test.jf.intel.com>
This change allows us to pass DMA_ATTR_SKIP_CPU_SYNC which allows us to
avoid invoking cache line invalidation if the driver will just handle it
later via a sync_for_cpu or sync_for_device call.
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: linux-snps-arc@lists.infradead.org
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
arch/arc/mm/dma.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index 20afc65..d0c4b28 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -133,7 +133,8 @@ static dma_addr_t arc_dma_map_page(struct device *dev, struct page *page,
unsigned long attrs)
{
phys_addr_t paddr = page_to_phys(page) + offset;
- _dma_cache_sync(paddr, size, dir);
+ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+ _dma_cache_sync(paddr, size, dir);
return plat_phys_to_dma(dev, paddr);
}
^ permalink raw reply related
* [PATCH 1/3] mwifiex: Allow mwifiex early access to device structure
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
netdev, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain
In-Reply-To: <1477331813-42151-1-git-send-email-rajatja@google.com>
Today all the interface drivers (usb/pcie/sdio) assign the
adapter->dev in the register_dev() callback, although they
have this piece of info well before hand.
This patch makes the device structure available for mwifiex
right at the beginning, so that it can be used for early
initialization if needed.
This is needed for subsequent patches in this patchset that
intend to unify and consolidate some of the code that would
otherwise have to be duplicated among the interface drivers
(sdio, pcie, usb).
Signed-off-by: Rajat Jain <rajatja@google.com>
---
drivers/net/wireless/marvell/mwifiex/main.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/main.h | 3 ++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +---
drivers/net/wireless/marvell/mwifiex/sdio.c | 5 +----
drivers/net/wireless/marvell/mwifiex/usb.c | 3 +--
5 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 2478ccd..dcceab2 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1567,7 +1567,8 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
*/
int
mwifiex_add_card(void *card, struct semaphore *sem,
- struct mwifiex_if_ops *if_ops, u8 iface_type)
+ struct mwifiex_if_ops *if_ops, u8 iface_type,
+ struct device *dev)
{
struct mwifiex_adapter *adapter;
@@ -1579,6 +1580,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_init_sw;
}
+ adapter->dev = dev;
adapter->iface_type = iface_type;
adapter->card_sem = sem;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 26df28f..91218a1 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1411,7 +1411,8 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
+ struct device *);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index f7c84d3..49b5835 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -224,7 +224,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
- MWIFIEX_PCIE);
+ MWIFIEX_PCIE, &pdev->dev);
if (ret) {
pr_err("%s failed\n", __func__);
goto err_free;
@@ -2990,11 +2990,9 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct pci_dev *pdev = card->dev;
/* save adapter pointer in card */
card->adapter = adapter;
- adapter->dev = &pdev->dev;
if (mwifiex_pcie_request_irq(adapter))
return -1;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 807af13..c95f41f 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -206,7 +206,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
- MWIFIEX_SDIO);
+ MWIFIEX_SDIO, &func->dev);
if (ret) {
dev_err(&func->dev, "add card failed\n");
goto err_disable;
@@ -2106,9 +2106,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
return ret;
}
-
- adapter->dev = &func->dev;
-
strcpy(adapter->fw_name, card->firmware);
if (card->fw_dump_enh) {
adapter->mem_type_mapping_tbl = generic_mem_type_map;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 73eb084..f847fff 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -476,7 +476,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, card);
ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
- MWIFIEX_USB);
+ MWIFIEX_USB, &card->udev->dev);
if (ret) {
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
usb_reset_device(udev);
@@ -932,7 +932,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
card->adapter = adapter;
- adapter->dev = &card->udev->dev;
switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
case USB8997_PID_1:
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH 0/3] mwifiex: Make WoWLAN a common feature
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
netdev, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain
I have a Marvell card on the PCIe bus that needs to support
WoWLAN (wake-on-wireless-LAN) feature. This is a feature offered
by the "core" mwifiex card and is not specific to an interface
(pcie/sdio/usb).
Currently the code to parse the WowLAN pin, and activate it
resides only in sdio.c [mostly commit ce4f6f0c353b ("mwifiex: add
platform specific wakeup interrupt support")]. I started by
copying all that code & data structures in pcie.c/pcie.h but then
realized that the we should probably have it common since the
feature is not interface specific.
Further, I noticed that interface driver had no interest in
device trees since there are no properties specific to interfaces.
Currently the only properties needed, are the common ones needed
by the core mwifiex.
This patch set thus introduces mwifiex_probe_of() to parse the
common properties, and then moves the WowLAN specific code to the
common module so that all the interfaces can use it. Essentially
this is a single logical patch that has been split up into
multiple patches only for the reason of simplicity and code
reviews.
This is currently rebased on the top of Linus' tree with the
following 2 patches applied:
https://patchwork.kernel.org/patch/9362275/
https://patchwork.kernel.org/patch/9390225/
Rajat Jain (3):
mwifiex: Allow mwifiex early access to device structure
mwifiex: Introduce mwifiex_probe_of() to parse common properties
mwifiex: Enable WoWLAN for both sdio and pcie
drivers/net/wireless/marvell/mwifiex/main.c | 58 ++++++++++++++++++-
drivers/net/wireless/marvell/mwifiex/main.h | 28 ++++++++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 8 ++-
drivers/net/wireless/marvell/mwifiex/sdio.c | 79 +++-----------------------
drivers/net/wireless/marvell/mwifiex/sdio.h | 8 ---
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 5 +-
drivers/net/wireless/marvell/mwifiex/usb.c | 3 +-
7 files changed, 99 insertions(+), 90 deletions(-)
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply
* [PATCH 3/3] mwifiex: Enable WoWLAN for both sdio and pcie
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1477331813-42151-1-git-send-email-rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Commit ce4f6f0c353b ("mwifiex: add platform specific wakeup interrupt
support") added WoWLAN feature only for sdio. This patch moves that
code to the common module so that all the interface drivers can use
it for free. It enables pcie and sdio for its use currently.
Signed-off-by: Rajat Jain <rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
drivers/net/wireless/marvell/mwifiex/main.c | 41 ++++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.h | 25 ++++++++++
drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +
drivers/net/wireless/marvell/mwifiex/sdio.c | 72 ++---------------------------
drivers/net/wireless/marvell/mwifiex/sdio.h | 8 ----
5 files changed, 73 insertions(+), 75 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index b2f3d96..20c9b77 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1552,14 +1552,55 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static irqreturn_t mwifiex_irq_wakeup_handler(int irq, void *priv)
+{
+ struct mwifiex_adapter *adapter = priv;
+
+ if (adapter->irq_wakeup >= 0) {
+ dev_dbg(adapter->dev, "%s: wake by wifi", __func__);
+ adapter->wake_by_wifi = true;
+ disable_irq_nosync(irq);
+ }
+
+ /* Notify PM core we are wakeup source */
+ pm_wakeup_event(adapter->dev, 0);
+
+ return IRQ_HANDLED;
+}
+
static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
{
+ int ret;
struct device *dev = adapter->dev;
if (!dev->of_node)
return;
adapter->dt_node = dev->of_node;
+ adapter->irq_wakeup = irq_of_parse_and_map(adapter->dt_node, 0);
+ if (!adapter->irq_wakeup) {
+ dev_info(dev, "fail to parse irq_wakeup from device tree\n");
+ return;
+ }
+
+ ret = devm_request_irq(dev, adapter->irq_wakeup,
+ mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
+ "wifi_wake", adapter);
+ if (ret) {
+ dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
+ adapter->irq_wakeup, ret);
+ goto err_exit;
+ }
+
+ disable_irq(adapter->irq_wakeup);
+ if (device_init_wakeup(dev, true)) {
+ dev_err(dev, "fail to init wakeup for mwifiex\n");
+ goto err_exit;
+ }
+ return;
+
+err_exit:
+ adapter->irq_wakeup = 0;
}
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 83e0776..12def94 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1010,6 +1010,10 @@ struct mwifiex_adapter {
bool usb_mc_setup;
struct cfg80211_wowlan_nd_info *nd_info;
struct ieee80211_regdomain *regd;
+
+ /* Wake-on-WLAN (WoWLAN) */
+ int irq_wakeup;
+ bool wake_by_wifi;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1409,6 +1413,27 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
return false;
}
+/* Disable platform specific wakeup interrupt */
+static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter)
+{
+ if (adapter->irq_wakeup >= 0) {
+ disable_irq_wake(adapter->irq_wakeup);
+ if (!adapter->wake_by_wifi)
+ disable_irq(adapter->irq_wakeup);
+ }
+}
+
+/* Enable platform specific wakeup interrupt */
+static inline void mwifiex_enable_wake(struct mwifiex_adapter *adapter)
+{
+ /* Enable platform specific wakeup interrupt */
+ if (adapter->irq_wakeup >= 0) {
+ adapter->wake_by_wifi = false;
+ enable_irq(adapter->irq_wakeup);
+ enable_irq_wake(adapter->irq_wakeup);
+ }
+}
+
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index ea423d5..af93661 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -133,6 +133,7 @@ static int mwifiex_pcie_suspend(struct device *dev)
adapter = card->adapter;
+ mwifiex_enable_wake(adapter);
hs_actived = mwifiex_enable_hs(adapter);
/* Indicate device suspended */
@@ -179,6 +180,7 @@ static int mwifiex_pcie_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_ASYNC_CMD);
+ mwifiex_disable_wake(adapter);
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 558743a..ff5bb45 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -79,67 +79,18 @@ static const struct of_device_id mwifiex_sdio_of_match_table[] = {
{ }
};
-static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
-{
- struct mwifiex_plt_wake_cfg *cfg = priv;
-
- if (cfg->irq_wifi >= 0) {
- pr_info("%s: wake by wifi", __func__);
- cfg->wake_by_wifi = true;
- disable_irq_nosync(irq);
- }
-
- /* Notify PM core we are wakeup source */
- pm_wakeup_event(cfg->dev, 0);
-
- return IRQ_HANDLED;
-}
-
/* This function parse device tree node using mmc subnode devicetree API.
* The device node is saved in card->plt_of_node.
* if the device tree node exist and include interrupts attributes, this
* function will also request platform specific wakeup interrupt.
*/
-static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
+static int mwifiex_sdio_probe_of(struct device *dev)
{
- struct mwifiex_plt_wake_cfg *cfg;
- int ret;
-
if (!of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
dev_err(dev, "required compatible string missing\n");
return -EINVAL;
}
- card->plt_of_node = dev->of_node;
- card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
- GFP_KERNEL);
- cfg = card->plt_wake_cfg;
- if (cfg && card->plt_of_node) {
- cfg->dev = dev;
- cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
- if (!cfg->irq_wifi) {
- dev_dbg(dev,
- "fail to parse irq_wifi from device tree\n");
- } else {
- ret = devm_request_irq(dev, cfg->irq_wifi,
- mwifiex_wake_irq_wifi,
- IRQF_TRIGGER_LOW,
- "wifi_wake", cfg);
- if (ret) {
- dev_dbg(dev,
- "Failed to request irq_wifi %d (%d)\n",
- cfg->irq_wifi, ret);
- card->plt_wake_cfg = NULL;
- return 0;
- }
- disable_irq(cfg->irq_wifi);
- }
- }
-
- ret = device_init_wakeup(dev, true);
- if (ret)
- dev_err(dev, "fail to init wakeup for mwifiex");
-
return 0;
}
@@ -199,11 +150,9 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
/* device tree node parsing and platform specific configuration*/
if (func->dev.of_node) {
- ret = mwifiex_sdio_probe_of(&func->dev, card);
- if (ret) {
- dev_err(&func->dev, "SDIO dt node parse failed\n");
+ ret = mwifiex_sdio_probe_of(&func->dev);
+ if (ret)
goto err_disable;
- }
valid_of_node = true;
}
@@ -269,12 +218,7 @@ static int mwifiex_sdio_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_SYNC_CMD);
- /* Disable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- disable_irq_wake(card->plt_wake_cfg->irq_wifi);
- if (!card->plt_wake_cfg->wake_by_wifi)
- disable_irq(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_disable_wake(adapter);
return 0;
}
@@ -354,13 +298,7 @@ static int mwifiex_sdio_suspend(struct device *dev)
}
adapter = card->adapter;
-
- /* Enable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- card->plt_wake_cfg->wake_by_wifi = false;
- enable_irq(card->plt_wake_cfg->irq_wifi);
- enable_irq_wake(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_enable_wake(adapter);
/* Enable the Host Sleep */
if (!mwifiex_enable_hs(adapter)) {
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index 07cdd23..b9fbc5c 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -154,12 +154,6 @@
a->mpa_rx.start_port = 0; \
} while (0)
-struct mwifiex_plt_wake_cfg {
- struct device *dev;
- int irq_wifi;
- bool wake_by_wifi;
-};
^ permalink raw reply related
* [PATCH 2/3] mwifiex: Introduce mwifiex_probe_of() to parse common properties
From: Rajat Jain @ 2016-10-24 17:56 UTC (permalink / raw)
To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Xinming Hu
Cc: Rajat Jain, Brian Norris, rajatxjain-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1477331813-42151-1-git-send-email-rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Introduce function mwifiex_probe_of() to parse common properties.
Since the interface drivers get to decide whether or not the device
tree node was a valid one (depending on the compatible property),
let the interface drivers pass a flag to indicate whether the device
tree node was a valid one.
The function mwifiex_probe_of()nodetself is currently only a place
holder with the next patch adding content to it.
Signed-off-by: Rajat Jain <rajatja-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
drivers/net/wireless/marvell/mwifiex/main.c | 15 ++++++++++++++-
drivers/net/wireless/marvell/mwifiex/main.h | 2 +-
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/sdio.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 5 +----
drivers/net/wireless/marvell/mwifiex/usb.c | 2 +-
6 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index dcceab2..b2f3d96 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1552,6 +1552,16 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
+{
+ struct device *dev = adapter->dev;
+
+ if (!dev->of_node)
+ return;
+
+ adapter->dt_node = dev->of_node;
+}
+
/*
* This function adds the card.
*
@@ -1568,7 +1578,7 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
int
mwifiex_add_card(void *card, struct semaphore *sem,
struct mwifiex_if_ops *if_ops, u8 iface_type,
- struct device *dev)
+ struct device *dev, bool of_node_valid)
{
struct mwifiex_adapter *adapter;
@@ -1581,6 +1591,9 @@ mwifiex_add_card(void *card, struct semaphore *sem,
}
adapter->dev = dev;
+ if (of_node_valid)
+ mwifiex_probe_of(adapter);
+
adapter->iface_type = iface_type;
adapter->card_sem = sem;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 91218a1..83e0776 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1412,7 +1412,7 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
- struct device *);
+ struct device *, bool);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 49b5835..ea423d5 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -194,6 +194,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct pcie_service_card *card;
+ bool valid_of_node = false;
int ret;
pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
@@ -221,10 +222,11 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
ret = mwifiex_pcie_probe_of(&pdev->dev);
if (ret)
goto err_free;
+ valid_of_node = true;
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
- MWIFIEX_PCIE, &pdev->dev);
+ MWIFIEX_PCIE, &pdev->dev, valid_of_node);
if (ret) {
pr_err("%s failed\n", __func__);
goto err_free;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index c95f41f..558743a 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -156,6 +156,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
{
int ret;
struct sdio_mmc_card *card = NULL;
+ bool valid_of_node = false;
pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
func->vendor, func->device, func->class, func->num);
@@ -203,10 +204,11 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
dev_err(&func->dev, "SDIO dt node parse failed\n");
goto err_disable;
}
+ valid_of_node = true;
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
- MWIFIEX_SDIO, &func->dev);
+ MWIFIEX_SDIO, &func->dev, valid_of_node);
if (ret) {
dev_err(&func->dev, "add card failed\n");
goto err_disable;
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index c8dccf5..73e337e 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2218,10 +2218,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
* The cal-data can be read from device tree and/or
* a configuration file and downloaded to firmware.
*/
- if ((priv->adapter->iface_type == MWIFIEX_SDIO ||
- priv->adapter->iface_type == MWIFIEX_PCIE) &&
- adapter->dev->of_node) {
- adapter->dt_node = adapter->dev->of_node;
+ if (adapter->dt_node) {
if (of_property_read_u32(adapter->dt_node,
"marvell,wakeup-pin",
&data) == 0) {
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index f847fff..11c9629 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -476,7 +476,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, card);
ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
- MWIFIEX_USB, &card->udev->dev);
+ MWIFIEX_USB, &card->udev->dev, false);
if (ret) {
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
usb_reset_device(udev);
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* Re: [PATCH] netns: revert "netns: avoid disabling irq for netns id"
From: Cong Wang @ 2016-10-24 17:52 UTC (permalink / raw)
To: Paul Moore; +Cc: Linux Kernel Network Developers, Elad Raz, Stephen Smalley
In-Reply-To: <CAGH-Kgv6BXrTLPdsLfYnoU8nVeh7fTv89xPZixOS9qqPg8=PXQ@mail.gmail.com>
On Sat, Oct 22, 2016 at 12:29 PM, Paul Moore <pmoore@redhat.com> wrote:
> On Fri, Oct 21, 2016 at 11:38 PM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
>> On Fri, Oct 21, 2016 at 6:49 PM, Paul Moore <pmoore@redhat.com> wrote:
>>> Eventually we should be able to reintroduce this code once we have
>>> rewritten the audit multicast code to queue messages much the same
>>> way we do for unicast messages. A tracking issue for this can be
>>> found below:
>>
>> NAK.
>>
>> 1) This will be forgotten by Paul.
>
> The way things are going right now, this argument is going to devolve
> into a "yes he will"/"no I won't" so I'll just repeat that I've
> created a tracking issue for this so I won't forget (and included a
> link, repeated below, in the commit description) and I think I have a
> reasonable history of following through on things.
>
> * https://github.com/linux-audit/audit-kernel/issues/23
I never doubt you will remember to do the audit part, what you will
forget is the revert to your revert. We will see.
Also, you make git log history much uglier.
>
>> 2) There is already a fix which is considered as a rework by Paul.
>
> Already discussed this in the other thread, I'm not going to go into
> detail here, just a quick summary: the fix provided by Cong Wang
> doubles the message queue's memory consumption and changes some
> fundamentals in how multicast messages are handled. The memory
> issues, while still an objectionable blocker, are easily resolved, but
> moving the netlink multicast send is something I want to make sure is
> tested/baked for a bit (it's 4.10 merge window material as far as I'm
> concerned).
Sounds like you don't have the capacity to get it reviewed and tested
within 5 weeks (assuming -rc7 will be the final RC), as a maintainer.
>
> At this point I think it is worth mentioning that we are in this
> position due to a lack of testing; if Cong Wang had tested his
> original patch with SELinux we might not be dealing with this
> regression now. A more measured approach seems very reasonable.
>
My SELinux is silently disabled because CONFIG_DEFAULT_SECURITY_SELINUX=y
was missing in my kernel config. The change is a cross-subsystem one,
I definitely can't guarantee I can cover all subsystems. This is exactly
why we need -rc1...-rc7, the moment you close the door for -rc2,
the moment you lose the opportunity to get it tested more widely.
I am sure you will revert the revert of revert again for the next merge
window if you continue to work in this style.
>> 3) -rc2 is Paul's personal deadline, not ours.
>
> The current 4.9-rc kernels are broken and cause errors when SELinux is
> enabled, while I understand SELinux is not a priority (or a secondary,
> or tertiary, or N-ary concern) for many on the netdev list, it is
> still an important part of the kernel and this regression needs to be
> treated seriously and corrected soon.
You get it wrong, it is never because SELinux is not important, every
part of Linux kernel is important. You need to realize we as a whole
community don't work in this way, -rc2 is NOT late for a bug fix of any
part of Linux kernel. If you can't review and test a 30-line patch in 5 weeks,
it is very likely your problem.
>
> SELinux/audit has run into interaction issues with the network stack
> before, and we've worked together to sort things out; I'm hopeful
> cooler heads will prevail and we can do the same here.
I am trying my best to help (by providing 3 possible patches), you refused
them because of _your_ -rc2 deadline. Let people judge who is the one
doesn't work together.
I am tired of explaining why we have -rc7 to you.
^ permalink raw reply
* [PATCH v2] net: ipv6: Fix processing of RAs in presence of VRF
From: David Ahern @ 2016-10-24 17:52 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
rt6_add_route_info and rt6_add_dflt_router were updated to pull the FIB
table from the device index, but the corresponding rt6_get_route_info
and rt6_get_dflt_router functions were not leading to the failure to
process RA's:
ICMPv6: RA: ndisc_router_discovery failed to add default route
Fix the 'get' functions by using the table id associated with the
device when applicable.
Also, now that default routes can be added to tables other than the
default table, rt6_purge_dflt_routers needs to be updated as well to
look at all tables. To handle that efficiently, add a flag to the table
denoting if it is has a default route via RA.
Fixes: ca254490c8dfd ("net: Add VRF support to IPv6 stack")
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
v2
- added Fixes to commit message
include/net/ip6_fib.h | 2 ++
net/ipv6/route.c | 68 ++++++++++++++++++++++++++++++++++++---------------
2 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index fb961a576abe..a74e2aa40ef4 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -230,6 +230,8 @@ struct fib6_table {
rwlock_t tb6_lock;
struct fib6_node tb6_root;
struct inet_peer_base tb6_peers;
+ unsigned int flags;
+#define RT6_TABLE_HAS_DFLT_ROUTER BIT(0)
};
#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index bdbc38e8bf29..3ac19eb81a86 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -102,11 +102,13 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex,
+ const struct in6_addr *gwaddr,
+ struct net_device *dev,
unsigned int pref);
static struct rt6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex);
+ const struct in6_addr *gwaddr,
+ struct net_device *dev);
#endif
struct uncached_list {
@@ -803,7 +805,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
rt = rt6_get_dflt_router(gwaddr, dev);
else
rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
- gwaddr, dev->ifindex);
+ gwaddr, dev);
if (rt && !lifetime) {
ip6_del_rt(rt);
@@ -811,8 +813,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
}
if (!rt && lifetime)
- rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
- pref);
+ rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr,
+ dev, pref);
else if (rt)
rt->rt6i_flags = RTF_ROUTEINFO |
(rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
@@ -2325,13 +2327,16 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex)
+ const struct in6_addr *gwaddr,
+ struct net_device *dev)
{
+ u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO;
+ int ifindex = dev->ifindex;
struct fib6_node *fn;
struct rt6_info *rt = NULL;
struct fib6_table *table;
- table = fib6_get_table(net, RT6_TABLE_INFO);
+ table = fib6_get_table(net, tb_id);
if (!table)
return NULL;
@@ -2357,12 +2362,13 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
static struct rt6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex,
+ const struct in6_addr *gwaddr,
+ struct net_device *dev,
unsigned int pref)
{
struct fib6_config cfg = {
.fc_metric = IP6_RT_PRIO_USER,
- .fc_ifindex = ifindex,
+ .fc_ifindex = dev->ifindex,
.fc_dst_len = prefixlen,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
RTF_UP | RTF_PREF(pref),
@@ -2371,7 +2377,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
.fc_nlinfo.nl_net = net,
};
- cfg.fc_table = l3mdev_fib_table_by_index(net, ifindex) ? : RT6_TABLE_INFO;
+ cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO,
cfg.fc_dst = *prefix;
cfg.fc_gateway = *gwaddr;
@@ -2381,16 +2387,17 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
ip6_route_add(&cfg);
- return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
+ return rt6_get_route_info(net, prefix, prefixlen, gwaddr, dev);
}
#endif
struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev)
{
+ u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT;
struct rt6_info *rt;
struct fib6_table *table;
- table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
+ table = fib6_get_table(dev_net(dev), tb_id);
if (!table)
return NULL;
@@ -2424,20 +2431,20 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
cfg.fc_gateway = *gwaddr;
- ip6_route_add(&cfg);
+ if (!ip6_route_add(&cfg)) {
+ struct fib6_table *table;
+
+ table = fib6_get_table(dev_net(dev), cfg.fc_table);
+ if (table)
+ table->flags |= RT6_TABLE_HAS_DFLT_ROUTER;
+ }
return rt6_get_dflt_router(gwaddr, dev);
}
-void rt6_purge_dflt_routers(struct net *net)
+static void __rt6_purge_dflt_routers(struct fib6_table *table)
{
struct rt6_info *rt;
- struct fib6_table *table;
-
- /* NOTE: Keep consistent with rt6_get_dflt_router */
- table = fib6_get_table(net, RT6_TABLE_DFLT);
- if (!table)
- return;
restart:
read_lock_bh(&table->tb6_lock);
@@ -2451,6 +2458,27 @@ void rt6_purge_dflt_routers(struct net *net)
}
}
read_unlock_bh(&table->tb6_lock);
+
+ table->flags &= ~RT6_TABLE_HAS_DFLT_ROUTER;
+}
+
+void rt6_purge_dflt_routers(struct net *net)
+{
+ struct fib6_table *table;
+ struct hlist_head *head;
+ unsigned int h;
+
+ rcu_read_lock();
+
+ for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
+ head = &net->ipv6.fib_table_hash[h];
+ hlist_for_each_entry_rcu(table, head, tb6_hlist) {
+ if (table->flags & RT6_TABLE_HAS_DFLT_ROUTER)
+ __rt6_purge_dflt_routers(table);
+ }
+ }
+
+ rcu_read_unlock();
}
static void rtmsg_to_fib6_config(struct net *net,
--
2.1.4
^ permalink raw reply related
* [PATCH] net: ipv6: Fix processing of RAs in presence of VRF
From: David Ahern @ 2016-10-24 17:39 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
rt6_add_route_info and rt6_add_dflt_router were updated to pull the FIB
table from the device index, but the corresponding rt6_get_route_info
and rt6_get_dflt_router functions were not leading to the failure to
process RA's:
ICMPv6: RA: ndisc_router_discovery failed to add default route
Fix the 'get' functions by using the table id associated with the
device when applicable.
Also, now that default routes can be added to tables other than the
default table, rt6_purge_dflt_routers needs to be updated as well to
look at all tables. To handle that efficiently, add a flag to the table
denoting if it is has a default route via RA.
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
include/net/ip6_fib.h | 2 ++
net/ipv6/route.c | 68 ++++++++++++++++++++++++++++++++++++---------------
2 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index fb961a576abe..a74e2aa40ef4 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -230,6 +230,8 @@ struct fib6_table {
rwlock_t tb6_lock;
struct fib6_node tb6_root;
struct inet_peer_base tb6_peers;
+ unsigned int flags;
+#define RT6_TABLE_HAS_DFLT_ROUTER BIT(0)
};
#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index bdbc38e8bf29..3ac19eb81a86 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -102,11 +102,13 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex,
+ const struct in6_addr *gwaddr,
+ struct net_device *dev,
unsigned int pref);
static struct rt6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex);
+ const struct in6_addr *gwaddr,
+ struct net_device *dev);
#endif
struct uncached_list {
@@ -803,7 +805,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
rt = rt6_get_dflt_router(gwaddr, dev);
else
rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
- gwaddr, dev->ifindex);
+ gwaddr, dev);
if (rt && !lifetime) {
ip6_del_rt(rt);
@@ -811,8 +813,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
}
if (!rt && lifetime)
- rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
- pref);
+ rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr,
+ dev, pref);
else if (rt)
rt->rt6i_flags = RTF_ROUTEINFO |
(rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
@@ -2325,13 +2327,16 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex)
+ const struct in6_addr *gwaddr,
+ struct net_device *dev)
{
+ u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO;
+ int ifindex = dev->ifindex;
struct fib6_node *fn;
struct rt6_info *rt = NULL;
struct fib6_table *table;
- table = fib6_get_table(net, RT6_TABLE_INFO);
+ table = fib6_get_table(net, tb_id);
if (!table)
return NULL;
@@ -2357,12 +2362,13 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
static struct rt6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
- const struct in6_addr *gwaddr, int ifindex,
+ const struct in6_addr *gwaddr,
+ struct net_device *dev,
unsigned int pref)
{
struct fib6_config cfg = {
.fc_metric = IP6_RT_PRIO_USER,
- .fc_ifindex = ifindex,
+ .fc_ifindex = dev->ifindex,
.fc_dst_len = prefixlen,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
RTF_UP | RTF_PREF(pref),
@@ -2371,7 +2377,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
.fc_nlinfo.nl_net = net,
};
- cfg.fc_table = l3mdev_fib_table_by_index(net, ifindex) ? : RT6_TABLE_INFO;
+ cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO,
cfg.fc_dst = *prefix;
cfg.fc_gateway = *gwaddr;
@@ -2381,16 +2387,17 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
ip6_route_add(&cfg);
- return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
+ return rt6_get_route_info(net, prefix, prefixlen, gwaddr, dev);
}
#endif
struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev)
{
+ u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT;
struct rt6_info *rt;
struct fib6_table *table;
- table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
+ table = fib6_get_table(dev_net(dev), tb_id);
if (!table)
return NULL;
@@ -2424,20 +2431,20 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
cfg.fc_gateway = *gwaddr;
- ip6_route_add(&cfg);
+ if (!ip6_route_add(&cfg)) {
+ struct fib6_table *table;
+
+ table = fib6_get_table(dev_net(dev), cfg.fc_table);
+ if (table)
+ table->flags |= RT6_TABLE_HAS_DFLT_ROUTER;
+ }
return rt6_get_dflt_router(gwaddr, dev);
}
-void rt6_purge_dflt_routers(struct net *net)
+static void __rt6_purge_dflt_routers(struct fib6_table *table)
{
struct rt6_info *rt;
- struct fib6_table *table;
-
- /* NOTE: Keep consistent with rt6_get_dflt_router */
- table = fib6_get_table(net, RT6_TABLE_DFLT);
- if (!table)
- return;
restart:
read_lock_bh(&table->tb6_lock);
@@ -2451,6 +2458,27 @@ void rt6_purge_dflt_routers(struct net *net)
}
}
read_unlock_bh(&table->tb6_lock);
+
+ table->flags &= ~RT6_TABLE_HAS_DFLT_ROUTER;
+}
+
+void rt6_purge_dflt_routers(struct net *net)
+{
+ struct fib6_table *table;
+ struct hlist_head *head;
+ unsigned int h;
+
+ rcu_read_lock();
+
+ for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
+ head = &net->ipv6.fib_table_hash[h];
+ hlist_for_each_entry_rcu(table, head, tb6_hlist) {
+ if (table->flags & RT6_TABLE_HAS_DFLT_ROUTER)
+ __rt6_purge_dflt_routers(table);
+ }
+ }
+
+ rcu_read_unlock();
}
static void rtmsg_to_fib6_config(struct net *net,
--
2.1.4
^ permalink raw reply related
* Re: net/can: warning in bcm_connect/proc_register
From: Andrey Konovalov @ 2016-10-24 17:31 UTC (permalink / raw)
To: Cong Wang
Cc: Oliver Hartkopp, Marc Kleine-Budde, David S. Miller, linux-can,
netdev, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko,
Dmitry Vyukov, Eric Dumazet
In-Reply-To: <CAM_iQpUAw6R1P-CQ-YJAYzb-HJXqUKAhJ5rLwp1L-ie3VkprSQ@mail.gmail.com>
Hi Cong,
I'm able to reproduce it by running
https://gist.github.com/xairy/33f2eb6bf807b004e643bae36c3d02d7 in a
tight parallel loop with stress
(https://godoc.org/golang.org/x/tools/cmd/stress):
$ gcc -lpthread tmp.c
$ ./stress ./a.out
The C program was generated from the following syzkaller prog:
mmap(&(0x7f0000000000/0x991000)=nil, (0x991000), 0x3, 0x32,
0xffffffffffffffff, 0x0)
socket(0x1d, 0x80002, 0x2)
r0 = socket(0x1d, 0x80002, 0x2)
connect$nfc_llcp(r0, &(0x7f000000c000)={0x27, 0x100000000, 0x0, 0x5,
0x100000000, 0x1,
"341b3a01b257849ca1d7d1ff9f999d8127b185f88d1d775d59c88a3aa6a8ddacdf2bdc324ea6578a21b85114610186c3817c34b05eaffd2c3f54f57fa81ba0",
0x1ff}, 0x60)
connect$nfc_llcp(r0, &(0x7f0000991000-0x60)={0x27, 0x100000000, 0x1,
0x5, 0xfffffffffffffffd, 0x0,
"341b3a01b257849ca1d7d1ff9f999d8127b185f88d1d775dbec88a3aa6a8ddacdf2bdc324ea6578a21b85114610186c3817c34b05eaffd2c3f54f57fa81ba0",
0x1ff}, 0x60)
Unfortunately I wasn't able to create a simpler reproducer.
Thanks!
On Mon, Oct 24, 2016 at 6:58 PM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Mon, Oct 24, 2016 at 9:21 AM, Andrey Konovalov <andreyknvl@google.com> wrote:
>> Hi,
>>
>> I've got the following error report while running the syzkaller fuzzer:
>>
>> WARNING: CPU: 0 PID: 32451 at fs/proc/generic.c:345 proc_register+0x25e/0x300
>> proc_dir_entry 'can-bcm/249757' already registered
>> Kernel panic - not syncing: panic_on_warn set ...
>
> Looks like we have two problems here:
>
> 1) A check for bo->bcm_proc_read != NULL seems missing
> 2) We need to lock the sock in bcm_connect().
>
> I will work on a patch. Meanwhile, it would help a lot if you could provide
> a reproducer.
>
> Thanks!
^ permalink raw reply
* Re: [PATCH] net: skip genenerating uevents for network namespaces that are exiting
From: Cong Wang @ 2016-10-24 17:17 UTC (permalink / raw)
To: Andrey Vagin
Cc: Linux Kernel Network Developers, Linux Containers,
Eric W . Biederman, LKML, David S. Miller
In-Reply-To: <CANaxB-wvJsts7RUEg1pouD0xMLTQAoVMaWaXZ2wLFT9XE1E1Mw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Sat, Oct 22, 2016 at 12:37 AM, Andrey Vagin <avagin-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> wrote:
> Hi Cong,
>
> On Thu, Oct 20, 2016 at 10:25 PM, Andrey Vagin <avagin-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> wrote:
>> On Thu, Oct 20, 2016 at 8:10 PM, Cong Wang <xiyou.wangcong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> On Thu, Oct 20, 2016 at 7:46 PM, Andrei Vagin <avagin-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> wrote:
>>>> No one can see these events, because a network namespace can not be
>>>> destroyed, if it has sockets.
>>>>
>>>
>>> Are you sure? kobject_uevent_env() seems sending uevents to all
>>> network namespaces.
>>
>> kobj_bcast_filter() checks that a kobject namespace is equal to a
>> socket namespace.
>
> Today I've checked that it really works as I read from the source code.
> I use this tool to read events:
> https://gist.github.com/avagin/430ba431fc2972002df40ebe6a048b36
>
> And I see that events from non-network devices are delivered to all sockets,
> but events from network devices are delivered only to sockets from
> a network namespace where a device is operated.
I missed it, it makes sense now. Please consider adding a comment in
the code or expanding your changelog for reference.
Thanks!
^ permalink raw reply
* Re: [PATCH net 1/1] net sched filters: fix notification of filter delete with proper handle
From: Cong Wang @ 2016-10-24 17:02 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: David Miller, Linux Kernel Network Developers, Daniel Borkmann,
Eric Dumazet
In-Reply-To: <1477236912-5789-1-git-send-email-jhs@emojatatu.com>
On Sun, Oct 23, 2016 at 8:35 AM, Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> From: Jamal Hadi Salim <jhs@mojatatu.com>
>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
We definitely need a serious changelog, even just a short one. ;)
Other than this,
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
We can address the "if (RTM_DELTFILTER != event)" in a separated patch
if needed.
Thanks.
^ permalink raw reply
* Re: net/can: warning in bcm_connect/proc_register
From: Cong Wang @ 2016-10-24 16:58 UTC (permalink / raw)
To: Andrey Konovalov
Cc: Oliver Hartkopp, Marc Kleine-Budde, David S. Miller, linux-can,
netdev, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko,
Dmitry Vyukov, Eric Dumazet
In-Reply-To: <CAAeHK+x6w+Lg1GoCZXdjPtM6n72dpUbF_Bvtg80YNK-Wh8YJ4w@mail.gmail.com>
On Mon, Oct 24, 2016 at 9:21 AM, Andrey Konovalov <andreyknvl@google.com> wrote:
> Hi,
>
> I've got the following error report while running the syzkaller fuzzer:
>
> WARNING: CPU: 0 PID: 32451 at fs/proc/generic.c:345 proc_register+0x25e/0x300
> proc_dir_entry 'can-bcm/249757' already registered
> Kernel panic - not syncing: panic_on_warn set ...
Looks like we have two problems here:
1) A check for bo->bcm_proc_read != NULL seems missing
2) We need to lock the sock in bcm_connect().
I will work on a patch. Meanwhile, it would help a lot if you could provide
a reproducer.
Thanks!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox