* [PATCH net 1/2] lwtunnel: Fix oops on state free after encap module unload
From: Robert Shearman @ 2017-01-18 15:32 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert, Roopa Prabhu, Robert Shearman
In-Reply-To: <1484753523-26230-1-git-send-email-rshearma@brocade.com>
When attempting to free lwtunnel state after the module for the encap
has been unloaded an oops occurs:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
IP: lwtstate_free+0x18/0x40
[..]
task: ffff88003e372380 task.stack: ffffc900001fc000
RIP: 0010:lwtstate_free+0x18/0x40
RSP: 0018:ffff88003fd83e88 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff88002bbb3380 RCX: ffff88000c91a300
[..]
Call Trace:
<IRQ>
free_fib_info_rcu+0x195/0x1a0
? rt_fibinfo_free+0x50/0x50
rcu_process_callbacks+0x2d3/0x850
? rcu_process_callbacks+0x296/0x850
__do_softirq+0xe4/0x4cb
irq_exit+0xb0/0xc0
smp_apic_timer_interrupt+0x3d/0x50
apic_timer_interrupt+0x93/0xa0
[..]
Code: e8 6e c6 fc ff 89 d8 5b 5d c3 bb de ff ff ff eb f4 66 90 66 66 66 66 90 55 48 89 e5 53 0f b7 07 48 89 fb 48 8b 04 c5 00 81 d5 81 <48> 8b 40 08 48 85 c0 74 13 ff d0 48 8d 7b 20 be 20 00 00 00 e8
The problem is that we don't check for NULL ops in
lwtstate_free. Adding the check fixes the immediate problem but will
then won't properly clean up for ops that implement the
->destroy_state function if the implementing module has been unloaded,
resulting in memory leaks or other problems. So in addition, refcount
the module when the ops implements ->destroy_state so it can't be
unloaded while there is still state around.
Fixes: 1104d9ba443a ("lwtunnel: Add destroy state operation")
Signed-off-by: Robert Shearman <rshearma@brocade.com>
---
include/net/lwtunnel.h | 2 ++
net/core/lwtunnel.c | 11 +++++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
index d4c1c75b8862..2b9993f33198 100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@ -44,6 +44,8 @@ struct lwtunnel_encap_ops {
int (*get_encap_size)(struct lwtunnel_state *lwtstate);
int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b);
int (*xmit)(struct sk_buff *skb);
+
+ struct module *owner;
};
#ifdef CONFIG_LWTUNNEL
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index a5d4e866ce88..3dc3cc3b38ec 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -126,8 +126,14 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
}
}
#endif
- if (likely(ops && ops->build_state))
+ /* take module reference if destroy_state is in use */
+ if (unlikely(ops && ops->destroy_state && !try_module_get(ops->owner)))
+ ops = NULL;
+ if (likely(ops && ops->build_state)) {
ret = ops->build_state(dev, encap, family, cfg, lws);
+ if (ret && ops->destroy_state)
+ module_put(ops->owner);
+ }
rcu_read_unlock();
return ret;
@@ -138,9 +144,10 @@ void lwtstate_free(struct lwtunnel_state *lws)
{
const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];
- if (ops->destroy_state) {
+ if (ops && ops->destroy_state) {
ops->destroy_state(lws);
kfree_rcu(lws, rcu);
+ module_put(ops->owner);
} else {
kfree(lws);
}
--
2.1.4
^ permalink raw reply related
* [PATCH net 0/2] net: Fix oops on state free after lwt module unload
From: Robert Shearman @ 2017-01-18 15:32 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert, Roopa Prabhu, Robert Shearman
This patchset fixes an oops in lwtstate_free and a memory leak that
would otherwise be exposed by ensuring that references are taken on
modules that need to stay around to clean up lwt state. To faciliate
this all ops that implement destroy_state and that can be configured
to build as a module are changed specify the owner module in the
ops. The intersection of those two sets is just ila at the moment.
Robert Shearman (2):
lwtunnel: Fix oops on state free after encap module unload
ila: Fix memory leak of lwt dst cache on module unload
include/net/lwtunnel.h | 2 ++
net/core/lwtunnel.c | 11 +++++++++--
net/ipv6/ila/ila_lwt.c | 1 +
3 files changed, 12 insertions(+), 2 deletions(-)
--
2.1.4
^ permalink raw reply
* xennet_start_xmit assumptions
From: Sowmini Varadhan @ 2017-01-18 15:31 UTC (permalink / raw)
To: netdev, xen-devel
As I was playing around with pf_packet, I accidentally wrote
a buggy application program that bzero'ed the msghdr, then set
up the msg_name, msg_namelen correctly, and then did a sendmsg
on the pf_packet/SOCK_RAW fd.
This causes packet_snd to set up an skb with a lot of issues,
e.g., skb->len = 0, skb_headlen(skb) is 0, etc. I think we can/should
drop the packet in packet_snd if the skb->len is 0, but there
may be other driver bugs going on:
Turns out that ixgbe and sunvnet handle this problematic
skb correctly (they drop it and system remains stable),
but it creates a panic in xen_netfront (xennet_start_xmit()
hits a null pointer deref when xennet_make_first_txreq() returns
NULL)
I'm new to the xen driver code, so I'm hoping that
the experts can comment here: reading the code in xennet_start_xmit,
it seems like it mandatorily requires the skb_headlen() to be
non-zero in order to create the first_tx? That may not always be
true, how does the code recover for purely non-linear skbs?
--Sowmini
^ permalink raw reply
* Re: [PATCH net-next] mlx4: support __GFP_MEMALLOC for rx
From: Eric Dumazet @ 2017-01-18 15:24 UTC (permalink / raw)
To: Konstantin Khlebnikov
Cc: David Miller, netdev, Tariq Toukan, linux-mm@kvack.org
In-Reply-To: <ed9a6b2a-428e-ac78-bba8-742f5e7c1eed@yandex-team.ru>
On Wed, 2017-01-18 at 18:11 +0300, Konstantin Khlebnikov wrote:
> On 18.01.2017 17:23, Eric Dumazet wrote:
> >
> > Take a look at sk_filter_trim_cap(), where the RX packets received on a
> > socket which does not have SOCK_MEMALLOC is dropped.
> >
> > /*
> > * If the skb was allocated from pfmemalloc reserves, only
> > * allow SOCK_MEMALLOC sockets to use it as this socket is
> > * helping free memory
> > */
> > if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
> > return -ENOMEM;
>
> I suppose this happens in BH context right after receiving packet?
>
> Potentially any ACK could free memory in TCP send queue,
> so using reserves here makes sense.
Yes, but only sockets with SOCK_MEMALLOC have this contract with the mm
layer.
For 'other' sockets, one possible trick would be that if only the page
fragment attached to skb had the pfmemalloc bit, and not the sk_buff
itself, we could attempt a skb_condense() operation [1], but it is not
really easy to properly recompute skb->pfmemalloc.
Pure TCP ACK packets can usually be trimmed by skb_condense().
Since they have no payload, we have a guarantee they wont sit in a queue
and hold memory.
--
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
* [RFC] RESEND - rdmatool - tool for RDMA users
From: Ariel Almog @ 2017-01-18 15:19 UTC (permalink / raw)
To: leon, linux-rdma, netdev
sorry for resending.
General
*******
As of today, there is no single, simple, tool that allows monitoring
and configuration of RDMA stack.
For netdev stack there are few standard tools, such as ethtool and
iproute2. There is a need to add a matching tool which will allow
control and query of RDMA subsystem.
rdmatool will provide standard, provider agnostic, user interface.
RDMA user can use this interface to
* Query RDMA device capabilities
* Query RDMA device status and current open resources
* Fetching RDMA statistics
* Configure RDMA device
The rdmatool will have the ability to control RDMA stack which
includes the ib_device and RDMA protocol params.
It is a good point to highlight the similarity to ethtool. It manages
net_device, while rdmatool will manage RDMA stack.
As a proposal, it is appealing to have a similar design to ethtool for
rdmatool too. As ethtool, it should contain user space part, kernel
handler and vendor specific handler(s).
Another tool which allows similar functionality is iproute2. Iproute2
allows user space tools to configure and query transport, network and
link layer. The advantages of using iproute2 is the reuse of existing
tool and familiar interface in addition to the wide spreading of this tool.
As start point of the discussion, we would like to propose two
implementation options for the rdmatool:
(1) Build a tool using ABI interface. This will be a RDMA tool
which will be distributed as part of RDMA package
(2) Enhancing iproute2 to include rdmatool functionality
Our opinion is that the new ABI interface provides vast functionality and
it will be a waste to use other interface for the same functionality.
Each of the proposed implementation above have their advantages, and we
would like to hear your opinion regarding this direction.
I’m posting this RFC in both netdev and linux-rdma communities in
order to get feedback on this topic.
General Description
*******************
The rdmatool will be combined from the following components:
* user space’s rdmatool - will be referred from now on as rdmatool-u.
* kernel’s rdmatool - will be referred from now on as rdmatool-k. This part
is in kernel, running under ibcore context
* ib_device’s rdma_ops - rdmatool-p is written by the provider.
In case the provider doesn't provide rdma_ops code, a generic code will
be used to provide the matching interface.
.------------------|
| rdmatool-u |
|------------------|
U |
ABI
K |
.------------------|
| rdmatool-k |
|------------------|
|
rdmatool_ops
|
.---------------------------|
| generic rdma_ops |
|---------------------------|--|
| ib_device’s rdma_ops |--|
|--|------------------------| |--|
|--|------------------------| |
|---------------------------|
The protocol on top of the ABI interface handles the transaction of
information on both directions (rdmatool-u to rdmatool-k and vice versa).
The transaction protocol shall contain the following information:
* Command – the requested operation by rdmatool-u
* ib_device – the device to handle; a dedicated value will indicate a stack
layer transactions
* Ancillary information according to the command
Later on, after we will close direction and design concerns, we will start
defining the actual structure to be used.
Flexibility
***********
Some of the commands allow passing both standard and
vendor specific information.
In order to allow easy enhancement of the tool, an Matan's ABI [1]
mechanism can be used to pass the vendor specific information.
As examples:
(1) Statistics ops will return the standard counters. In addition, it can
report on extra counters. The rdmatool-u will present the addition
statistics as is.
(2) For configuration, where rdmatool-u finds undefined information at the
end of the command line, it will pass it as is to the rdmatool-k which
will pass it to the ops handler where it can be handled or ignored.
Persistence
***********
Another target that we would like to achieve is easy configuration.
rdmatool-u will provide an export mechanism mto store and restore configuration
The configuration file will be human readable and will be parsed by the
various tools (systemd, udev, rdmatool-u, etc.).
Functionality
*************
The rdmatool will provide a platform which can grow as needed. The
initial functionality might include:
* help – man page
* version – version number
* statistics – RDMA statistics – such as port and QP statistics
To allow easy reading of statistics, we offer to use a filter functionality,
allowing reading of statistics families, such as link layer, error
counters, etc.
* protocol – RoCE/iWARP/InfiniBand related configuration, such as RDMA
congestion configuration and statistics
* query – RDMA objects (qp, cq, srq, ..) information such as owner,
status, type
* debug – an interface to allow read and write from user space to the
provider RDMA driver, exposing debug information
We would like to get the community feedback regarding which solution shall be
used: a standalone tool in RDMA package (ABI) or adding functionality to
iproute2 as extension?
Reference
[1] [RFC ABI V6 00/14] SG-based RDMA ABI Proposal -
https://www.spinics.net/lists/linux-rdma/msg43960.html
Thanks for feedback.
Ariel and Leon
^ permalink raw reply
* Re: [PATCH] virtio: don't set VIRTIO_NET_HDR_F_DATA_VALID on xmit
From: Michael S. Tsirkin @ 2017-01-18 15:18 UTC (permalink / raw)
To: Jason Wang; +Cc: Rolf Neugebauer, netdev, davem, rppt
In-Reply-To: <34158479-8d4a-3761-a02e-66c474aca53e@redhat.com>
On Wed, Jan 18, 2017 at 11:54:21AM +0800, Jason Wang wrote:
>
>
> On 2017年01月18日 02:27, Michael S. Tsirkin wrote:
> > On Tue, Jan 17, 2017 at 06:13:51PM +0000, Rolf Neugebauer wrote:
> > > This patch part reverts fd2a0437dc33 and e858fae2b0b8 which introduced a
> > > subtle change in how the virtio_net flags are derived from the SKBs
> > > ip_summed field.
> > >
> > > With the above commits, the flags are set to VIRTIO_NET_HDR_F_DATA_VALID
> > > when ip_summed == CHECKSUM_UNNECESSARY, thus treating it differently to
> > > ip_summed == CHECKSUM_NONE, which should be the same.
> > >
> > > Further, the virtio spec 1.0 / CS04 explicitly says that
> > > VIRTIO_NET_HDR_F_DATA_VALID must not be set by the driver.
> > >
> > > Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
> > Fixes: fd2a0437dc33 ("virtio_net: introduce virtio_net_hdr_{from,to}_skb")
> > Fixes: e858fae2b0b8 (" virtio_net: use common code for virtio_net_hdr and skb GSO conversion")
> > Acked-by: Michael S. Tsirkin <mst@redhat.com>
> >
> > Should be backported into stable as well.
>
> Looks like a side effect is that we will never see this on receive path?
I thought receive path is using virtio_net_hdr_to_skb - isn't it?
> We
> probably need a hint for virtio_net_hdr_from_skb().
>
> Thanks
>
> >
> >
> > > ---
> > > include/linux/virtio_net.h | 2 --
> > > 1 file changed, 2 deletions(-)
> > >
> > > diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
> > > index 66204007d7ac..56436472ccc7 100644
> > > --- a/include/linux/virtio_net.h
> > > +++ b/include/linux/virtio_net.h
> > > @@ -91,8 +91,6 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
> > > skb_checksum_start_offset(skb));
> > > hdr->csum_offset = __cpu_to_virtio16(little_endian,
> > > skb->csum_offset);
> > > - } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
> > > - hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
> > > } /* else everything is zero */
> > > return 0;
> > > --
> > > 2.11.0
^ permalink raw reply
* Re: [net PATCH v5 6/6] virtio_net: XDP support for adjust_head
From: Michael S. Tsirkin @ 2017-01-18 15:15 UTC (permalink / raw)
To: John Fastabend
Cc: jasowang, john.r.fastabend, netdev, alexei.starovoitov, daniel
In-Reply-To: <20170117222259.20280.24625.stgit@john-Precision-Tower-5810>
On Tue, Jan 17, 2017 at 02:22:59PM -0800, John Fastabend wrote:
> Add support for XDP adjust head by allocating a 256B header region
> that XDP programs can grow into. This is only enabled when a XDP
> program is loaded.
>
> In order to ensure that we do not have to unwind queue headroom push
> queue setup below bpf_prog_add. It reads better to do a prog ref
> unwind vs another queue setup call.
>
> At the moment this code must do a full reset to ensure old buffers
> without headroom on program add or with headroom on program removal
> are not used incorrectly in the datapath. Ideally we would only
> have to disable/enable the RX queues being updated but there is no
> API to do this at the moment in virtio so use the big hammer. In
> practice it is likely not that big of a problem as this will only
> happen when XDP is enabled/disabled changing programs does not
> require the reset. There is some risk that the driver may either
> have an allocation failure or for some reason fail to correctly
> negotiate with the underlying backend in this case the driver will
> be left uninitialized. I have not seen this ever happen on my test
> systems and for what its worth this same failure case can occur
> from probe and other contexts in virtio framework.
>
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
I've been thinking about it - can't we drop
old buffers without the head room which were posted before
xdp attached?
Avoiding the reset would be much nicer.
Thoughts?
> ---
> drivers/net/virtio_net.c | 149 +++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 125 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 62dbf4b..3b129b4 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -41,6 +41,9 @@
> #define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
> #define GOOD_COPY_LEN 128
>
> +/* Amount of XDP headroom to prepend to packets for use by xdp_adjust_head */
> +#define VIRTIO_XDP_HEADROOM 256
> +
> /* RX packet size EWMA. The average packet size is used to determine the packet
> * buffer size when refilling RX rings. As the entire RX ring may be refilled
> * at once, the weight is chosen so that the EWMA will be insensitive to short-
> @@ -359,6 +362,7 @@ static void virtnet_xdp_xmit(struct virtnet_info *vi,
> }
>
> if (vi->mergeable_rx_bufs) {
> + xdp->data -= sizeof(struct virtio_net_hdr_mrg_rxbuf);
> /* Zero header and leave csum up to XDP layers */
> hdr = xdp->data;
> memset(hdr, 0, vi->hdr_len);
> @@ -375,7 +379,9 @@ static void virtnet_xdp_xmit(struct virtnet_info *vi,
> num_sg = 2;
> sg_init_table(sq->sg, 2);
> sg_set_buf(sq->sg, hdr, vi->hdr_len);
> - skb_to_sgvec(skb, sq->sg + 1, 0, skb->len);
> + skb_to_sgvec(skb, sq->sg + 1,
> + xdp->data - xdp->data_hard_start,
> + xdp->data_end - xdp->data);
> }
> err = virtqueue_add_outbuf(sq->vq, sq->sg, num_sg,
> data, GFP_ATOMIC);
> @@ -401,7 +407,6 @@ static struct sk_buff *receive_small(struct net_device *dev,
> struct bpf_prog *xdp_prog;
>
> len -= vi->hdr_len;
> - skb_trim(skb, len);
>
> rcu_read_lock();
> xdp_prog = rcu_dereference(rq->xdp_prog);
> @@ -413,11 +418,15 @@ static struct sk_buff *receive_small(struct net_device *dev,
> if (unlikely(hdr->hdr.gso_type || hdr->hdr.flags))
> goto err_xdp;
>
> - xdp.data = skb->data;
> + xdp.data_hard_start = skb->data;
> + xdp.data = skb->data + VIRTIO_XDP_HEADROOM;
> xdp.data_end = xdp.data + len;
> act = bpf_prog_run_xdp(xdp_prog, &xdp);
> switch (act) {
> case XDP_PASS:
> + /* Recalculate length in case bpf program changed it */
> + __skb_pull(skb, xdp.data - xdp.data_hard_start);
> + len = xdp.data_end - xdp.data;
> break;
> case XDP_TX:
> virtnet_xdp_xmit(vi, rq, &xdp, skb);
> @@ -432,6 +441,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
> }
> rcu_read_unlock();
>
> + skb_trim(skb, len);
> return skb;
>
> err_xdp:
> @@ -480,7 +490,7 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
> unsigned int *len)
> {
> struct page *page = alloc_page(GFP_ATOMIC);
> - unsigned int page_off = 0;
> + unsigned int page_off = VIRTIO_XDP_HEADROOM;
>
> if (!page)
> return NULL;
> @@ -516,7 +526,8 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
> put_page(p);
> }
>
> - *len = page_off;
> + /* Headroom does not contribute to packet length */
> + *len = page_off - VIRTIO_XDP_HEADROOM;
> return page;
> err_buf:
> __free_pages(page, 0);
> @@ -555,7 +566,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
> page, offset, &len);
> if (!xdp_page)
> goto err_xdp;
> - offset = 0;
> + offset = VIRTIO_XDP_HEADROOM;
> } else {
> xdp_page = page;
> }
> @@ -568,18 +579,29 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
> if (unlikely(hdr->hdr.gso_type))
> goto err_xdp;
>
> + /* Allow consuming headroom but reserve enough space to push
> + * the descriptor on if we get an XDP_TX return code.
> + */
> data = page_address(xdp_page) + offset;
> + xdp.data_hard_start = data - VIRTIO_XDP_HEADROOM + vi->hdr_len;
> xdp.data = data + vi->hdr_len;
> xdp.data_end = xdp.data + (len - vi->hdr_len);
> act = bpf_prog_run_xdp(xdp_prog, &xdp);
> switch (act) {
> case XDP_PASS:
> + /* recalculate offset to account for any header
> + * adjustments. Note other cases do not build an
> + * skb and avoid using offset
> + */
> + offset = xdp.data -
> + page_address(xdp_page) - vi->hdr_len;
> +
> /* We can only create skb based on xdp_page. */
> if (unlikely(xdp_page != page)) {
> rcu_read_unlock();
> put_page(page);
> head_skb = page_to_skb(vi, rq, xdp_page,
> - 0, len, PAGE_SIZE);
> + offset, len, PAGE_SIZE);
> ewma_pkt_len_add(&rq->mrg_avg_pkt_len, len);
> return head_skb;
> }
> @@ -744,23 +766,30 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
> dev_kfree_skb(skb);
> }
>
> +static unsigned int virtnet_get_headroom(struct virtnet_info *vi)
> +{
> + return vi->xdp_queue_pairs ? VIRTIO_XDP_HEADROOM : 0;
> +}
> +
> static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq,
> gfp_t gfp)
> {
> + int headroom = GOOD_PACKET_LEN + virtnet_get_headroom(vi);
> + unsigned int xdp_headroom = virtnet_get_headroom(vi);
> struct sk_buff *skb;
> struct virtio_net_hdr_mrg_rxbuf *hdr;
> int err;
>
> - skb = __netdev_alloc_skb_ip_align(vi->dev, GOOD_PACKET_LEN, gfp);
> + skb = __netdev_alloc_skb_ip_align(vi->dev, headroom, gfp);
> if (unlikely(!skb))
> return -ENOMEM;
>
> - skb_put(skb, GOOD_PACKET_LEN);
> + skb_put(skb, headroom);
>
> hdr = skb_vnet_hdr(skb);
> sg_init_table(rq->sg, 2);
> sg_set_buf(rq->sg, hdr, vi->hdr_len);
> - skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
> + skb_to_sgvec(skb, rq->sg + 1, xdp_headroom, skb->len - xdp_headroom);
>
> err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp);
> if (err < 0)
> @@ -828,24 +857,27 @@ static unsigned int get_mergeable_buf_len(struct ewma_pkt_len *avg_pkt_len)
> return ALIGN(len, MERGEABLE_BUFFER_ALIGN);
> }
>
> -static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp)
> +static int add_recvbuf_mergeable(struct virtnet_info *vi,
> + struct receive_queue *rq, gfp_t gfp)
> {
> struct page_frag *alloc_frag = &rq->alloc_frag;
> + unsigned int headroom = virtnet_get_headroom(vi);
> char *buf;
> unsigned long ctx;
> int err;
> unsigned int len, hole;
>
> len = get_mergeable_buf_len(&rq->mrg_avg_pkt_len);
> - if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp)))
> + if (unlikely(!skb_page_frag_refill(len + headroom, alloc_frag, gfp)))
> return -ENOMEM;
>
> buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset;
> + buf += headroom; /* advance address leaving hole at front of pkt */
> ctx = mergeable_buf_to_ctx(buf, len);
> get_page(alloc_frag->page);
> - alloc_frag->offset += len;
> + alloc_frag->offset += len + headroom;
> hole = alloc_frag->size - alloc_frag->offset;
> - if (hole < len) {
> + if (hole < len + headroom) {
> /* To avoid internal fragmentation, if there is very likely not
> * enough space for another buffer, add the remaining space to
> * the current buffer. This extra space is not included in
> @@ -879,7 +911,7 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
> gfp |= __GFP_COLD;
> do {
> if (vi->mergeable_rx_bufs)
> - err = add_recvbuf_mergeable(rq, gfp);
> + err = add_recvbuf_mergeable(vi, rq, gfp);
> else if (vi->big_packets)
> err = add_recvbuf_big(vi, rq, gfp);
> else
> @@ -1702,6 +1734,7 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
> }
>
> static int init_vqs(struct virtnet_info *vi);
> +static void _remove_vq_common(struct virtnet_info *vi);
>
> static int virtnet_restore_up(struct virtio_device *vdev)
> {
> @@ -1727,12 +1760,45 @@ static int virtnet_restore_up(struct virtio_device *vdev)
> return err;
> }
>
> +static int virtnet_reset(struct virtnet_info *vi)
> +{
> + struct virtio_device *dev = vi->vdev;
> + int ret;
> +
> + virtio_config_disable(dev);
> + dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
> + virtnet_freeze_down(dev);
> + _remove_vq_common(vi);
> +
> + dev->config->reset(dev);
> + virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> +
> + ret = virtio_finalize_features(dev);
> + if (ret)
> + goto err;
> +
> + ret = virtnet_restore_up(dev);
> + if (ret)
> + goto err;
> + ret = _virtnet_set_queues(vi, vi->curr_queue_pairs);
> + if (ret)
> + goto err;
> +
> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> + virtio_config_enable(dev);
> + return 0;
> +err:
> + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
> + return ret;
> +}
> +
> static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog)
> {
> unsigned long int max_sz = PAGE_SIZE - sizeof(struct padded_vnet_hdr);
> struct virtnet_info *vi = netdev_priv(dev);
> struct bpf_prog *old_prog;
> - u16 xdp_qp = 0, curr_qp;
> + u16 oxdp_qp, xdp_qp = 0, curr_qp;
> int i, err;
>
> if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
> @@ -1764,21 +1830,32 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog)
> return -ENOMEM;
> }
>
> + if (prog) {
> + prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
> + if (IS_ERR(prog))
> + return PTR_ERR(prog);
> + }
> +
> err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
> if (err) {
> dev_warn(&dev->dev, "XDP Device queue allocation failure.\n");
> - return err;
> + goto virtio_queue_err;
> }
>
> - if (prog) {
> - prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
> - if (IS_ERR(prog)) {
> - _virtnet_set_queues(vi, curr_qp);
> - return PTR_ERR(prog);
> - }
> + oxdp_qp = vi->xdp_queue_pairs;
> +
> + /* Changing the headroom in buffers is a disruptive operation because
> + * existing buffers must be flushed and reallocated. This will happen
> + * when a xdp program is initially added or xdp is disabled by removing
> + * the xdp program resulting in number of XDP queues changing.
> + */
> + if (vi->xdp_queue_pairs != xdp_qp) {
> + vi->xdp_queue_pairs = xdp_qp;
> + err = virtnet_reset(vi);
> + if (err)
> + goto virtio_reset_err;
> }
>
> - vi->xdp_queue_pairs = xdp_qp;
> netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
>
> for (i = 0; i < vi->max_queue_pairs; i++) {
> @@ -1789,6 +1866,21 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog)
> }
>
> return 0;
> +
> +virtio_reset_err:
> + /* On reset error do our best to unwind XDP changes inflight and return
> + * error up to user space for resolution. The underlying reset hung on
> + * us so not much we can do here.
> + */
> + dev_warn(&dev->dev, "XDP reset failure and queues unstable\n");
> + vi->xdp_queue_pairs = oxdp_qp;
> +virtio_queue_err:
> + /* On queue set error we can unwind bpf ref count and user space can
> + * retry this is most likely an allocation failure.
> + */
> + if (prog)
> + bpf_prog_sub(prog, vi->max_queue_pairs - 1);
> + return err;
> }
>
> static bool virtnet_xdp_query(struct net_device *dev)
> @@ -2382,6 +2474,15 @@ static int virtnet_probe(struct virtio_device *vdev)
> return err;
> }
>
> +static void _remove_vq_common(struct virtnet_info *vi)
> +{
> + vi->vdev->config->reset(vi->vdev);
> + free_unused_bufs(vi);
> + _free_receive_bufs(vi);
> + free_receive_page_frags(vi);
> + virtnet_del_vqs(vi);
> +}
> +
> static void remove_vq_common(struct virtnet_info *vi)
> {
> vi->vdev->config->reset(vi->vdev);
^ permalink raw reply
* [RFC] net: ipv6: return the first matched rt6_info for multicast packets in find_rr_leaf()
From: Rajasekar Kumar @ 2017-01-18 15:13 UTC (permalink / raw)
To: davem, kuznet, jmorris, yoshfuji, kaber, netdev, linux-kernel
There is a performance issue when large number of interfaces are
enabled with VRRP protocol in 2 router nodes which are connected
to each other. When VRRP hello is received (which is multicast
packet with DIP: ff02::18), a rt6_info node is added to fib6_node
of address ff02::18. This happens for each interface on which
VRRP is enabled. For 2000 interfaces with VRRP enabled, 2000
rt6_info nodes are added to the same fib6_node. As of today,
find_rr_leaf() goes further to find better match, even after first
successful match based on interface key. In this case, it walks
2000 nodes for every incoming packet/outgoing packet, which is
expensive and not needed. rt6_info match based on supplied
interface match should be sufficient. The first match occurs
when there is interface match, and after that there can not be
another match for multicast packets. So, first match should be
returned for multicast packets.
find_rr_leaf() tries to find best available gateway, mainly based on
interface match and gateway's reachablity info.When this is required
for unicast packets, multicast packets do not need either gateway's
reachability status or gateway's Layer2 address as it is derived
from Destination IP (group address). rt6_info match based on supplied
interface match should be sufficient.
This fix helps in scenario wherein multicast packets arrive in some
interfaces frequently than other interfaces. rt6_info is added to
beginning of list for former cases. Verified this case.
Signed-off-by: Rajasekar Kumar <sekraj@gmail.com>
---
Changes from first mail:
- Including netdev@vger.kernel.org, linux-kernel@vger.kernel.org to get review inputs/help
- Changed the subject prefix to RFC from PATCH
- Amended commit message to include test scenario
net/ipv6/route.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8417c41..609b543 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -703,6 +703,8 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
}
match = find_match(rt, oif, strict, &mpri, match, do_rr);
+ if (match && ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
+ return match;
}
for (rt = fn->leaf; rt && rt != rr_head; rt = rt->dst.rt6_next) {
@@ -712,13 +714,18 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
}
match = find_match(rt, oif, strict, &mpri, match, do_rr);
+ if (match && ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
+ return match;
}
if (match || !cont)
return match;
- for (rt = cont; rt; rt = rt->dst.rt6_next)
+ for (rt = cont; rt; rt = rt->dst.rt6_next) {
match = find_match(rt, oif, strict, &mpri, match, do_rr);
+ if (match && ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
+ return match;
+ }
return match;
}
--
2.9.3
^ permalink raw reply related
* Re: [PATCH net-next] mlx4: support __GFP_MEMALLOC for rx
From: Konstantin Khlebnikov @ 2017-01-18 15:11 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, Tariq Toukan, linux-mm@kvack.org
In-Reply-To: <1484749428.13165.100.camel@edumazet-glaptop3.roam.corp.google.com>
On 18.01.2017 17:23, Eric Dumazet wrote:
> On Wed, 2017-01-18 at 12:31 +0300, Konstantin Khlebnikov wrote:
>> On 18.01.2017 07:14, Eric Dumazet wrote:
>>> From: Eric Dumazet <edumazet@google.com>
>>>
>>> Commit 04aeb56a1732 ("net/mlx4_en: allocate non 0-order pages for RX
>>> ring with __GFP_NOMEMALLOC") added code that appears to be not needed at
>>> that time, since mlx4 never used __GFP_MEMALLOC allocations anyway.
>>>
>>> As using memory reserves is a must in some situations (swap over NFS or
>>> iSCSI), this patch adds this flag.
>>
>> AFAIK __GFP_MEMALLOC is used for TX, not for RX: for allocations which
>> are required by memory reclaimer to free some pages.
>>
>> Allocation RX buffers with __GFP_MEMALLOC is a straight way to
>> depleting all reserves by flood from network.
>
> You are mistaken.
>
> How do you think a TCP flow can make progress sending data if no ACK
> packet can go back in RX ?
Well. Ok. I mistaken.
>
> Take a look at sk_filter_trim_cap(), where the RX packets received on a
> socket which does not have SOCK_MEMALLOC is dropped.
>
> /*
> * If the skb was allocated from pfmemalloc reserves, only
> * allow SOCK_MEMALLOC sockets to use it as this socket is
> * helping free memory
> */
> if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
> return -ENOMEM;
I suppose this happens in BH context right after receiving packet?
Potentially any ACK could free memory in TCP send queue,
so using reserves here makes sense.
>
> Also take a look at __dev_alloc_pages()
>
> static inline struct page *__dev_alloc_pages(gfp_t gfp_mask,
> unsigned int order)
> {
> /* This piece of code contains several assumptions.
> * 1. This is for device Rx, therefor a cold page is preferred.
> * 2. The expectation is the user wants a compound page.
> * 3. If requesting a order 0 page it will not be compound
> * due to the check to see if order has a value in prep_new_page
> * 4. __GFP_MEMALLOC is ignored if __GFP_NOMEMALLOC is set due to
> * code in gfp_to_alloc_flags that should be enforcing this.
> */
> gfp_mask |= __GFP_COLD | __GFP_COMP | __GFP_MEMALLOC;
>
> return alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
> }
>
>
> So __GFP_MEMALLOC in RX is absolutely supported.
>
> But drivers have to opt-in, either using __dev_alloc_pages() or
> dev_alloc_pages, or explicitely ORing __GFP_MEMALLOC when using
> alloc_page[s]()
>
>
>
--
Konstantin
--
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: [PATCH 2/2] at803x: double check SGMII side autoneg
From: Timur Tabi @ 2017-01-18 15:02 UTC (permalink / raw)
To: Zefir Kurtisi, netdev; +Cc: andrew, f.fainelli
In-Reply-To: <b12e913d-874b-734a-4401-88315b8459dc@neratec.com>
On 01/18/2017 07:53 AM, Zefir Kurtisi wrote:
> No, not necessarily. The SGMII link default configuration is set such that you do
> not have to bother at all.
Does the SGMII link need to make the speed and duplex of the external link?
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c#n50
Here is where I can configure the SGMII link to match whatever phydev says
the external link is. This is code that was handed down to me. I've never
really understood what the purpose was. Shouldn't I just be able to
configure the SGMII link to 1Gbs full-duplex, regardless of what the external
link is set to?
> That is, if in your case you see the warning popping up but the link always
> regains connection, then it is an ignorable false positive.
Unfortunately, I can't really ignore it because genphy does this:
$ ifup eth1
[ 1034.754276] qcom-emac QCOM8070:00 eth1: Link is Up - 1Gbps/Full - flow
control rx/tx
But the at803x driver does this:
$ ifup eth1
[ 1020.507728] 803x_aneg_done: SGMII link is not ok
[ 1020.513517] qcom-emac QCOM8070:00 eth1: Link is Up - 1Gbps/Full - flow
control rx/tx
[ 1020.522839] qcom-emac QCOM8070:00 eth1: Link is Up - 1Gbps/Full - flow
control rx/tx
Customers are going to complain.
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH 3/3] bcm63xx_enet: avoid uninitialized variable warning
From: Arnd Bergmann @ 2017-01-18 14:52 UTC (permalink / raw)
To: Florian Fainelli, David S. Miller
Cc: Arnd Bergmann, xypron.glpk@gmx.de, linux-kernel,
bcm-kernel-feedback-list, netdev, linux-arm-kernel,
Philippe Reynes
In-Reply-To: <20170118145306.1004008-1-arnd@arndb.de>
gcc-7 and probably earlier versions get confused by this function
and print a harmless warning:
drivers/net/ethernet/broadcom/bcm63xx_enet.c: In function 'bcm_enet_open':
drivers/net/ethernet/broadcom/bcm63xx_enet.c:1130:3: error: 'phydev' may be used uninitialized in this function [-Werror=maybe-uninitialized]
This adds an initialization for the 'phydev' variable when it is unused
and changes the check to test for that NULL pointer to make it clear
that we always pass a valid pointer here.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 1ad904680ca6..f0a0bcb31b7e 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -913,6 +913,8 @@ static int bcm_enet_open(struct net_device *dev)
priv->old_link = 0;
priv->old_duplex = -1;
priv->old_pause = -1;
+ } else {
+ phydev = NULL;
}
/* mask all interrupts and request them */
@@ -1083,7 +1085,7 @@ static int bcm_enet_open(struct net_device *dev)
enet_dmac_writel(priv, priv->dma_chan_int_mask,
ENETDMAC_IRMASK, priv->tx_chan);
- if (priv->has_phy)
+ if (phydev)
phy_start(phydev);
else
bcm_enet_adjust_link(dev);
@@ -1126,7 +1128,7 @@ static int bcm_enet_open(struct net_device *dev)
free_irq(dev->irq, dev);
out_phy_disconnect:
- if (priv->has_phy)
+ if (phydev)
phy_disconnect(phydev);
return ret;
--
2.9.0
^ permalink raw reply related
* [PATCH 2/3] qed: avoid possible stack overflow in qed_ll2_acquire_connection
From: Arnd Bergmann @ 2017-01-18 14:52 UTC (permalink / raw)
To: Yuval Mintz, Ariel Elior, everest-linux-l2
Cc: Arnd Bergmann, David S. Miller, Ram Amrani, Wei Yongjun,
Hannes Reinecke, netdev, linux-kernel
In-Reply-To: <20170118145306.1004008-1-arnd@arndb.de>
struct qed_ll2_info is rather large, so putting it on the stack
can cause an overflow, as this warning tries to tell us:
drivers/net/ethernet/qlogic/qed/qed_ll2.c: In function 'qed_ll2_start':
drivers/net/ethernet/qlogic/qed/qed_ll2.c:2159:1: error: the frame size of 1056 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]
qed_ll2_start_ooo() already uses a dynamic allocation for the structure
to work around that problem, and we could do the same in qed_ll2_start()
as well as qed_roce_ll2_start(), but since the structure is only
used to pass a couple of initialization values here, it seems nicer
to replace it with a different structure.
Lacking any idea for better naming, I'm adding 'struct qed_ll2_conn',
which now contains all the initialization data, and this now simply
gets copied into struct qed_ll2_info rather than assigning all members
one by one.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/qlogic/qed/qed_ll2.c | 88 +++++++++++++-----------------
drivers/net/ethernet/qlogic/qed/qed_ll2.h | 24 ++++----
drivers/net/ethernet/qlogic/qed/qed_roce.c | 2 +-
3 files changed, 53 insertions(+), 61 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index 05e32f4322eb..02c5d47cfc6d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -320,7 +320,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
list_del(&p_pkt->list_entry);
b_last_packet = list_empty(&p_tx->active_descq);
list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);
- if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+ if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
struct qed_ooo_buffer *p_buffer;
p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
@@ -332,7 +332,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
b_last_frag =
p_tx->cur_completing_bd_idx == p_pkt->bd_used;
tx_frag = p_pkt->bds_set[0].tx_frag;
- if (p_ll2_conn->gsi_enable)
+ if (p_ll2_conn->conn.gsi_enable)
qed_ll2b_release_tx_gsi_packet(p_hwfn,
p_ll2_conn->
my_id,
@@ -401,7 +401,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
spin_unlock_irqrestore(&p_tx->lock, flags);
tx_frag = p_pkt->bds_set[0].tx_frag;
- if (p_ll2_conn->gsi_enable)
+ if (p_ll2_conn->conn.gsi_enable)
qed_ll2b_complete_tx_gsi_packet(p_hwfn,
p_ll2_conn->my_id,
p_pkt->cookie,
@@ -573,7 +573,7 @@ static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
list_move_tail(&p_pkt->list_entry, &p_rx->free_descq);
- if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+ if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
struct qed_ooo_buffer *p_buffer;
p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
@@ -761,7 +761,7 @@ qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id, 1,
p_buffer->vlan, bd_flags,
l4_hdr_offset_w,
- p_ll2_conn->tx_dest, 0,
+ p_ll2_conn->conn.tx_dest, 0,
first_frag,
p_buffer->packet_length,
p_buffer, true);
@@ -881,7 +881,7 @@ qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
u16 buf_idx;
int rc = 0;
- if (p_ll2_info->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+ if (p_ll2_info->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
return rc;
if (!rx_num_ooo_buffers)
@@ -924,7 +924,7 @@ static void
qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn)
{
- if (p_ll2_conn->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+ if (p_ll2_conn->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
return;
qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
@@ -936,7 +936,7 @@ static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
{
struct qed_ooo_buffer *p_buffer;
- if (p_ll2_conn->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+ if (p_ll2_conn->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
return;
qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
@@ -968,23 +968,19 @@ static int qed_ll2_start_ooo(struct qed_dev *cdev,
{
struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
- struct qed_ll2_info *ll2_info;
+ struct qed_ll2_conn ll2_info;
int rc;
- ll2_info = kzalloc(sizeof(*ll2_info), GFP_KERNEL);
- if (!ll2_info)
- return -ENOMEM;
- ll2_info->conn_type = QED_LL2_TYPE_ISCSI_OOO;
- ll2_info->mtu = params->mtu;
- ll2_info->rx_drop_ttl0_flg = params->drop_ttl0_packets;
- ll2_info->rx_vlan_removal_en = params->rx_vlan_stripping;
- ll2_info->tx_tc = OOO_LB_TC;
- ll2_info->tx_dest = CORE_TX_DEST_LB;
-
- rc = qed_ll2_acquire_connection(hwfn, ll2_info,
+ ll2_info.conn_type = QED_LL2_TYPE_ISCSI_OOO;
+ ll2_info.mtu = params->mtu;
+ ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
+ ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping;
+ ll2_info.tx_tc = OOO_LB_TC;
+ ll2_info.tx_dest = CORE_TX_DEST_LB;
+
+ rc = qed_ll2_acquire_connection(hwfn, &ll2_info,
QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
handle);
- kfree(ll2_info);
if (rc) {
DP_INFO(cdev, "Failed to acquire LL2 OOO connection\n");
goto out;
@@ -1029,7 +1025,7 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn,
u8 action_on_error)
{
- enum qed_ll2_conn_type conn_type = p_ll2_conn->conn_type;
+ enum qed_ll2_conn_type conn_type = p_ll2_conn->conn.conn_type;
struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
struct core_rx_start_ramrod_data *p_ramrod = NULL;
struct qed_spq_entry *p_ent = NULL;
@@ -1055,7 +1051,7 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
p_ramrod->sb_index = p_rx->rx_sb_index;
p_ramrod->complete_event_flg = 1;
- p_ramrod->mtu = cpu_to_le16(p_ll2_conn->mtu);
+ p_ramrod->mtu = cpu_to_le16(p_ll2_conn->conn.mtu);
DMA_REGPAIR_LE(p_ramrod->bd_base,
p_rx->rxq_chain.p_phys_addr);
cqe_pbl_size = (u16)qed_chain_get_page_cnt(&p_rx->rcq_chain);
@@ -1063,8 +1059,8 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr,
qed_chain_get_pbl_phys(&p_rx->rcq_chain));
- p_ramrod->drop_ttl0_flg = p_ll2_conn->rx_drop_ttl0_flg;
- p_ramrod->inner_vlan_removal_en = p_ll2_conn->rx_vlan_removal_en;
+ p_ramrod->drop_ttl0_flg = p_ll2_conn->conn.rx_drop_ttl0_flg;
+ p_ramrod->inner_vlan_removal_en = p_ll2_conn->conn.rx_vlan_removal_en;
p_ramrod->queue_id = p_ll2_conn->queue_id;
p_ramrod->main_func_queue = (conn_type == QED_LL2_TYPE_ISCSI_OOO) ? 0
: 1;
@@ -1079,14 +1075,14 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
}
p_ramrod->action_on_error.error_type = action_on_error;
- p_ramrod->gsi_offload_flag = p_ll2_conn->gsi_enable;
+ p_ramrod->gsi_offload_flag = p_ll2_conn->conn.gsi_enable;
return qed_spq_post(p_hwfn, p_ent, NULL);
}
static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn)
{
- enum qed_ll2_conn_type conn_type = p_ll2_conn->conn_type;
+ enum qed_ll2_conn_type conn_type = p_ll2_conn->conn.conn_type;
struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;
struct core_tx_start_ramrod_data *p_ramrod = NULL;
struct qed_spq_entry *p_ent = NULL;
@@ -1098,7 +1094,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
return 0;
- if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO)
+ if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
p_ll2_conn->tx_stats_en = 0;
else
p_ll2_conn->tx_stats_en = 1;
@@ -1119,7 +1115,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn));
p_ramrod->sb_index = p_tx->tx_sb_index;
- p_ramrod->mtu = cpu_to_le16(p_ll2_conn->mtu);
+ p_ramrod->mtu = cpu_to_le16(p_ll2_conn->conn.mtu);
p_ramrod->stats_en = p_ll2_conn->tx_stats_en;
p_ramrod->stats_id = p_ll2_conn->tx_stats_id;
@@ -1129,7 +1125,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
p_ramrod->pbl_size = cpu_to_le16(pbl_size);
memset(&pq_params, 0, sizeof(pq_params));
- pq_params.core.tc = p_ll2_conn->tx_tc;
+ pq_params.core.tc = p_ll2_conn->conn.tx_tc;
pq_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_CORE, &pq_params);
p_ramrod->qm_pq_id = cpu_to_le16(pq_id);
@@ -1146,7 +1142,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn, "Unknown connection type: %d\n", conn_type);
}
- p_ramrod->gsi_offload_flag = p_ll2_conn->gsi_enable;
+ p_ramrod->gsi_offload_flag = p_ll2_conn->conn.gsi_enable;
return qed_spq_post(p_hwfn, p_ent, NULL);
}
@@ -1247,7 +1243,7 @@ qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn,
DP_VERBOSE(p_hwfn, QED_MSG_LL2,
"Allocated LL2 Rxq [Type %08x] with 0x%08x buffers\n",
- p_ll2_info->conn_type, rx_num_desc);
+ p_ll2_info->conn.conn_type, rx_num_desc);
out:
return rc;
@@ -1285,7 +1281,7 @@ static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn,
DP_VERBOSE(p_hwfn, QED_MSG_LL2,
"Allocated LL2 Txq [Type %08x] with 0x%08x buffers\n",
- p_ll2_info->conn_type, tx_num_desc);
+ p_ll2_info->conn.conn_type, tx_num_desc);
out:
if (rc)
@@ -1296,7 +1292,7 @@ static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn,
}
int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
- struct qed_ll2_info *p_params,
+ struct qed_ll2_conn *p_params,
u16 rx_num_desc,
u16 tx_num_desc,
u8 *p_connection_handle)
@@ -1325,15 +1321,7 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
if (!p_ll2_info)
return -EBUSY;
- p_ll2_info->conn_type = p_params->conn_type;
- p_ll2_info->mtu = p_params->mtu;
- p_ll2_info->rx_drop_ttl0_flg = p_params->rx_drop_ttl0_flg;
- p_ll2_info->rx_vlan_removal_en = p_params->rx_vlan_removal_en;
- p_ll2_info->tx_tc = p_params->tx_tc;
- p_ll2_info->tx_dest = p_params->tx_dest;
- p_ll2_info->ai_err_packet_too_big = p_params->ai_err_packet_too_big;
- p_ll2_info->ai_err_no_buf = p_params->ai_err_no_buf;
- p_ll2_info->gsi_enable = p_params->gsi_enable;
+ p_ll2_info->conn = *p_params;
rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info, rx_num_desc);
if (rc)
@@ -1394,9 +1382,9 @@ static int qed_ll2_establish_connection_rx(struct qed_hwfn *p_hwfn,
SET_FIELD(action_on_error,
CORE_RX_ACTION_ON_ERROR_PACKET_TOO_BIG,
- p_ll2_conn->ai_err_packet_too_big);
+ p_ll2_conn->conn.ai_err_packet_too_big);
SET_FIELD(action_on_error,
- CORE_RX_ACTION_ON_ERROR_NO_BUFF, p_ll2_conn->ai_err_no_buf);
+ CORE_RX_ACTION_ON_ERROR_NO_BUFF, p_ll2_conn->conn.ai_err_no_buf);
return qed_sp_ll2_rx_queue_start(p_hwfn, p_ll2_conn, action_on_error);
}
@@ -1623,7 +1611,7 @@ static void qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,
"LL2 [q 0x%02x cid 0x%08x type 0x%08x] Tx Producer at [0x%04x] - set with a %04x bytes %02x BDs buffer at %08x:%08x\n",
p_ll2->queue_id,
p_ll2->cid,
- p_ll2->conn_type,
+ p_ll2->conn.conn_type,
prod_idx,
first_frag_len,
num_of_bds,
@@ -1699,7 +1687,7 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,
(NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
"LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 0x%04x]\n",
p_ll2_conn->queue_id,
- p_ll2_conn->cid, p_ll2_conn->conn_type, db_msg.spq_prod);
+ p_ll2_conn->cid, p_ll2_conn->conn.conn_type, db_msg.spq_prod);
}
int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
@@ -1840,7 +1828,7 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
qed_ll2_rxq_flush(p_hwfn, connection_handle);
}
- if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO)
+ if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
return rc;
@@ -2016,7 +2004,7 @@ static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
{
- struct qed_ll2_info ll2_info;
+ struct qed_ll2_conn ll2_info;
struct qed_ll2_buffer *buffer, *tmp_buffer;
enum qed_ll2_conn_type conn_type;
struct qed_ptt *p_ptt;
@@ -2064,6 +2052,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
/* Prepare the temporary ll2 information */
memset(&ll2_info, 0, sizeof(ll2_info));
+
ll2_info.conn_type = conn_type;
ll2_info.mtu = params->mtu;
ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
@@ -2143,7 +2132,6 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
}
ether_addr_copy(cdev->ll2_mac_address, params->ll2_mac_address);
-
return 0;
release_terminate_all:
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
index c7f2975590ee..db3e4fc78e09 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -135,15 +135,8 @@ struct qed_ll2_tx_queue {
bool b_completing_packet;
};
-struct qed_ll2_info {
- /* Lock protecting the state of LL2 */
- struct mutex mutex;
+struct qed_ll2_conn {
enum qed_ll2_conn_type conn_type;
- u32 cid;
- u8 my_id;
- u8 queue_id;
- u8 tx_stats_id;
- bool b_active;
u16 mtu;
u8 rx_drop_ttl0_flg;
u8 rx_vlan_removal_en;
@@ -151,10 +144,21 @@ struct qed_ll2_info {
enum core_tx_dest tx_dest;
enum core_error_handle ai_err_packet_too_big;
enum core_error_handle ai_err_no_buf;
+ u8 gsi_enable;
+};
+
+struct qed_ll2_info {
+ /* Lock protecting the state of LL2 */
+ struct mutex mutex;
+ struct qed_ll2_conn conn;
+ u32 cid;
+ u8 my_id;
+ u8 queue_id;
+ u8 tx_stats_id;
+ bool b_active;
u8 tx_stats_en;
struct qed_ll2_rx_queue rx_queue;
struct qed_ll2_tx_queue tx_queue;
- u8 gsi_enable;
};
/**
@@ -172,7 +176,7 @@ struct qed_ll2_info {
* @return 0 on success, failure otherwise
*/
int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
- struct qed_ll2_info *p_params,
+ struct qed_ll2_conn *p_params,
u16 rx_num_desc,
u16 tx_num_desc,
u8 *p_connection_handle);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c
index bd4cad2b343b..c3c8c5018e93 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_roce.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c
@@ -2632,7 +2632,7 @@ static int qed_roce_ll2_start(struct qed_dev *cdev,
{
struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
struct qed_roce_ll2_info *roce_ll2;
- struct qed_ll2_info ll2_params;
+ struct qed_ll2_conn ll2_params;
int rc;
if (!params) {
--
2.9.0
^ permalink raw reply related
* [PATCH 1/3] cxgb4: hide unused warnings
From: Arnd Bergmann @ 2017-01-18 14:52 UTC (permalink / raw)
To: Hariprasad S
Cc: Arnd Bergmann, David S. Miller, Ganesh Goudar, Rahul Lakkireddy,
Varun Prakash, netdev, linux-kernel
The two new variables are only used inside of an #ifdef and cause
harmless warnings when that is disabled:
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c: In function 'init_one':
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:4646:9: error: unused variable 'port_vec' [-Werror=unused-variable]
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:4646:6: error: unused variable 'v' [-Werror=unused-variable]
This adds another #ifdef around the declarations.
Fixes: 96fe11f27b70 ("cxgb4: Implement ndo_get_phys_port_id for mgmt dev")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 4da6f900ff24..49e000ebd2b9 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -4643,7 +4643,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
u32 whoami, pl_rev;
enum chip_type chip;
static int adap_idx = 1;
+#ifdef CONFIG_PCI_IOV
u32 v, port_vec;
+#endif
printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
--
2.9.0
^ permalink raw reply related
* Re: Initializing MAC address at run-time
From: Mark Rutland @ 2017-01-18 14:45 UTC (permalink / raw)
To: Mason
Cc: Linux ARM, DT, netdev, Arnd Bergmann, Kevin Hilman,
Uwe Kleine-Konig, Thibaud Cornic
In-Reply-To: <e083ed68-0e8e-380e-23bd-5ad387c88575-GANU6spQydw@public.gmane.org>
On Wed, Jan 18, 2017 at 03:03:57PM +0100, Mason wrote:
> Hello,
>
> When my system boots up, eth0 is given a seemingly random MAC address.
>
> [ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
> [ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
>
>
> The DT node for eth0 is:
>
> eth0: ethernet@26000 {
> compatible = "sigma,smp8734-ethernet";
> reg = <0x26000 0x800>;
> interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&clkgen SYS_CLK>;
> };
>
> Documentation/devicetree/bindings/net/ethernet.txt mentions
> - local-mac-address: array of 6 bytes, specifies the MAC address that was
> assigned to the network device;
>
> And indeed, if I define this property, eth0 ends up with the MAC address
> I specify in the device tree. But of course, I don't want all my boards
> to share the same MAC address. Every interface has a unique MAC address.
>
> In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
> the MAC address somewhere in MMIO space, in some weird custom format.
>
> So, at init, I can find the MAC address, and dynamically insert the
> "local-mac-address" property in the eth0 node.
To me it sounds very convoluted to do this from the kernel, to pass
information back to itself. I don't think this is the best way to handle
this.
> Is there another (better) way to do this?
>
> I'll post my code below, for illustration purpose.
>
> Mark suggested this can be done from user-space, but I can't do that,
> because I'm using an NFS rootfs, so I need the network before I even
> have a user-space. And the DHCP server is configured to serve different
> root filesystems, based on the MAC address.
That's not quite what I said. I asked whether your information was
coming from userspace or from a kernel driver.
My suggestion was that this should be done in the probe path somehow,
by describing the relationship between the ethernet controller and the
device containing the MAC information.
e.g. on the ethernet device, have a phandle (and perhaps some other
args) describinng the device containing the MAC, and how to extract it.
That way, in the ethernet probe path we can go and look up the MAC
address from the provider of that information.
> I need to do something similar with the NAND partitions. The boot loader
> stores the partition offsets somewhere, and I need to pass this info
> to the NAND framework, so I assumed that inserting the corresponding
> properties at run-time was the correct way to do it.
I would say similar could happen here.
Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] softingcs: ret is never non-zero, so remove non-zero check and -ENODEV return
From: Marc Kleine-Budde @ 2017-01-18 14:44 UTC (permalink / raw)
To: Colin King, Wolfgang Grandegger, linux-can, netdev; +Cc: linux-kernel
In-Reply-To: <20170111150238.19845-1-colin.king@canonical.com>
[-- Attachment #1.1: Type: text/plain, Size: 697 bytes --]
On 01/11/2017 04:02 PM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The error return ret is never zero in the error handling path in
> softingcs_probe, so the check for non-zero and returning -ENODEV
> is logically dead code and hence redundant. Remove it and just
> return ret.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
Thanks, applied to can-next.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [1/1] net: wireless: marvell: fix improper return value
From: Kalle Valo @ 2017-01-18 14:43 UTC (permalink / raw)
To: Pan Bian
Cc: Andreas Kemnade, Johannes Berg, libertas-dev, linux-wireless,
netdev, linux-kernel, Pan Bian
In-Reply-To: <1480760857-4549-1-git-send-email-bianpan2016@163.com>
Pan Bian <bianpan2016@163.com> wrote:
> Function lbs_cmd_802_11_sleep_params() always return 0, even if the call
> to lbs_cmd_with_response() fails. In this case, the parameter @sp will
> keep uninitialized. Because the return value is 0, its caller (say
> lbs_sleepparams_read()) will not detect the error, and will copy the
> uninitialized stack memory to user sapce, resulting in stack information
> leak. To avoid the bug, this patch returns variable ret (which takes
> the return value of lbs_cmd_with_response()) instead of 0.
>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188451
>
> Signed-off-by: Pan Bian <bianpan2016@163.com>
The prefix should be "libertas:", I'll fix that.
--
https://patchwork.kernel.org/patch/9459597/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [1/5] ath10k: Remove unused 'buf_len' variable
From: Kalle Valo @ 2017-01-18 14:37 UTC (permalink / raw)
To: Kirtika Ruchandani
Cc: Kalle Valo, Arnd Bergmann, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA, Raja Mani, Michal Kazior
In-Reply-To: <196e46eee00fd3ebb56da1373c36f3dff66f2ae1.1479974100.git.kirtika-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Kirtika Ruchandani <kirtika.ruchandani-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Commit 32653cf19554 removed the call to 'skb_trim(skb, buf_len)'
> in ath10k_wmi_event_mgmt_rx(), leaving the buf_len variable set but
> unused. Compiling with W=1 gives the following warning, fix it.
> drivers/net/wireless/ath/ath10k/wmi.c: In function ‘ath10k_wmi_event_mgmt_rx’:
> drivers/net/wireless/ath/ath10k/wmi.c:2280:6: warning: variable ‘buf_len’ set but not used [-Wunused-but-set-variable]
>
> This is a harmless warning, and is only being fixed to reduce the
> noise with W=1 in the kernel.
>
> Fixes: 32653cf19554 ("ath10k: implement intermediate event args")
> Cc: Michal Kazior <michal.kazior-++hxYGjEMp0AvxtiuMwx3w@public.gmane.org>
> Cc: Kalle Valo <kvalo-A+ZNKFmMK5xy9aJCnZT0Uw@public.gmane.org>
> Signed-off-by: Kirtika Ruchandani <kirtika-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
These patches seem to be corrupted:
Applying: ath10k: Remove unused 'buf_len' variable
fatal: corrupt patch at line 13
error: could not build fake ancestor
Patch failed at 0001 ath10k: Remove unused 'buf_len' variable
When resending please also cc ath10k list:
https://wireless.wiki.kernel.org/en/users/drivers/ath10k/sources#submitting_patches
4 patches set to Changes Requested.
9444973 [1/5] ath10k: Remove unused 'buf_len' variable
9444935 [2/5] ath10k: Remove unused 'num_vdev_stats' variable
9444971 [4/5] ath10k: Removed unused 'dev' in ath10k_ahb_clock_enable()
9444975 [5/5] ath10k: Removed unused 'dev' in ath10k_ahb_resource_init
--
https://patchwork.kernel.org/patch/9444973/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v3 1/2] bpf: add a longest prefix match trie map implementation
From: David Herrmann @ 2017-01-18 14:30 UTC (permalink / raw)
To: Alexei Starovoitov; +Cc: Daniel Mack, Daniel Borkmann, netdev, David S. Miller
In-Reply-To: <587A581A.6060304@fb.com>
Hi
On Sat, Jan 14, 2017 at 5:55 PM, Alexei Starovoitov <ast@fb.com> wrote:
> Another alternative is to extend samples/bpf/map_perf_test
> It has perf tests for most map types today (including lru)
> and trie would be natural addition there.
> I would prefer this latter option.
I hooked into gettid() and installed a simple kprobe bpf program that
searches for an entry in an lpm trie. The bpf program does either 0,
1, 8, or 32 lookups in a row (always the same element). The trie has
size 0, 1, or 8192. The data is below. The results vary by roughly 5%
on every run.
A single gettid() syscall with an empty bpf program takes roughly
6.5us on my system. Lookups in empty tries take ~1.8us on first try,
~0.9us on retries. Lookups in tries with 8192 entries take ~7.1us (on
the first _and_ any subsequent try).
https://gist.github.com/dvdhrm/4c90e61a1c39746d5c55ab9e0e29315e
Thanks
David
Trie-size: 0
#Lookups: 0
0:lpm_perf kmalloc 9,230,321 events per sec
-> 6.5us / syscall
Trie-size: 1
#Lookups: 1
0:lpm_perf kmalloc 7,224,508 events per sec
-> 8.3us / syscall
Trie-size: 1
#Lookups: 8
0:lpm_perf kmalloc 4,152,740 events per sec
-> 14.4us / syscall
Trie-size: 1
#Lookups: 32
0:lpm_perf kmalloc 1,713,415 events per sec
-> 35.0us / syscall
Trie-size: 8192
#Lookups: 1
0:lpm_perf kmalloc 4,369,138 events per sec
-> 13.7us / syscall
Trie-size: 8192
#Lookups: 8
0:lpm_perf kmalloc 943,849 events per sec
-> 63.6us / syscall
Trie-size: 8192
#Lookups: 32
0:lpm_perf kmalloc 271,737 events per sec
-> 220.8us / syscall
^ permalink raw reply
* Re: [PATCH net-next] mlx4: support __GFP_MEMALLOC for rx
From: Eric Dumazet @ 2017-01-18 14:23 UTC (permalink / raw)
To: Konstantin Khlebnikov
Cc: David Miller, netdev, Tariq Toukan, linux-mm@kvack.org
In-Reply-To: <2696ea05-bb39-787b-2029-33b729fd88e0@yandex-team.ru>
On Wed, 2017-01-18 at 12:31 +0300, Konstantin Khlebnikov wrote:
> On 18.01.2017 07:14, Eric Dumazet wrote:
> > From: Eric Dumazet <edumazet@google.com>
> >
> > Commit 04aeb56a1732 ("net/mlx4_en: allocate non 0-order pages for RX
> > ring with __GFP_NOMEMALLOC") added code that appears to be not needed at
> > that time, since mlx4 never used __GFP_MEMALLOC allocations anyway.
> >
> > As using memory reserves is a must in some situations (swap over NFS or
> > iSCSI), this patch adds this flag.
>
> AFAIK __GFP_MEMALLOC is used for TX, not for RX: for allocations which
> are required by memory reclaimer to free some pages.
>
> Allocation RX buffers with __GFP_MEMALLOC is a straight way to
> depleting all reserves by flood from network.
You are mistaken.
How do you think a TCP flow can make progress sending data if no ACK
packet can go back in RX ?
Take a look at sk_filter_trim_cap(), where the RX packets received on a
socket which does not have SOCK_MEMALLOC is dropped.
/*
* If the skb was allocated from pfmemalloc reserves, only
* allow SOCK_MEMALLOC sockets to use it as this socket is
* helping free memory
*/
if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
return -ENOMEM;
Also take a look at __dev_alloc_pages()
static inline struct page *__dev_alloc_pages(gfp_t gfp_mask,
unsigned int order)
{
/* This piece of code contains several assumptions.
* 1. This is for device Rx, therefor a cold page is preferred.
* 2. The expectation is the user wants a compound page.
* 3. If requesting a order 0 page it will not be compound
* due to the check to see if order has a value in prep_new_page
* 4. __GFP_MEMALLOC is ignored if __GFP_NOMEMALLOC is set due to
* code in gfp_to_alloc_flags that should be enforcing this.
*/
gfp_mask |= __GFP_COLD | __GFP_COMP | __GFP_MEMALLOC;
return alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
}
So __GFP_MEMALLOC in RX is absolutely supported.
But drivers have to opt-in, either using __dev_alloc_pages() or
dev_alloc_pages, or explicitely ORing __GFP_MEMALLOC when using
alloc_page[s]()
--
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 net] bpf: don't trigger OOM killer under pressure with map alloc
From: Daniel Borkmann @ 2017-01-18 14:14 UTC (permalink / raw)
To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
This patch adds two helpers, bpf_map_area_alloc() and bpf_map_area_free(),
that are to be used for map allocations. Using kmalloc() for very large
allocations can cause excessive work within the page allocator, so i) fall
back earlier to vmalloc() when the attempt is considered costly anyway,
and even more importantly ii) don't trigger OOM killer with any of the
allocators.
Since this is based on a user space request, for example, when creating
maps with element pre-allocation, we really want such requests to fail
instead of killing other user space processes.
Also, don't spam the kernel log with warnings should any of the allocations
fail under pressure. Given that, we can make backend selection in
bpf_map_area_alloc() generic, and convert all maps over to use this API
for spots with potentially large allocation requests.
Note, replacing the one kmalloc_array() is fine as overflow checks happen
earlier in htab_map_alloc(), since it must also protect the multiplication
for vmalloc() should kmalloc_array() fail.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
include/linux/bpf.h | 2 ++
kernel/bpf/arraymap.c | 18 +++++++-----------
kernel/bpf/hashtab.c | 22 +++++++++-------------
kernel/bpf/stackmap.c | 20 ++++++++------------
kernel/bpf/syscall.c | 26 ++++++++++++++++++++++++++
5 files changed, 52 insertions(+), 36 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 05cf951..3ed1f3b 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -247,6 +247,8 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
void bpf_map_put_with_uref(struct bpf_map *map);
void bpf_map_put(struct bpf_map *map);
int bpf_map_precharge_memlock(u32 pages);
+void *bpf_map_area_alloc(size_t size);
+void bpf_map_area_free(void *base);
extern int sysctl_unprivileged_bpf_disabled;
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 229a5d5..3d55d95 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -11,7 +11,6 @@
*/
#include <linux/bpf.h>
#include <linux/err.h>
-#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/filter.h>
@@ -74,14 +73,10 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
if (array_size >= U32_MAX - PAGE_SIZE)
return ERR_PTR(-ENOMEM);
-
/* allocate all map elements and zero-initialize them */
- array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
- if (!array) {
- array = vzalloc(array_size);
- if (!array)
- return ERR_PTR(-ENOMEM);
- }
+ array = bpf_map_area_alloc(array_size);
+ if (!array)
+ return ERR_PTR(-ENOMEM);
/* copy mandatory map attributes */
array->map.map_type = attr->map_type;
@@ -97,7 +92,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
if (array_size >= U32_MAX - PAGE_SIZE ||
elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) {
- kvfree(array);
+ bpf_map_area_free(array);
return ERR_PTR(-ENOMEM);
}
out:
@@ -262,7 +257,7 @@ static void array_map_free(struct bpf_map *map)
if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
bpf_array_free_percpu(array);
- kvfree(array);
+ bpf_map_area_free(array);
}
static const struct bpf_map_ops array_ops = {
@@ -319,7 +314,8 @@ static void fd_array_map_free(struct bpf_map *map)
/* make sure it's empty */
for (i = 0; i < array->map.max_entries; i++)
BUG_ON(array->ptrs[i] != NULL);
- kvfree(array);
+
+ bpf_map_area_free(array);
}
static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 3f2bb58..a753bbe 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -13,7 +13,6 @@
#include <linux/bpf.h>
#include <linux/jhash.h>
#include <linux/filter.h>
-#include <linux/vmalloc.h>
#include "percpu_freelist.h"
#include "bpf_lru_list.h"
@@ -103,7 +102,7 @@ static void htab_free_elems(struct bpf_htab *htab)
free_percpu(pptr);
}
free_elems:
- vfree(htab->elems);
+ bpf_map_area_free(htab->elems);
}
static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
@@ -125,7 +124,8 @@ static int prealloc_init(struct bpf_htab *htab)
{
int err = -ENOMEM, i;
- htab->elems = vzalloc(htab->elem_size * htab->map.max_entries);
+ htab->elems = bpf_map_area_alloc(htab->elem_size *
+ htab->map.max_entries);
if (!htab->elems)
return -ENOMEM;
@@ -320,14 +320,10 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
goto free_htab;
err = -ENOMEM;
- htab->buckets = kmalloc_array(htab->n_buckets, sizeof(struct bucket),
- GFP_USER | __GFP_NOWARN);
-
- if (!htab->buckets) {
- htab->buckets = vmalloc(htab->n_buckets * sizeof(struct bucket));
- if (!htab->buckets)
- goto free_htab;
- }
+ htab->buckets = bpf_map_area_alloc(htab->n_buckets *
+ sizeof(struct bucket));
+ if (!htab->buckets)
+ goto free_htab;
for (i = 0; i < htab->n_buckets; i++) {
INIT_HLIST_HEAD(&htab->buckets[i].head);
@@ -354,7 +350,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
free_extra_elems:
free_percpu(htab->extra_elems);
free_buckets:
- kvfree(htab->buckets);
+ bpf_map_area_free(htab->buckets);
free_htab:
kfree(htab);
return ERR_PTR(err);
@@ -1014,7 +1010,7 @@ static void htab_map_free(struct bpf_map *map)
prealloc_destroy(htab);
free_percpu(htab->extra_elems);
- kvfree(htab->buckets);
+ bpf_map_area_free(htab->buckets);
kfree(htab);
}
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index 732ae16..be85191 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -7,7 +7,6 @@
#include <linux/bpf.h>
#include <linux/jhash.h>
#include <linux/filter.h>
-#include <linux/vmalloc.h>
#include <linux/stacktrace.h>
#include <linux/perf_event.h>
#include "percpu_freelist.h"
@@ -32,7 +31,7 @@ static int prealloc_elems_and_freelist(struct bpf_stack_map *smap)
u32 elem_size = sizeof(struct stack_map_bucket) + smap->map.value_size;
int err;
- smap->elems = vzalloc(elem_size * smap->map.max_entries);
+ smap->elems = bpf_map_area_alloc(elem_size * smap->map.max_entries);
if (!smap->elems)
return -ENOMEM;
@@ -45,7 +44,7 @@ static int prealloc_elems_and_freelist(struct bpf_stack_map *smap)
return 0;
free_elems:
- vfree(smap->elems);
+ bpf_map_area_free(smap->elems);
return err;
}
@@ -76,12 +75,9 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
if (cost >= U32_MAX - PAGE_SIZE)
return ERR_PTR(-E2BIG);
- smap = kzalloc(cost, GFP_USER | __GFP_NOWARN);
- if (!smap) {
- smap = vzalloc(cost);
- if (!smap)
- return ERR_PTR(-ENOMEM);
- }
+ smap = bpf_map_area_alloc(cost);
+ if (!smap)
+ return ERR_PTR(-ENOMEM);
err = -E2BIG;
cost += n_buckets * (value_size + sizeof(struct stack_map_bucket));
@@ -112,7 +108,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
put_buffers:
put_callchain_buffers();
free_smap:
- kvfree(smap);
+ bpf_map_area_free(smap);
return ERR_PTR(err);
}
@@ -262,9 +258,9 @@ static void stack_map_free(struct bpf_map *map)
/* wait for bpf programs to complete before freeing stack map */
synchronize_rcu();
- vfree(smap->elems);
+ bpf_map_area_free(smap->elems);
pcpu_freelist_destroy(&smap->freelist);
- kvfree(smap);
+ bpf_map_area_free(smap);
put_callchain_buffers();
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 1d6b29e..19b6129 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -12,6 +12,8 @@
#include <linux/bpf.h>
#include <linux/syscalls.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mmzone.h>
#include <linux/anon_inodes.h>
#include <linux/file.h>
#include <linux/license.h>
@@ -49,6 +51,30 @@ void bpf_register_map_type(struct bpf_map_type_list *tl)
list_add(&tl->list_node, &bpf_map_types);
}
+void *bpf_map_area_alloc(size_t size)
+{
+ /* We definitely need __GFP_NORETRY, so OOM killer doesn't
+ * trigger under memory pressure as we really just want to
+ * fail instead.
+ */
+ const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
+ void *area;
+
+ if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+ area = kmalloc(size, GFP_USER | flags);
+ if (area != NULL)
+ return area;
+ }
+
+ return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
+ PAGE_KERNEL);
+}
+
+void bpf_map_area_free(void *area)
+{
+ kvfree(area);
+}
+
int bpf_map_precharge_memlock(u32 pages)
{
struct user_struct *user = get_current_user();
--
1.9.3
^ permalink raw reply related
* Initializing MAC address at run-time
From: Mason @ 2017-01-18 14:03 UTC (permalink / raw)
To: Linux ARM, DT, netdev
Cc: Mark Rutland, Thibaud Cornic, Uwe Kleine-Konig, Arnd Bergmann,
Kevin Hilman
Hello,
When my system boots up, eth0 is given a seemingly random MAC address.
[ 0.950734] nb8800 26000.ethernet eth0: MAC address ba:de:d6:38:b8:38
[ 0.957334] nb8800 26000.ethernet eth0: MAC address 6e:f1:48:de:d6:c4
The DT node for eth0 is:
eth0: ethernet@26000 {
compatible = "sigma,smp8734-ethernet";
reg = <0x26000 0x800>;
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkgen SYS_CLK>;
};
Documentation/devicetree/bindings/net/ethernet.txt mentions
- local-mac-address: array of 6 bytes, specifies the MAC address that was
assigned to the network device;
And indeed, if I define this property, eth0 ends up with the MAC address
I specify in the device tree. But of course, I don't want all my boards
to share the same MAC address. Every interface has a unique MAC address.
In fact, the boot loader (not Uboot, a custom non-DT boot loader) stores
the MAC address somewhere in MMIO space, in some weird custom format.
So, at init, I can find the MAC address, and dynamically insert the
"local-mac-address" property in the eth0 node.
Is there another (better) way to do this?
I'll post my code below, for illustration purpose.
Mark suggested this can be done from user-space, but I can't do that,
because I'm using an NFS rootfs, so I need the network before I even
have a user-space. And the DHCP server is configured to serve different
root filesystems, based on the MAC address.
I need to do something similar with the NAND partitions. The boot loader
stores the partition offsets somewhere, and I need to pass this info
to the NAND framework, so I assumed that inserting the corresponding
properties at run-time was the correct way to do it.
Regards.
#include <linux/of.h>
#include <linux/io.h>
#include <asm/unaligned.h>
#define XENV_LRRW_ADDR 0x61a00
#define XENV_LRRW_SIZE 628
static u8 xenv[XENV_LRRW_SIZE] __initdata;
static void __init *xenv_lookup(void *addr, const char *key, int keylen)
{
u32 len = le32_to_cpup(addr);
void *end = addr + len;
if (len > XENV_LRRW_SIZE)
return NULL;
for (addr += 36; addr < end; addr += len)
{
len = get_unaligned_be16(addr) & 0xfff;
if (strcmp(key, addr + 2) == 0)
return addr + 2 + keylen;
}
return NULL;
}
static struct property prop;
static u8 mac[6];
static const char mac_lo[] __initconst = "lrrw.maclo";
static const char mac_hi[] __initconst = "lrrw.machi";
static int __init tango_get_mac_address(void *xenv)
{
struct device_node *np = of_find_node_by_path("eth0");
u8 *lo = xenv_lookup(xenv, mac_lo, sizeof mac_lo);
u8 *hi = xenv_lookup(xenv, mac_hi, sizeof mac_hi);
if (np == NULL || lo == NULL || hi == NULL) return -ENODEV;
mac[0] = hi[1];
mac[1] = hi[0];
mac[2] = lo[3];
mac[3] = lo[2];
mac[4] = lo[1];
mac[5] = lo[0];
prop.name = "local-mac-address";
prop.length = sizeof mac;
prop.value = mac;
return of_update_property(np, &prop);
}
static int __init mac_fixup(void)
{
void __iomem *xenv_orig = ioremap(XENV_LRRW_ADDR, XENV_LRRW_SIZE);
memcpy_fromio(xenv, xenv_orig, XENV_LRRW_SIZE);
iounmap(xenv_orig);
return tango_get_mac_address(xenv);
}
device_initcall(mac_fixup);
^ permalink raw reply
* Re: [PATCH 2/2] at803x: double check SGMII side autoneg
From: Zefir Kurtisi @ 2017-01-18 13:53 UTC (permalink / raw)
To: Timur Tabi, netdev; +Cc: andrew, f.fainelli
In-Reply-To: <5763c2fb-7286-15b0-091f-1abf26c0afe7@codeaurora.org>
On 01/18/2017 02:13 PM, Timur Tabi wrote:
> Zefir Kurtisi wrote:
>> The fact that you see the warning means external autoneg completes before the
>> SGMII side in best case or SGMII link remains down in worst case.
>
> So I'm no expert on this. Are you saying that I might possibly be doing things
> backwards in my driver? That is, I should be configuring the SGMII side of the
> link before I start autonegotiation?
>
No, not necessarily. The SGMII link default configuration is set such that you do
not have to bother at all.
That is, if in your case you see the warning popping up but the link always
regains connection, then it is an ignorable false positive.
^ permalink raw reply
* [PATCH] net: ethtool: avoid allocation failure for dump_regs
From: David Arcari @ 2017-01-18 13:34 UTC (permalink / raw)
To: netdev; +Cc: David Arcari
If the user executes 'ethtool -d' for an interface and the associated
get_regs_len() function returns 0, the user will see a call trace from
the vmalloc() call in ethtool_get_regs(). This patch modifies
ethtool_get_regs() to avoid the call to vmalloc when the size is zero.
Signed-off-by: David Arcari <darcari@redhat.com>
---
net/core/ethtool.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index e23766c..47acd6f 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1405,7 +1405,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
if (regs.len > reglen)
regs.len = reglen;
- regbuf = vzalloc(reglen);
+ regbuf = reglen ? vzalloc(reglen) : NULL;
if (reglen && !regbuf)
return -ENOMEM;
^ permalink raw reply related
* Re: [PATCH 2/2] at803x: double check SGMII side autoneg
From: Timur Tabi @ 2017-01-18 13:13 UTC (permalink / raw)
To: Zefir Kurtisi, netdev; +Cc: andrew, f.fainelli
In-Reply-To: <3291b7c1-7bf6-d776-adab-b89c9cd9be38@neratec.com>
Zefir Kurtisi wrote:
> The fact that you see the warning means external autoneg completes before the
> SGMII side in best case or SGMII link remains down in worst case.
So I'm no expert on this. Are you saying that I might possibly be doing
things backwards in my driver? That is, I should be configuring the
SGMII side of the link before I start autonegotiation?
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.
^ permalink raw reply
* [net-next PATCH 3/3] device: Implement a bus agnostic dev_num_vf routine
From: Phil Sutter @ 2017-01-18 13:04 UTC (permalink / raw)
To: David Miller, Bjorn Helgaas; +Cc: netdev, linux-pci
In-Reply-To: <20170118130439.15023-1-phil@nwl.cc>
Now that pci_bus_type has num_vf callback set, dev_num_vf can be
implemented in a bus type independent way and the check for whether a
PCI device is being handled in rtnetlink can be dropped.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
include/linux/device.h | 7 +++++++
include/linux/pci.h | 2 --
net/core/rtnetlink.c | 3 +--
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/include/linux/device.h b/include/linux/device.h
index 6d73b70a4a5d7..bd684fc8ec1d8 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1144,6 +1144,13 @@ extern int device_online(struct device *dev);
extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
+static inline int dev_num_vf(struct device *dev)
+{
+ if (dev->bus && dev->bus->num_vf)
+ return dev->bus->num_vf(dev);
+ return 0;
+}
+
/*
* Root device objects for grouping under /sys/devices
*/
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e2d1a124216a9..adbc859fe7c4c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -885,7 +885,6 @@ void pcibios_setup_bridge(struct pci_bus *bus, unsigned long type);
void pci_sort_breadthfirst(void);
#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
#define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false))
-#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
/* Generic PCI functions exported to card drivers */
@@ -1630,7 +1629,6 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
#define dev_is_pci(d) (false)
#define dev_is_pf(d) (false)
-#define dev_num_vf(d) (0)
#endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 75e3ea7bda08f..94dd6d53ea9a5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -837,8 +837,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
static inline int rtnl_vfinfo_size(const struct net_device *dev,
u32 ext_filter_mask)
{
- if (dev->dev.parent && dev_is_pci(dev->dev.parent) &&
- (ext_filter_mask & RTEXT_FILTER_VF)) {
+ if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) {
int num_vfs = dev_num_vf(dev->dev.parent);
size_t size = nla_total_size(0);
size += num_vfs *
--
2.11.0
^ permalink raw reply related
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