* Re: [RFC PATCH v2 14/17] net: skb_array: expose peek API
From: Michael S. Tsirkin @ 2017-06-06 3:10 UTC (permalink / raw)
To: John Fastabend; +Cc: eric.dumazet, netdev
In-Reply-To: <20170502154032.9304.50203.stgit@john-Precision-Tower-5810>
On Tue, May 02, 2017 at 08:40:32AM -0700, John Fastabend wrote:
> This adds a peek routine to skb_array.h for use with qdisc.
>
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> ---
> include/linux/skb_array.h | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/include/linux/skb_array.h b/include/linux/skb_array.h
> index f4dfade..33f1f0c 100644
> --- a/include/linux/skb_array.h
> +++ b/include/linux/skb_array.h
> @@ -72,6 +72,11 @@ static inline bool __skb_array_empty(struct skb_array *a)
> return !__ptr_ring_peek(&a->ring);
> }
>
> +static inline struct sk_buff *skb_array_peek(struct skb_array *a)
> +{
> + return __ptr_ring_peek(&a->ring);
> +}
> +
> static inline bool skb_array_empty(struct skb_array *a)
> {
> return ptr_ring_empty(&a->ring);
I think it's better to call this __skb_array_peek: the issue
is that callers must be careful with it's use - see the comment
near __ptr_ring_peek.
--
MST
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2017-06-06 1:49 UTC (permalink / raw)
To: David Miller, Networking
Cc: Linux-Next Mailing List, Linux Kernel Mailing List,
Florian Fainelli, Vivien Didelot
Hi all,
Today's linux-next merge of the net-next tree got a conflict in:
net/dsa/dsa2.c
between commit:
b07ac9894644 ("net: dsa: Fix stale cpu_switch reference after unbind then bind")
from the net tree and commits:
8b0d3ea55587 ("net: dsa: store CPU port pointer in the tree")
937c7df85ce7 ("net: dsa: Pass dsa_port reference to ethtool setup/restore")
from the net-next tree.
I fixed it up (I think (maybe it should be "dst->cpu_dp.ds = NULL"?) -
see below) and can carry the fix as necessary. This is now fixed as far
as linux-next is concerned, but any non trivial conflicts should be
mentioned to your upstream maintainer when your tree is submitted for
merging. You may also want to consider cooperating with the maintainer
of the conflicting tree to minimise any particularly complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc net/dsa/dsa2.c
index 7796580e99ee,cd13bb54a30c..000000000000
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@@ -484,10 -474,8 +474,10 @@@ static void dsa_dst_unapply(struct dsa_
dsa_ds_unapply(dst, ds);
}
- if (dst->cpu_switch) {
- dsa_cpu_port_ethtool_restore(dst->cpu_switch);
- dst->cpu_switch = NULL;
- if (dst->cpu_dp)
++ if (dst->cpu_dp) {
+ dsa_cpu_port_ethtool_restore(dst->cpu_dp);
++ dst->cpu_dp = NULL;
+ }
pr_info("DSA: tree %d unapplied\n", dst->tree);
dst->applied = false;
^ permalink raw reply
* [PATCH] net: ethoc: enable NAPI before poll may be scheduled
From: Max Filippov @ 2017-06-06 1:31 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Florian Fainelli, Thierry Reding, Tobias Klauser,
Max Filippov, stable
ethoc_reset enables device interrupts, ethoc_interrupt may schedule a
NAPI poll before NAPI is enabled in the ethoc_open, which results in
device being unable to send or receive anything until it's closed and
reopened. In case the device is flooded with ingress packets it may be
unable to recover at all.
Move napi_enable above ethoc_reset in the ethoc_open to fix that.
Cc: stable@vger.kernel.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
drivers/net/ethernet/ethoc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 23d8274..4f33660 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -739,6 +739,8 @@ static int ethoc_open(struct net_device *dev)
if (ret)
return ret;
+ napi_enable(&priv->napi);
+
ethoc_init_ring(priv, dev->mem_start);
ethoc_reset(priv);
@@ -754,7 +756,6 @@ static int ethoc_open(struct net_device *dev)
priv->old_duplex = -1;
phy_start(dev->phydev);
- napi_enable(&priv->napi);
if (netif_msg_ifup(priv)) {
dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n",
--
2.1.4
^ permalink raw reply related
* Re: [PATCH v2 2/3] PCI: Enable PCIe Relaxed Ordering if supported
From: Alexander Duyck @ 2017-06-06 0:28 UTC (permalink / raw)
To: Ding Tianhong
Cc: Casey Leedom, Ashok Raj, Bjorn Helgaas, Michael Werner,
Ganesh Goudar, Asit K Mallick, Patrick J Cramer,
Suravee Suthikulpanit, Bob Shaw, h, Amir Ancel, Gabriele Paoloni,
David Laight, Jeff Kirsher, Catalin Marinas, Will Deacon,
Mark Rutland, Robin Murphy, David Miller, linux-arm-kernel
In-Reply-To: <0853b74b-6c0e-68e9-225b-621d833615e4@huawei.com>
On Mon, Jun 5, 2017 at 6:33 AM, Ding Tianhong <dingtianhong@huawei.com> wrote:
>
>
> On 2017/6/4 2:19, Alexander Duyck wrote:
>> On Fri, Jun 2, 2017 at 9:04 PM, Ding Tianhong <dingtianhong@huawei.com> wrote:
>>> The PCIe Device Control Register use the bit 4 to indicate that
>>> whether the device is permitted to enable relaxed ordering or not.
>>> But relaxed ordering is not safe for some platform which could only
>>> use strong write ordering, so devices are allowed (but not required)
>>> to enable relaxed ordering bit by default.
>>>
>>> If a platform support relaxed ordering but does not enable it by
>>> default, enable it in the PCIe configuration. This allows some device
>>> to send TLPs with the relaxed ordering attributes set, which may
>>> improve the performance.
>>>
>>> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>>> ---
>>> drivers/pci/pci.c | 42 ++++++++++++++++++++++++++++++++++++++++++
>>> drivers/pci/probe.c | 11 +++++++++++
>>> include/linux/pci.h | 3 +++
>>> 3 files changed, 56 insertions(+)
>>>
>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>> index b01bd5b..f57a374 100644
>>> --- a/drivers/pci/pci.c
>>> +++ b/drivers/pci/pci.c
>>> @@ -4878,6 +4878,48 @@ int pcie_set_mps(struct pci_dev *dev, int mps)
>>> EXPORT_SYMBOL(pcie_set_mps);
>>>
>>> /**
>>> + * pcie_set_relaxed_ordering - set PCI Express relexed ordering bit
>>> + * @dev: PCI device to query
>>> + *
>>> + * If possible sets relaxed ordering
>>> + */
>>> +int pcie_set_relaxed_ordering(struct pci_dev *dev)
>>> +{
>>> + return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
>>> +}
>>> +EXPORT_SYMBOL(pcie_set_relaxed_ordering);
>>> +
>>> +/**
>>> + * pcie_clear_relaxed_ordering - clear PCI Express relexed ordering bit
>>> + * @dev: PCI device to query
>>> + *
>>> + * If possible clear relaxed ordering
>>> + */
>>> +int pcie_clear_relaxed_ordering(struct pci_dev *dev)
>>> +{
>>> + return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
>>> +}
>>> +EXPORT_SYMBOL(pcie_clear_relaxed_ordering);
>>> +
>>> +/**
>>> + * pcie_get_relaxed_ordering - check PCI Express relexed ordering bit
>>> + * @dev: PCI device to query
>>> + *
>>> + * Returns true if relaxed ordering is been set
>>> + */
>>> +int pcie_get_relaxed_ordering(struct pci_dev *dev)
>>> +{
>>> + u16 v;
>>> +
>>> + pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &v);
>>> +
>>> + return (v & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
>>> +}
>>> +EXPORT_SYMBOL(pcie_get_relaxed_ordering);
>>> +
>>> +/**
>>> + * pcie_set_mps - set PCI Express maximum payload size
>>> +/**
>>> * pcie_get_minimum_link - determine minimum link settings of a PCI device
>>> * @dev: PCI device to query
>>> * @speed: storage for minimum speed
>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>> index 19c8950..aeb22b5 100644
>>> --- a/drivers/pci/probe.c
>>> +++ b/drivers/pci/probe.c
>>> @@ -1701,6 +1701,16 @@ static void pci_configure_extended_tags(struct pci_dev *dev)
>>> PCI_EXP_DEVCTL_EXT_TAG);
>>> }
>>>
>>> +static void pci_configure_relaxed_ordering(struct pci_dev *dev)
>>> +{
>>> + int ret;
>>> +
>>> + if (dev && (dev->dev_flags & PCI_DEV_FLAGS_NO_RELAXED_ORDERING))
>>
>> So there is a minor issue here. The problem is this is only trying to
>> modify relaxed ordering for the device itself. That isn't what we
>> want. What we want is to modify it on all of the upstream port
>> interfaces where there is something the path to the root complex that
>> has an issue. So if the root complex has to set the
>> NO_RELAXED_ORDERING flag on a root port, all of the interfaces below
>> it that would be pushing traffic toward it should not have the relaxed
>> ordering bit set.
>>
>> Also I am pretty sure this is a PCIe capability, not a PCI capability.
>> You probably need to make sure you code is making this distinction
>> which I don't know if it currently is. If you need an example of the
>> kind of checks I am suggesting just take a look at
>> pcie_configure_mps(). It is verifying the function is PCIe before
>> attempting to make any updates. In your case you will probably also
>> need to make sure there is a bus for you to walk up the chain of.
>> Otherwise this shouldn't apply.
>>
>>
>>> + pcie_set_relaxed_ordering(dev);
>>> + else
>>> + pcie_clear_relaxed_ordering(dev);
>>> +}
>>
>> Also I am not a fan of the way this is handled currently. If you don't
>> have relaxed ordering set then you don't need to do anything else, if
>> you do have it set but there is no bus to walk up you shouldn't change
>> it, and if there is a bus to walk up and you find that the root
>> complex on that bus has the NO_RELAXED_ORDERING set you should clear
>> it. Right now this code seems to be enabling relaxed ordering if the
>> NO_RELAXED_ORDERING flag is set.
>>
>
> Hi Alexander:
>
> I reconsidered your suggestion and found I miss something here,
> decide to modify the configure police as your solution, I think
> it is close to our goal.
>
> Thanks
> Ding
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 19c8950..68dee05 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1701,6 +1701,45 @@ static void pci_configure_extended_tags(struct pci_dev *dev)
> PCI_EXP_DEVCTL_EXT_TAG);
> }
>
> +static int pcie_clearing_relaxed_ordering(struct pci_dev *dev, void *data)
> +{
> + int origin_ero;
> +
> + if (!pci_is_pcie(dev))
> + return 0;
> +
> + origin_ero = pcie_get_relaxed_ordering(dev);
> +
> + /* If the releaxed ordering enable bit is not set, do nothing. */
> + if (!origin_ero)
> + return 0;
> +
> + pcie_clear_relaxed_ordering(dev);
> +
> + dev_info(&dev->dev, "Disable Relaxed Ordering\n");
> +
> + return 0;
> +}
> +
> +static void pci_configure_relaxed_ordering(struct pci_dev *dev)
> +{
> + int origin_ero;
> +
> + if (!pci_is_pcie(dev))
> + return;
> +
> + origin_ero = pcie_get_relaxed_ordering(dev);
> + /* If the releaxed ordering enable bit is not set, do nothing. */
> + if (!origin_ero)
> + return;
> +
> + if (dev->dev_flags & PCI_DEV_FLAGS_NO_RELAXED_ORDERING) {
> + pcie_clear_relaxed_ordering(dev);
> + pci_walk_bus(dev->bus, pcie_clearing_relaxed_ordering, NULL);
> + dev_info(&dev->dev, "Disable Relaxed Ordering\n");
> + }
> +}
> +
This is kind of backwards from what I was thinking. Basically what I
would like to see is at probe time we should work our way up the PCIe
buses checking to see if any device has
PCI_DEV_FLAGS_NO_RELAXED_ORDERING set. The assumption is if we can't
use relaxed ordering with the downstream facing port we probably
shouldn't be enabling it on our upstream facing port. We don't want to
be writing to other devices and such since we don't know what they
need, we will only know what our device needs and if the root complex
reports that it can't support relaxed ordering we should disable it
for the device we are initializing and move on.
You might use pcie_get_minimum_link as an example of what I am
thinking. Basically what we should do is add a function that will
return true if any of the devices above us do not support relaxed
ordering, otherwise return false. Then based on that result if we get
a return that indicates that relaxed ordering is not supported we
should update our device to disable relaxed ordering. If the device
above us doesn't exist, or isn't PCIe we should just exit and skip
updating relaxed ordering since we are probably running in a guest.
> static void pci_configure_device(struct pci_dev *dev)
> {
> struct hotplug_params hpp;
> @@ -1708,6 +1747,7 @@ static void pci_configure_device(struct pci_dev *dev)
>
> pci_configure_mps(dev);
> pci_configure_extended_tags(dev);
> + pci_configure_relaxed_ordering(dev);
>
> memset(&hpp, 0, sizeof(hpp));
> ret = pci_get_hp_params(dev, &hpp);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
>
>
>
>>> +
>>> static void pci_configure_device(struct pci_dev *dev)
>>> {
>>> struct hotplug_params hpp;
>>> @@ -1708,6 +1718,7 @@ static void pci_configure_device(struct pci_dev *dev)
>>>
>>> pci_configure_mps(dev);
>>> pci_configure_extended_tags(dev);
>>> + pci_configure_relaxed_ordering(dev);
>>>
>>> memset(&hpp, 0, sizeof(hpp));
>>> ret = pci_get_hp_params(dev, &hpp);
>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>> index e1e8428..84bd6af 100644
>>> --- a/include/linux/pci.h
>>> +++ b/include/linux/pci.h
>>> @@ -1105,6 +1105,9 @@ int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
>>> void pci_pme_wakeup_bus(struct pci_bus *bus);
>>> void pci_d3cold_enable(struct pci_dev *dev);
>>> void pci_d3cold_disable(struct pci_dev *dev);
>>> +int pcie_set_relaxed_ordering(struct pci_dev *dev);
>>> +int pcie_clear_relaxed_ordering(struct pci_dev *dev);
>>> +int pcie_get_relaxed_ordering(struct pci_dev *dev);
>>>
>>> static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
>>> bool enable)
>>> --
>>> 1.9.0
>>>
>>>
>>
>> .
>>
>
^ permalink raw reply
* Re: [PATCH 2/2] xfrm: add UDP encapsulation port in migrate message
From: Richard Guy Briggs @ 2017-06-06 0:05 UTC (permalink / raw)
To: Antony Antony; +Cc: netdev, Steffen Klassert, Herbert Xu, David S . Miller
In-Reply-To: <20170605215625.11043-3-antony@phenome.org>
On 2017-06-05 23:56, Antony Antony wrote:
> Add XFRMA_ENCAP, UDP encapsulation port, to km_migrate announcement
> to userland. Only add if XFRMA_ENCAP was in user migrate request.
>
> Signed-off-by: Antony Antony <antony@phenome.org>
Looks reasonable to me.
Reviewed-by: Richard Guy Briggs <rgb@tricolour.ca>
> ---
> include/net/xfrm.h | 5 +++--
> net/key/af_key.c | 3 ++-
> net/xfrm/xfrm_policy.c | 2 +-
> net/xfrm/xfrm_state.c | 5 +++--
> net/xfrm/xfrm_user.c | 23 +++++++++++++++++------
> 5 files changed, 26 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> index df98463..9fb75fb 100644
> --- a/include/net/xfrm.h
> +++ b/include/net/xfrm.h
> @@ -631,7 +631,8 @@ struct xfrm_mgr {
> u8 dir, u8 type,
> const struct xfrm_migrate *m,
> int num_bundles,
> - const struct xfrm_kmaddress *k);
> + const struct xfrm_kmaddress *k,
> + struct xfrm_encap_tmpl *encap);
> bool (*is_alive)(const struct km_event *c);
> };
>
> @@ -1675,7 +1676,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
> #ifdef CONFIG_XFRM_MIGRATE
> int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> const struct xfrm_migrate *m, int num_bundles,
> - const struct xfrm_kmaddress *k);
> + const struct xfrm_kmaddress *k, struct xfrm_encap_tmpl *encap);
> struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
> struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
> struct xfrm_migrate *m,
> diff --git a/net/key/af_key.c b/net/key/af_key.c
> index 56df9fb..2ad2286 100644
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -3508,7 +3508,8 @@ static int set_ipsecrequest(struct sk_buff *skb,
> #ifdef CONFIG_NET_KEY_MIGRATE
> static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> const struct xfrm_migrate *m, int num_bundles,
> - const struct xfrm_kmaddress *k)
> + const struct xfrm_kmaddress *k,
> + struct xfrm_encap_tmpl *encap)
> {
> int i;
> int sasize_sel;
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index eaecfa4..7152147 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -3337,7 +3337,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> }
>
> /* Stage 5 - announce */
> - km_migrate(sel, dir, type, m, num_migrate, k);
> + km_migrate(sel, dir, type, m, num_migrate, k, encap);
>
> xfrm_pol_put(pol);
>
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index ae6206b..d6220f7 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -1966,7 +1966,7 @@ EXPORT_SYMBOL(km_policy_expired);
> #ifdef CONFIG_XFRM_MIGRATE
> int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> const struct xfrm_migrate *m, int num_migrate,
> - const struct xfrm_kmaddress *k)
> + const struct xfrm_kmaddress *k, struct xfrm_encap_tmpl *encap)
> {
> int err = -EINVAL;
> int ret;
> @@ -1975,7 +1975,8 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> rcu_read_lock();
> list_for_each_entry_rcu(km, &xfrm_km_list, list) {
> if (km->migrate) {
> - ret = km->migrate(sel, dir, type, m, num_migrate, k);
> + ret = km->migrate(sel, dir, type, m, num_migrate, k,
> + encap);
> if (!ret)
> err = ret;
> }
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index fb98892..8c54484 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -2314,17 +2314,20 @@ static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff
> return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk);
> }
>
> -static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
> +static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma,
> + int with_encp)
> {
> return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
> + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
> + + (with_encp ? nla_total_size(sizeof(struct xfrm_encap_tmpl)) : 0)
> + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
> + userpolicy_type_attrsize();
> }
>
> static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
> int num_migrate, const struct xfrm_kmaddress *k,
> - const struct xfrm_selector *sel, u8 dir, u8 type)
> + const struct xfrm_selector *sel,
> + struct xfrm_encap_tmpl *encap, u8 dir, u8 type)
> {
> const struct xfrm_migrate *mp;
> struct xfrm_userpolicy_id *pol_id;
> @@ -2346,6 +2349,11 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
> if (err)
> goto out_cancel;
> }
> + if (encap) {
> + err = nla_put(skb, XFRMA_ENCAP, sizeof(*encap), encap);
> + if (err)
> + goto out_cancel;
> + }
> err = copy_to_user_policy_type(type, skb);
> if (err)
> goto out_cancel;
> @@ -2365,17 +2373,19 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
>
> static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> const struct xfrm_migrate *m, int num_migrate,
> - const struct xfrm_kmaddress *k)
> + const struct xfrm_kmaddress *k,
> + struct xfrm_encap_tmpl *encap)
> {
> struct net *net = &init_net;
> struct sk_buff *skb;
>
> - skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
> + skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k, !!encap),
> + GFP_ATOMIC);
> if (skb == NULL)
> return -ENOMEM;
>
> /* build migrate */
> - if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
> + if (build_migrate(skb, m, num_migrate, k, sel, encap, dir, type) < 0)
> BUG();
>
> return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE);
> @@ -2383,7 +2393,8 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> #else
> static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> const struct xfrm_migrate *m, int num_migrate,
> - const struct xfrm_kmaddress *k)
> + const struct xfrm_kmaddress *k,
> + struct xfrm_encap_tmpl *encap)
> {
> return -ENOPROTOOPT;
> }
> --
> 2.9.3
slainte mhath, RGB
^ permalink raw reply
* Re: [PATCH 1/2] xfrm: extend MIGRATE with UDP encapsulation port
From: Richard Guy Briggs @ 2017-06-06 0:05 UTC (permalink / raw)
To: Antony Antony; +Cc: netdev, Steffen Klassert, Herbert Xu, David S . Miller
In-Reply-To: <20170605215625.11043-2-antony@phenome.org>
On 2017-06-05 23:56, Antony Antony wrote:
> Add UDP encapsulation port to XFRM_MSG_MIGRATE using an optional
> netlink attribute XFRMA_ENCAP.
>
> The devices that support IKE MOBIKE extension (RFC-4555 Section 3.8)
> could go to sleep for a few minutes and wake up. When it wake up the
> NAT mapping could have expired, the device send a MOBIKE UPDATE_SA
> message to migrate the IPsec SA. The change could be a change UDP
> encapsulation port, IP address, or both.
>
> Reported-by: Paul Wouters <pwouters@redhat.com>
> Signed-off-by: Antony Antony <antony@phenome.org>
Looks reasonable to me.
Reviewed-by: Richard Guy Briggs <rgb@tricolour.ca>
> ---
> include/net/xfrm.h | 6 ++++--
> net/key/af_key.c | 2 +-
> net/xfrm/xfrm_policy.c | 11 ++++-------
> net/xfrm/xfrm_state.c | 18 +++++++++++++-----
> net/xfrm/xfrm_user.c | 14 ++++++++++++--
> 5 files changed, 34 insertions(+), 17 deletions(-)
>
> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> index 7e7e2b0..df98463 100644
> --- a/include/net/xfrm.h
> +++ b/include/net/xfrm.h
> @@ -1678,10 +1678,12 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> const struct xfrm_kmaddress *k);
> struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
> struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
> - struct xfrm_migrate *m);
> + struct xfrm_migrate *m,
> + struct xfrm_encap_tmpl *encap);
> int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> struct xfrm_migrate *m, int num_bundles,
> - struct xfrm_kmaddress *k, struct net *net);
> + struct xfrm_kmaddress *k, struct net *net,
> + struct xfrm_encap_tmpl *encap);
> #endif
>
> int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
> diff --git a/net/key/af_key.c b/net/key/af_key.c
> index 512dc43..56df9fb 100644
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -2602,7 +2602,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
> }
>
> return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
> - kma ? &k : NULL, net);
> + kma ? &k : NULL, net, NULL);
>
> out:
> return err;
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index ed4e52d..eaecfa4 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -3268,11 +3268,6 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
> return -EINVAL;
>
> for (i = 0; i < num_migrate; i++) {
> - if (xfrm_addr_equal(&m[i].old_daddr, &m[i].new_daddr,
> - m[i].old_family) &&
> - xfrm_addr_equal(&m[i].old_saddr, &m[i].new_saddr,
> - m[i].old_family))
> - return -EINVAL;
> if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) ||
> xfrm_addr_any(&m[i].new_saddr, m[i].new_family))
> return -EINVAL;
> @@ -3296,7 +3291,8 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
>
> int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> struct xfrm_migrate *m, int num_migrate,
> - struct xfrm_kmaddress *k, struct net *net)
> + struct xfrm_kmaddress *k, struct net *net,
> + struct xfrm_encap_tmpl *encap)
> {
> int i, err, nx_cur = 0, nx_new = 0;
> struct xfrm_policy *pol = NULL;
> @@ -3319,7 +3315,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
> if ((x = xfrm_migrate_state_find(mp, net))) {
> x_cur[nx_cur] = x;
> nx_cur++;
> - if ((xc = xfrm_state_migrate(x, mp))) {
> + xc = xfrm_state_migrate(x, mp, encap);
> + if (xc) {
> x_new[nx_new] = xc;
> nx_new++;
> } else {
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 2e291bc..ae6206b 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -1309,7 +1309,8 @@ int xfrm_state_add(struct xfrm_state *x)
> EXPORT_SYMBOL(xfrm_state_add);
>
> #ifdef CONFIG_XFRM_MIGRATE
> -static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
> +static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> + struct xfrm_encap_tmpl *encap)
> {
> struct net *net = xs_net(orig);
> struct xfrm_state *x = xfrm_state_alloc(net);
> @@ -1351,8 +1352,14 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
> }
> x->props.calgo = orig->props.calgo;
>
> - if (orig->encap) {
> - x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
> + if (encap || orig->encap) {
> + if (encap)
> + x->encap = kmemdup(encap, sizeof(*x->encap),
> + GFP_KERNEL);
> + else
> + x->encap = kmemdup(orig->encap, sizeof(*x->encap),
> + GFP_KERNEL);
> +
> if (!x->encap)
> goto error;
> }
> @@ -1442,11 +1449,12 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
> EXPORT_SYMBOL(xfrm_migrate_state_find);
>
> struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
> - struct xfrm_migrate *m)
> + struct xfrm_migrate *m,
> + struct xfrm_encap_tmpl *encap)
> {
> struct xfrm_state *xc;
>
> - xc = xfrm_state_clone(x);
> + xc = xfrm_state_clone(x, encap);
> if (!xc)
> return NULL;
>
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index 38614df..fb98892 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -2243,6 +2243,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
> int err;
> int n = 0;
> struct net *net = sock_net(skb->sk);
> + struct xfrm_encap_tmpl *encap = NULL;
>
> if (attrs[XFRMA_MIGRATE] == NULL)
> return -EINVAL;
> @@ -2260,9 +2261,18 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
> if (!n)
> return 0;
>
> - xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net);
> + if (attrs[XFRMA_ENCAP]) {
> + encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
> + sizeof(*encap), GFP_KERNEL);
> + if (!encap)
> + return 0;
> + }
>
> - return 0;
> + err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap);
> +
> + kfree(encap);
> +
> + return err;
> }
> #else
> static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
> --
> 2.9.3
slainte mhath, RGB
^ permalink raw reply
* [PATCH net-next 16/16] nfp: advertise support for NFD ABI 0.5
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
NFD ABI 0.5 is equivalent to NFD ABI 3.0 but requires that the
driver checks the APP id symbol and makes sure it can support
given app. Most advanced apps will likely require control vNIC
(ability to exchange control messages between the driver and
app FW). Detailed app version checking and capability exchange
is left to app-specific code.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 2 +-
drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index db12700b5afc..5f27703060c2 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -749,7 +749,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
nfp_warn(pf->cpp, "OBSOLETE Firmware detected - VF isolation not available\n");
} else {
switch (fw_ver.major) {
- case 1 ... 4:
+ case 1 ... 5:
stride = 4;
break;
default:
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
index 0bf3b0febd07..c879626e035b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
@@ -161,7 +161,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
dev_warn(&pdev->dev, "OBSOLETE Firmware detected - VF isolation not available\n");
} else {
switch (fw_ver.major) {
- case 1 ... 4:
+ case 1 ... 5:
stride = 4;
tx_bar_no = NFP_NET_Q0_BAR;
rx_bar_no = tx_bar_no;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 10/16] nfp: make vNIC ctrl memory mapping function reusable
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
We will soon need to map control vNIC PCI memory as well as data vNIC
memory. Make the function for mapping areas pointed to by an RTsym
reusable.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 55 ++++++++++++-----------
1 file changed, 28 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index dd2a99fca716..3644b12d93db 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -248,40 +248,37 @@ nfp_net_pf_total_qcs(struct nfp_pf *pf, void __iomem *ctrl_bar,
return max_qc - min_qc;
}
-static u8 __iomem *nfp_net_pf_map_ctrl_bar(struct nfp_pf *pf)
+static u8 __iomem *
+nfp_net_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
+ unsigned int min_size, struct nfp_cpp_area **area)
{
- const struct nfp_rtsym *ctrl_sym;
- u8 __iomem *ctrl_bar;
+ const struct nfp_rtsym *sym;
char pf_symbol[256];
+ u8 __iomem *mem;
- snprintf(pf_symbol, sizeof(pf_symbol), "_pf%u_net_bar0",
+ snprintf(pf_symbol, sizeof(pf_symbol), sym_fmt,
nfp_cppcore_pcie_unit(pf->cpp));
- ctrl_sym = nfp_rtsym_lookup(pf->cpp, pf_symbol);
- if (!ctrl_sym) {
- dev_err(&pf->pdev->dev,
- "Failed to find PF BAR0 symbol %s\n", pf_symbol);
- return NULL;
+ sym = nfp_rtsym_lookup(pf->cpp, pf_symbol);
+ if (!sym) {
+ nfp_err(pf->cpp, "Failed to find PF symbol %s\n", pf_symbol);
+ return (u8 __iomem *)ERR_PTR(-ENOENT);
}
- if (ctrl_sym->size < pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE) {
- dev_err(&pf->pdev->dev,
- "PF BAR0 too small to contain %d vNICs\n",
- pf->max_data_vnics);
- return NULL;
+ if (sym->size < min_size) {
+ nfp_err(pf->cpp, "PF symbol %s too small\n", pf_symbol);
+ return (u8 __iomem *)ERR_PTR(-EINVAL);
}
- ctrl_bar = nfp_net_map_area(pf->cpp, "net.ctrl",
- ctrl_sym->domain, ctrl_sym->target,
- ctrl_sym->addr, ctrl_sym->size,
- &pf->data_vnic_bar);
- if (IS_ERR(ctrl_bar)) {
- dev_err(&pf->pdev->dev, "Failed to map PF BAR0: %ld\n",
- PTR_ERR(ctrl_bar));
- return NULL;
+ mem = nfp_net_map_area(pf->cpp, name, sym->domain, sym->target,
+ sym->addr, sym->size, area);
+ if (IS_ERR(mem)) {
+ nfp_err(pf->cpp, "Failed to map PF symbol %s: %ld\n",
+ pf_symbol, PTR_ERR(mem));
+ return mem;
}
- return ctrl_bar;
+ return mem;
}
static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn)
@@ -662,10 +659,10 @@ int nfp_net_refresh_eth_port(struct nfp_port *port)
*/
int nfp_net_pci_probe(struct nfp_pf *pf)
{
+ u32 ctrl_bar_sz, tx_area_sz, rx_area_sz;
u8 __iomem *ctrl_bar, *tx_bar, *rx_bar;
u32 total_tx_qcs, total_rx_qcs;
struct nfp_net_fw_version fw_ver;
- u32 tx_area_sz, rx_area_sz;
u32 start_q;
int stride;
int err;
@@ -685,9 +682,13 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
goto err_unlock;
}
- ctrl_bar = nfp_net_pf_map_ctrl_bar(pf);
- if (!ctrl_bar) {
- err = pf->fw_loaded ? -EINVAL : -EPROBE_DEFER;
+ ctrl_bar_sz = pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE;
+ ctrl_bar = nfp_net_pf_map_rtsym(pf, "net.ctrl", "_pf%d_net_bar0",
+ ctrl_bar_sz, &pf->data_vnic_bar);
+ if (IS_ERR(ctrl_bar)) {
+ err = PTR_ERR(ctrl_bar);
+ if (!pf->fw_loaded && err == -ENOENT)
+ err = -EPROBE_DEFER;
goto err_unlock;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 15/16] nfp: create control vNICs and wire up rx/tx
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
When driver encounters an nfp_app which has a control message handler
defined, allocate a control vNIC. This control channel will be used
to exchange data with the application FW such as flow table programming,
statistics and global datapath control.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_app.c | 18 +++
drivers/net/ethernet/netronome/nfp/nfp_app.h | 44 ++++++++
drivers/net/ethernet/netronome/nfp/nfp_main.h | 7 ++
.../net/ethernet/netronome/nfp/nfp_net_common.c | 2 +-
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 121 ++++++++++++++++++---
5 files changed, 177 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c
index cea2090cf063..de07517da1bd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c
@@ -31,6 +31,7 @@
* SOFTWARE.
*/
+#include <linux/skbuff.h>
#include <linux/slab.h>
#include "nfpcore/nfp_cpp.h"
@@ -42,6 +43,23 @@ static const struct nfp_app_type *apps[] = {
&app_bpf,
};
+struct sk_buff *nfp_app_ctrl_msg_alloc(struct nfp_app *app, unsigned int size)
+{
+ struct sk_buff *skb;
+
+ if (nfp_app_ctrl_has_meta(app))
+ size += 8;
+
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ return NULL;
+
+ if (nfp_app_ctrl_has_meta(app))
+ skb_reserve(skb, 8);
+
+ return skb;
+}
+
struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id)
{
struct nfp_app *app;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index f6091ad0a9a9..3fbf68f8577c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -37,6 +37,7 @@
struct bpf_prog;
struct net_device;
struct pci_dev;
+struct sk_buff;
struct tc_to_netdev;
struct sk_buff;
struct nfp_app;
@@ -63,6 +64,9 @@ extern const struct nfp_app_type app_bpf;
* @extra_cap: extra capabilities string
* @vnic_init: init vNICs (assign port types, etc.)
* @vnic_clean: clean up app's vNIC state
+ * @start: start application logic
+ * @stop: stop application logic
+ * @ctrl_msg_rx: control message handler
* @setup_tc: setup TC ndo
* @tc_busy: TC HW offload busy (rules loaded)
* @xdp_offload: offload an XDP program
@@ -81,6 +85,11 @@ struct nfp_app_type {
unsigned int id);
void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn);
+ int (*start)(struct nfp_app *app);
+ void (*stop)(struct nfp_app *app);
+
+ void (*ctrl_msg_rx)(struct nfp_app *app, struct sk_buff *skb);
+
int (*setup_tc)(struct nfp_app *app, struct net_device *netdev,
u32 handle, __be16 proto, struct tc_to_netdev *tc);
bool (*tc_busy)(struct nfp_app *app, struct nfp_net *nn);
@@ -93,6 +102,7 @@ struct nfp_app_type {
* @pdev: backpointer to PCI device
* @pf: backpointer to NFP PF structure
* @cpp: pointer to the CPP handle
+ * @ctrl: pointer to ctrl vNIC struct
* @type: pointer to const application ops and info
*/
struct nfp_app {
@@ -100,6 +110,8 @@ struct nfp_app {
struct nfp_pf *pf;
struct nfp_cpp *cpp;
+ struct nfp_net *ctrl;
+
const struct nfp_app_type *type;
};
@@ -124,6 +136,21 @@ static inline void nfp_app_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
app->type->vnic_clean(app, nn);
}
+static inline int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl)
+{
+ app->ctrl = ctrl;
+ if (!app->type->start)
+ return 0;
+ return app->type->start(app);
+}
+
+static inline void nfp_app_stop(struct nfp_app *app)
+{
+ if (!app->type->stop)
+ return;
+ app->type->stop(app);
+}
+
static inline const char *nfp_app_name(struct nfp_app *app)
{
if (!app)
@@ -131,6 +158,11 @@ static inline const char *nfp_app_name(struct nfp_app *app)
return app->type->name;
}
+static inline bool nfp_app_needs_ctrl_vnic(struct nfp_app *app)
+{
+ return app && app->type->ctrl_msg_rx;
+}
+
static inline bool nfp_app_ctrl_has_meta(struct nfp_app *app)
{
return app->type->ctrl_has_meta;
@@ -174,6 +206,18 @@ static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
return app->type->xdp_offload(app, nn, prog);
}
+static inline bool nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb)
+{
+ return nfp_ctrl_tx(app->ctrl, skb);
+}
+
+static inline void nfp_app_ctrl_rx(struct nfp_app *app, struct sk_buff *skb)
+{
+ app->type->ctrl_msg_rx(app, skb);
+}
+
+struct sk_buff *nfp_app_ctrl_msg_alloc(struct nfp_app *app, unsigned int size);
+
struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id);
void nfp_app_free(struct nfp_app *app);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h
index 66b1e1490805..37832853b0b3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h
@@ -63,11 +63,13 @@ struct nfp_nsp_identify;
* @cpp: Pointer to the CPP handle
* @app: Pointer to the APP handle
* @data_vnic_bar: Pointer to the CPP area for the data vNICs' BARs
+ * @ctrl_vnic_bar: Pointer to the CPP area for the ctrl vNIC's BAR
* @qc_area: Pointer to the CPP area for the queues
* @irq_entries: Array of MSI-X entries for all vNICs
* @limit_vfs: Number of VFs supported by firmware (~0 for PCI limit)
* @num_vfs: Number of SR-IOV VFs enabled
* @fw_loaded: Is the firmware loaded?
+ * @ctrl_vnic: Pointer to the control vNIC if available
* @eth_tbl: NSP ETH table
* @nspi: NSP identification info
* @hwmon_dev: pointer to hwmon device
@@ -87,6 +89,7 @@ struct nfp_pf {
struct nfp_app *app;
struct nfp_cpp_area *data_vnic_bar;
+ struct nfp_cpp_area *ctrl_vnic_bar;
struct nfp_cpp_area *qc_area;
struct msix_entry *irq_entries;
@@ -96,6 +99,8 @@ struct nfp_pf {
bool fw_loaded;
+ struct nfp_net *ctrl_vnic;
+
struct nfp_eth_table *eth_tbl;
struct nfp_nsp_identify *nspi;
@@ -127,4 +132,6 @@ nfp_net_find_port(struct nfp_eth_table *eth_tbl, unsigned int id);
void
nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_cpp *cpp, unsigned int id);
+bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb);
+
#endif /* NFP_MAIN_H */
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 59f1764242a0..4f0df63de626 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1950,7 +1950,7 @@ nfp_ctrl_rx_one(struct nfp_net *nn, struct nfp_net_dp *dp,
skb_reserve(skb, pkt_off);
skb_put(skb, pkt_len);
- dev_kfree_skb_any(skb);
+ nfp_app_ctrl_rx(nn->app, skb);
return true;
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 362dca38223b..db12700b5afc 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -266,12 +266,11 @@ static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn)
static void nfp_net_pf_free_vnics(struct nfp_pf *pf)
{
- struct nfp_net *nn;
+ struct nfp_net *nn, *next;
- while (!list_empty(&pf->vnics)) {
- nn = list_first_entry(&pf->vnics, struct nfp_net, vnic_list);
- nfp_net_pf_free_vnic(pf, nn);
- }
+ list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list)
+ if (nfp_net_is_data_vnic(nn))
+ nfp_net_pf_free_vnic(pf, nn);
}
static struct nfp_net *
@@ -302,10 +301,12 @@ nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
nn->stride_rx = stride;
nn->stride_tx = stride;
- err = nfp_app_vnic_init(pf->app, nn, eth_id);
- if (err) {
- nfp_net_free(nn);
- return ERR_PTR(err);
+ if (needs_netdev) {
+ err = nfp_app_vnic_init(pf->app, nn, eth_id);
+ if (err) {
+ nfp_net_free(nn);
+ return ERR_PTR(err);
+ }
}
pf->num_vnics++;
@@ -446,6 +447,8 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf)
/* Finish vNIC init and register */
id = 0;
list_for_each_entry(nn, &pf->vnics, vnic_list) {
+ if (!nfp_net_is_data_vnic(nn))
+ continue;
err = nfp_net_pf_init_vnic(pf, nn, id);
if (err)
goto err_prev_deinit;
@@ -457,12 +460,15 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf)
err_prev_deinit:
list_for_each_entry_continue_reverse(nn, &pf->vnics, vnic_list)
- nfp_net_pf_clean_vnic(pf, nn);
+ if (nfp_net_is_data_vnic(nn))
+ nfp_net_pf_clean_vnic(pf, nn);
return err;
}
-static int nfp_net_pf_app_init(struct nfp_pf *pf)
+static int
+nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
{
+ u8 __iomem *ctrl_bar;
int err;
pf->app = nfp_app_alloc(pf, nfp_net_pf_get_app_id(pf));
@@ -473,8 +479,28 @@ static int nfp_net_pf_app_init(struct nfp_pf *pf)
if (err)
goto err_free;
+ if (!nfp_app_needs_ctrl_vnic(pf->app))
+ return 0;
+
+ ctrl_bar = nfp_net_pf_map_rtsym(pf, "net.ctrl", "_pf%u_net_ctrl_bar",
+ NFP_PF_CSR_SLICE_SIZE,
+ &pf->ctrl_vnic_bar);
+ if (IS_ERR(ctrl_bar)) {
+ err = PTR_ERR(ctrl_bar);
+ goto err_free;
+ }
+
+ pf->ctrl_vnic = nfp_net_pf_alloc_vnic(pf, false, ctrl_bar, qc_bar,
+ stride, 0);
+ if (IS_ERR(pf->ctrl_vnic)) {
+ err = PTR_ERR(pf->ctrl_vnic);
+ goto err_unmap;
+ }
+
return 0;
+err_unmap:
+ nfp_cpp_area_release_free(pf->ctrl_vnic_bar);
err_free:
nfp_app_free(pf->app);
return err;
@@ -482,12 +508,72 @@ static int nfp_net_pf_app_init(struct nfp_pf *pf)
static void nfp_net_pf_app_clean(struct nfp_pf *pf)
{
+ if (pf->ctrl_vnic) {
+ nfp_net_pf_free_vnic(pf, pf->ctrl_vnic);
+ nfp_cpp_area_release_free(pf->ctrl_vnic_bar);
+ }
nfp_app_free(pf->app);
pf->app = NULL;
}
+static int nfp_net_pf_app_start_ctrl(struct nfp_pf *pf)
+{
+ int err;
+
+ if (!pf->ctrl_vnic)
+ return 0;
+ err = nfp_net_pf_init_vnic(pf, pf->ctrl_vnic, 0);
+ if (err)
+ return err;
+
+ err = nfp_ctrl_open(pf->ctrl_vnic);
+ if (err)
+ goto err_clean_ctrl;
+
+ return 0;
+
+err_clean_ctrl:
+ nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic);
+ return err;
+}
+
+static void nfp_net_pf_app_stop_ctrl(struct nfp_pf *pf)
+{
+ if (!pf->ctrl_vnic)
+ return;
+ nfp_ctrl_close(pf->ctrl_vnic);
+ nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic);
+}
+
+static int nfp_net_pf_app_start(struct nfp_pf *pf)
+{
+ int err;
+
+ err = nfp_net_pf_app_start_ctrl(pf);
+ if (err)
+ return err;
+
+ err = nfp_app_start(pf->app, pf->ctrl_vnic);
+ if (err)
+ goto err_ctrl_stop;
+
+ return 0;
+
+err_ctrl_stop:
+ nfp_net_pf_app_stop_ctrl(pf);
+ return err;
+}
+
+static void nfp_net_pf_app_stop(struct nfp_pf *pf)
+{
+ nfp_app_stop(pf->app);
+ nfp_net_pf_app_stop_ctrl(pf);
+}
+
static void nfp_net_pci_remove_finish(struct nfp_pf *pf)
{
+ nfp_net_pf_app_stop(pf);
+ /* stop app first, to avoid double free of ctrl vNIC's ddir */
nfp_net_debugfs_dir_clean(&pf->ddir);
nfp_net_pf_free_irqs(pf);
@@ -685,7 +771,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
goto err_ctrl_unmap;
}
- err = nfp_net_pf_app_init(pf);
+ err = nfp_net_pf_app_init(pf, qc_bar, stride);
if (err)
goto err_unmap_qc;
@@ -700,14 +786,20 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
if (err)
goto err_free_vnics;
- err = nfp_net_pf_init_vnics(pf);
+ err = nfp_net_pf_app_start(pf);
if (err)
goto err_free_irqs;
+ err = nfp_net_pf_init_vnics(pf);
+ if (err)
+ goto err_stop_app;
+
mutex_unlock(&pf->lock);
return 0;
+err_stop_app:
+ nfp_net_pf_app_stop(pf);
err_free_irqs:
nfp_net_pf_free_irqs(pf);
err_free_vnics:
@@ -733,7 +825,8 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
goto out;
list_for_each_entry(nn, &pf->vnics, vnic_list)
- nfp_net_pf_clean_vnic(pf, nn);
+ if (nfp_net_is_data_vnic(nn))
+ nfp_net_pf_clean_vnic(pf, nn);
nfp_net_pf_free_vnics(pf);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 09/16] nfp: add control vNIC datapath
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
Since control vNICs don't have a netdev, they can't use napi and
queuing stack provides. Add simple tasklet-based data receive
and send of control messages with queuing on a skb_list.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_app.h | 11 +
drivers/net/ethernet/netronome/nfp/nfp_net.h | 17 +-
.../net/ethernet/netronome/nfp/nfp_net_common.c | 323 ++++++++++++++++++++-
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 3 +
4 files changed, 345 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index 13efdefffa1a..f6091ad0a9a9 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -38,6 +38,7 @@ struct bpf_prog;
struct net_device;
struct pci_dev;
struct tc_to_netdev;
+struct sk_buff;
struct nfp_app;
struct nfp_cpp;
struct nfp_pf;
@@ -55,6 +56,7 @@ extern const struct nfp_app_type app_bpf;
* struct nfp_app_type - application definition
* @id: application ID
* @name: application name
+ * @ctrl_has_meta: control messages have prepend of type:5/port:CTRL
*
* Callbacks
* @init: perform basic app checks
@@ -69,6 +71,8 @@ struct nfp_app_type {
enum nfp_app_id id;
const char *name;
+ bool ctrl_has_meta;
+
int (*init)(struct nfp_app *app);
const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn);
@@ -99,6 +103,8 @@ struct nfp_app {
const struct nfp_app_type *type;
};
+bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb);
+
static inline int nfp_app_init(struct nfp_app *app)
{
if (!app->type->init)
@@ -125,6 +131,11 @@ static inline const char *nfp_app_name(struct nfp_app *app)
return app->type->name;
}
+static inline bool nfp_app_ctrl_has_meta(struct nfp_app *app)
+{
+ return app->type->ctrl_has_meta;
+}
+
static inline const char *nfp_app_extra_cap(struct nfp_app *app,
struct nfp_net *nn)
{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 6b21c4d0ccfa..eb849d26f4dd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -405,7 +405,14 @@ struct nfp_net_rx_ring {
*/
struct nfp_net_r_vector {
struct nfp_net *nfp_net;
- struct napi_struct napi;
+ union {
+ struct napi_struct napi;
+ struct {
+ struct tasklet_struct tasklet;
+ struct sk_buff_head queue;
+ struct spinlock lock;
+ };
+ };
struct nfp_net_tx_ring *tx_ring;
struct nfp_net_rx_ring *rx_ring;
@@ -816,6 +823,11 @@ static inline bool nfp_net_running(struct nfp_net *nn)
return nn->dp.ctrl & NFP_NET_CFG_CTRL_ENABLE;
}
+static inline const char *nfp_net_name(struct nfp_net *nn)
+{
+ return nn->dp.netdev ? nn->dp.netdev->name : "ctrl";
+}
+
/* Globals */
extern const char nfp_driver_version[];
@@ -838,6 +850,9 @@ void nfp_net_free(struct nfp_net *nn);
int nfp_net_init(struct nfp_net *nn);
void nfp_net_clean(struct nfp_net *nn);
+int nfp_ctrl_open(struct nfp_net *nn);
+void nfp_ctrl_close(struct nfp_net *nn);
+
void nfp_net_set_ethtool_ops(struct net_device *netdev);
void nfp_net_info(struct nfp_net *nn);
int nfp_net_reconfig(struct nfp_net *nn, u32 update);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index c47705861a81..59f1764242a0 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -392,6 +392,15 @@ static irqreturn_t nfp_net_irq_rxtx(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t nfp_ctrl_irq_rxtx(int irq, void *data)
+{
+ struct nfp_net_r_vector *r_vec = data;
+
+ tasklet_schedule(&r_vec->tasklet);
+
+ return IRQ_HANDLED;
+}
+
/**
* nfp_net_read_link_status() - Reread link status from control BAR
* @nn: NFP Network structure
@@ -523,7 +532,7 @@ nfp_net_aux_irq_request(struct nfp_net *nn, u32 ctrl_offset,
entry = &nn->irq_entries[vector_idx];
- snprintf(name, name_sz, format, netdev_name(nn->dp.netdev));
+ snprintf(name, name_sz, format, nfp_net_name(nn));
err = request_irq(entry->vector, handler, 0, name, nn);
if (err) {
nn_err(nn, "Failed to request IRQ %d (err=%d).\n",
@@ -943,6 +952,9 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring)
r_vec->tx_pkts += done_pkts;
u64_stats_update_end(&r_vec->tx_sync);
+ if (!dp->netdev)
+ return;
+
nd_q = netdev_get_tx_queue(dp->netdev, tx_ring->idx);
netdev_tx_completed_queue(nd_q, done_pkts, done_bytes);
if (nfp_net_tx_ring_should_wake(tx_ring)) {
@@ -1052,7 +1064,7 @@ nfp_net_tx_ring_reset(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
tx_ring->qcp_rd_p = 0;
tx_ring->wr_ptr_add = 0;
- if (tx_ring->is_xdp)
+ if (tx_ring->is_xdp || !dp->netdev)
return;
nd_q = netdev_get_tx_queue(dp->netdev, tx_ring->idx);
@@ -1742,6 +1754,231 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
return pkts_polled;
}
+/* Control device data path
+ */
+
+static bool
+nfp_ctrl_tx_one(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
+ struct sk_buff *skb, bool old)
+{
+ unsigned int real_len = skb->len, meta_len = 0;
+ struct nfp_net_tx_ring *tx_ring;
+ struct nfp_net_tx_buf *txbuf;
+ struct nfp_net_tx_desc *txd;
+ struct nfp_net_dp *dp;
+ dma_addr_t dma_addr;
+ int wr_idx;
+
+ dp = &r_vec->nfp_net->dp;
+ tx_ring = r_vec->tx_ring;
+
+ if (WARN_ON_ONCE(skb_shinfo(skb)->nr_frags)) {
+ nn_dp_warn(dp, "Driver's CTRL TX does not implement gather\n");
+ goto err_free;
+ }
+
+ if (unlikely(nfp_net_tx_full(tx_ring, 1))) {
+ u64_stats_update_begin(&r_vec->tx_sync);
+ r_vec->tx_busy++;
+ u64_stats_update_end(&r_vec->tx_sync);
+ if (!old)
+ __skb_queue_tail(&r_vec->queue, skb);
+ else
+ __skb_queue_head(&r_vec->queue, skb);
+ return true;
+ }
+
+ if (nfp_app_ctrl_has_meta(nn->app)) {
+ if (unlikely(skb_headroom(skb) < 8)) {
+ nn_dp_warn(dp, "CTRL TX on skb without headroom\n");
+ goto err_free;
+ }
+ meta_len = 8;
+ put_unaligned_be32(NFP_META_PORT_ID_CTRL, skb_push(skb, 4));
+ put_unaligned_be32(NFP_NET_META_PORTID, skb_push(skb, 4));
+ }
+
+ /* Start with the head skbuf */
+ dma_addr = dma_map_single(dp->dev, skb->data, skb_headlen(skb),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dp->dev, dma_addr))
+ goto err_dma_warn;
+
+ wr_idx = D_IDX(tx_ring, tx_ring->wr_p);
+
+ /* Stash the soft descriptor of the head then initialize it */
+ txbuf = &tx_ring->txbufs[wr_idx];
+ txbuf->skb = skb;
+ txbuf->dma_addr = dma_addr;
+ txbuf->fidx = -1;
+ txbuf->pkt_cnt = 1;
+ txbuf->real_len = real_len;
+
+ /* Build TX descriptor */
+ txd = &tx_ring->txds[wr_idx];
+ txd->offset_eop = meta_len | PCIE_DESC_TX_EOP;
+ txd->dma_len = cpu_to_le16(skb_headlen(skb));
+ nfp_desc_set_dma_addr(txd, dma_addr);
+ txd->data_len = cpu_to_le16(skb->len);
+
+ txd->flags = 0;
+ txd->mss = 0;
+ txd->lso_hdrlen = 0;
+
+ tx_ring->wr_p++;
+ tx_ring->wr_ptr_add++;
+ nfp_net_tx_xmit_more_flush(tx_ring);
+
+ return false;
+
+err_dma_warn:
+ nn_dp_warn(dp, "Failed to DMA map TX CTRL buffer\n");
+err_free:
+ u64_stats_update_begin(&r_vec->tx_sync);
+ r_vec->tx_errors++;
+ u64_stats_update_end(&r_vec->tx_sync);
+ dev_kfree_skb_any(skb);
+ return false;
+}
+
+bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb)
+{
+ struct nfp_net_r_vector *r_vec = &nn->r_vecs[0];
+ bool ret;
+
+ spin_lock_bh(&r_vec->lock);
+ ret = nfp_ctrl_tx_one(nn, r_vec, skb, false);
+ spin_unlock_bh(&r_vec->lock);
+
+ return ret;
+}
+
+static void __nfp_ctrl_tx_queued(struct nfp_net_r_vector *r_vec)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(&r_vec->queue)))
+ if (nfp_ctrl_tx_one(r_vec->nfp_net, r_vec, skb, true))
+ return;
+}
+
+static bool
+nfp_ctrl_meta_ok(struct nfp_net *nn, void *data, unsigned int meta_len)
+{
+ u32 meta_type, meta_tag;
+
+ if (!nfp_app_ctrl_has_meta(nn->app))
+ return !meta_len;
+
+ if (meta_len != 8)
+ return false;
+
+ meta_type = get_unaligned_be32(data);
+ meta_tag = get_unaligned_be32(data + 4);
+
+ return (meta_type == NFP_NET_META_PORTID &&
+ meta_tag == NFP_META_PORT_ID_CTRL);
+}
+
+static bool
+nfp_ctrl_rx_one(struct nfp_net *nn, struct nfp_net_dp *dp,
+ struct nfp_net_r_vector *r_vec, struct nfp_net_rx_ring *rx_ring)
+{
+ unsigned int meta_len, data_len, meta_off, pkt_len, pkt_off;
+ struct nfp_net_rx_buf *rxbuf;
+ struct nfp_net_rx_desc *rxd;
+ dma_addr_t new_dma_addr;
+ struct sk_buff *skb;
+ void *new_frag;
+ int idx;
+
+ idx = D_IDX(rx_ring, rx_ring->rd_p);
+
+ rxd = &rx_ring->rxds[idx];
+ if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD))
+ return false;
+
+ /* Memory barrier to ensure that we won't do other reads
+ * before the DD bit.
+ */
+ dma_rmb();
+
+ rx_ring->rd_p++;
+
+ rxbuf = &rx_ring->rxbufs[idx];
+ meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK;
+ data_len = le16_to_cpu(rxd->rxd.data_len);
+ pkt_len = data_len - meta_len;
+
+ pkt_off = NFP_NET_RX_BUF_HEADROOM + dp->rx_dma_off;
+ if (dp->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC)
+ pkt_off += meta_len;
+ else
+ pkt_off += dp->rx_offset;
+ meta_off = pkt_off - meta_len;
+
+ /* Stats update */
+ u64_stats_update_begin(&r_vec->rx_sync);
+ r_vec->rx_pkts++;
+ r_vec->rx_bytes += pkt_len;
+ u64_stats_update_end(&r_vec->rx_sync);
+
+ nfp_net_dma_sync_cpu_rx(dp, rxbuf->dma_addr + meta_off, data_len);
+
+ if (unlikely(!nfp_ctrl_meta_ok(nn, rxbuf->frag + meta_off, meta_len))) {
+ nn_dp_warn(dp, "incorrect metadata for ctrl packet (%d)\n",
+ meta_len);
+ nfp_net_rx_drop(dp, r_vec, rx_ring, rxbuf, NULL);
+ return true;
+ }
+
+ skb = build_skb(rxbuf->frag, dp->fl_bufsz);
+ if (unlikely(!skb)) {
+ nfp_net_rx_drop(dp, r_vec, rx_ring, rxbuf, NULL);
+ return true;
+ }
+ new_frag = nfp_net_napi_alloc_one(dp, &new_dma_addr);
+ if (unlikely(!new_frag)) {
+ nfp_net_rx_drop(dp, r_vec, rx_ring, rxbuf, skb);
+ return true;
+ }
+
+ nfp_net_dma_unmap_rx(dp, rxbuf->dma_addr);
+
+ nfp_net_rx_give_one(dp, rx_ring, new_frag, new_dma_addr);
+
+ skb_reserve(skb, pkt_off);
+ skb_put(skb, pkt_len);
+
+ dev_kfree_skb_any(skb);
+
+ return true;
+}
+
+static void nfp_ctrl_rx(struct nfp_net_r_vector *r_vec)
+{
+ struct nfp_net_rx_ring *rx_ring = r_vec->rx_ring;
+ struct nfp_net *nn = r_vec->nfp_net;
+ struct nfp_net_dp *dp = &nn->dp;
+
+ while (nfp_ctrl_rx_one(nn, dp, r_vec, rx_ring))
+ continue;
+}
+
+static void nfp_ctrl_poll(unsigned long arg)
+{
+ struct nfp_net_r_vector *r_vec = (void *)arg;
+
+ spin_lock_bh(&r_vec->lock);
+ nfp_net_tx_complete(r_vec->tx_ring);
+ __nfp_ctrl_tx_queued(r_vec);
+ spin_unlock_bh(&r_vec->lock);
+
+ nfp_ctrl_rx(r_vec);
+
+ nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_entry);
+}
+
/* Setup and Configuration
*/
@@ -1764,10 +2001,21 @@ static void nfp_net_vecs_init(struct nfp_net *nn)
r_vec = &nn->r_vecs[r];
r_vec->nfp_net = nn;
- r_vec->handler = nfp_net_irq_rxtx;
r_vec->irq_entry = entry->entry;
r_vec->irq_vector = entry->vector;
+ if (nn->dp.netdev) {
+ r_vec->handler = nfp_net_irq_rxtx;
+ } else {
+ r_vec->handler = nfp_ctrl_irq_rxtx;
+
+ __skb_queue_head_init(&r_vec->queue);
+ spin_lock_init(&r_vec->lock);
+ tasklet_init(&r_vec->tasklet, nfp_ctrl_poll,
+ (unsigned long)r_vec);
+ tasklet_disable(&r_vec->tasklet);
+ }
+
cpumask_set_cpu(r, &r_vec->affinity_mask);
}
}
@@ -2034,15 +2282,22 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
int err;
/* Setup NAPI */
- netif_napi_add(nn->dp.netdev, &r_vec->napi,
- nfp_net_poll, NAPI_POLL_WEIGHT);
+ if (nn->dp.netdev)
+ netif_napi_add(nn->dp.netdev, &r_vec->napi,
+ nfp_net_poll, NAPI_POLL_WEIGHT);
+ else
+ tasklet_enable(&r_vec->tasklet);
snprintf(r_vec->name, sizeof(r_vec->name),
- "%s-rxtx-%d", nn->dp.netdev->name, idx);
+ "%s-rxtx-%d", nfp_net_name(nn), idx);
err = request_irq(r_vec->irq_vector, r_vec->handler, 0, r_vec->name,
r_vec);
if (err) {
- netif_napi_del(&r_vec->napi);
+ if (nn->dp.netdev)
+ netif_napi_del(&r_vec->napi);
+ else
+ tasklet_disable(&r_vec->tasklet);
+
nn_err(nn, "Error requesting IRQ %d\n", r_vec->irq_vector);
return err;
}
@@ -2060,7 +2315,11 @@ static void
nfp_net_cleanup_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec)
{
irq_set_affinity_hint(r_vec->irq_vector, NULL);
- netif_napi_del(&r_vec->napi);
+ if (nn->dp.netdev)
+ netif_napi_del(&r_vec->napi);
+ else
+ tasklet_disable(&r_vec->tasklet);
+
free_irq(r_vec->irq_vector, r_vec);
}
@@ -2338,6 +2597,24 @@ static int nfp_net_netdev_close(struct net_device *netdev)
return 0;
}
+void nfp_ctrl_close(struct nfp_net *nn)
+{
+ int r;
+
+ rtnl_lock();
+
+ for (r = 0; r < nn->dp.num_r_vecs; r++) {
+ disable_irq(nn->r_vecs[r].irq_vector);
+ tasklet_disable(&nn->r_vecs[r].tasklet);
+ }
+
+ nfp_net_clear_config_and_disable(nn);
+
+ nfp_net_close_free_all(nn);
+
+ rtnl_unlock();
+}
+
/**
* nfp_net_open_stack() - Start the device from stack's perspective
* @nn: NFP Net device to reconfigure
@@ -2453,6 +2730,35 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return err;
}
+int nfp_ctrl_open(struct nfp_net *nn)
+{
+ int err, r;
+
+ /* ring dumping depends on vNICs being opened/closed under rtnl */
+ rtnl_lock();
+
+ err = nfp_net_open_alloc_all(nn);
+ if (err)
+ goto err_unlock;
+
+ err = nfp_net_set_config_and_enable(nn);
+ if (err)
+ goto err_free_all;
+
+ for (r = 0; r < nn->dp.num_r_vecs; r++)
+ enable_irq(nn->r_vecs[r].irq_vector);
+
+ rtnl_unlock();
+
+ return 0;
+
+err_free_all:
+ nfp_net_close_free_all(nn);
+err_unlock:
+ rtnl_unlock();
+ return err;
+}
+
static void nfp_net_set_rx_mode(struct net_device *netdev)
{
struct nfp_net *nn = netdev_priv(netdev);
@@ -3278,6 +3584,7 @@ int nfp_net_init(struct nfp_net *nn)
/* Chained metadata is signalled by capabilities except in version 4 */
nn->dp.chained_metadata_format = nn->fw_ver.major == 4 ||
+ !nn->dp.netdev ||
nn->cap & NFP_NET_CFG_CTRL_CHAIN_META;
if (nn->dp.chained_metadata_format && nn->fw_ver.major != 4)
nn->cap &= ~NFP_NET_CFG_CTRL_RSS;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index c8208bf370e0..48a8bf97645e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -71,8 +71,11 @@
#define NFP_NET_META_FIELD_SIZE 4
#define NFP_NET_META_HASH 1 /* next field carries hash type */
#define NFP_NET_META_MARK 2
+#define NFP_NET_META_PORTID 5
#define NFP_NET_META_CSUM 6 /* checksum complete type */
+#define NFP_META_PORT_ID_CTRL ~0U
+
/**
* Hash type pre-pended when a RSS hash was computed
*/
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 14/16] nfp: allow non-equal distribution of IRQs
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
Thus far the code assumed all vNICs will request similar number of IRQs.
This will be no longer true with control vNICs (where 1 IRQ will suffice).
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 98a99b199674..362dca38223b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -420,7 +420,8 @@ static int nfp_net_pf_alloc_irqs(struct nfp_pf *pf)
list_for_each_entry(nn, &pf->vnics, vnic_list) {
unsigned int n;
- n = DIV_ROUND_UP(irqs_left, vnics_left);
+ n = min(NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs,
+ DIV_ROUND_UP(irqs_left, vnics_left));
nfp_net_irqs_assign(nn, &pf->irq_entries[num_irqs - irqs_left],
n);
irqs_left -= n;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 13/16] nfp: slice the netdev spawning function
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
We want to be able to create a special vNIC for control messages.
This vNIC should be created before any netdev is registered to allow
nfp_app logic to exchange messages with the FW app before any netdev
is visible to user space. Unfortunately we can't enable IRQs until
we know how many vNICs we will need to spawn.
Divide the function which spawns netdevs for vNICs into three parts:
- vNIC/memory allocation;
- IRQ allocation;
- netdev init and register.
This will help us insert the initialization of the control channel
after IRQ allocation but before netdev init and register.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 62 ++++++++++++++---------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 82172665e023..98a99b199674 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -391,18 +391,10 @@ static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)
nfp_app_vnic_clean(pf->app, nn);
}
-static int
-nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
- void __iomem *ctrl_bar, void __iomem *qc_bar, int stride)
+static int nfp_net_pf_alloc_irqs(struct nfp_pf *pf)
{
- unsigned int id, wanted_irqs, num_irqs, vnics_left, irqs_left;
+ unsigned int wanted_irqs, num_irqs, vnics_left, irqs_left;
struct nfp_net *nn;
- int err;
-
- /* Allocate the vnics and do basic init */
- err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);
- if (err)
- return err;
/* Get MSI-X vectors */
wanted_irqs = 0;
@@ -410,18 +402,16 @@ nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
wanted_irqs += NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs;
pf->irq_entries = kcalloc(wanted_irqs, sizeof(*pf->irq_entries),
GFP_KERNEL);
- if (!pf->irq_entries) {
- err = -ENOMEM;
- goto err_nn_free;
- }
+ if (!pf->irq_entries)
+ return -ENOMEM;
num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries,
NFP_NET_MIN_VNIC_IRQS * pf->num_vnics,
wanted_irqs);
if (!num_irqs) {
- nn_warn(nn, "Unable to allocate MSI-X Vectors. Exiting\n");
- err = -ENOMEM;
- goto err_vec_free;
+ nfp_warn(pf->cpp, "Unable to allocate MSI-X vectors\n");
+ kfree(pf->irq_entries);
+ return -ENOMEM;
}
/* Distribute IRQs to vNICs */
@@ -437,6 +427,21 @@ nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
vnics_left--;
}
+ return 0;
+}
+
+static void nfp_net_pf_free_irqs(struct nfp_pf *pf)
+{
+ nfp_net_irqs_disable(pf->pdev);
+ kfree(pf->irq_entries);
+}
+
+static int nfp_net_pf_init_vnics(struct nfp_pf *pf)
+{
+ struct nfp_net *nn;
+ unsigned int id;
+ int err;
+
/* Finish vNIC init and register */
id = 0;
list_for_each_entry(nn, &pf->vnics, vnic_list) {
@@ -452,11 +457,6 @@ nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
err_prev_deinit:
list_for_each_entry_continue_reverse(nn, &pf->vnics, vnic_list)
nfp_net_pf_clean_vnic(pf, nn);
- nfp_net_irqs_disable(pf->pdev);
-err_vec_free:
- kfree(pf->irq_entries);
-err_nn_free:
- nfp_net_pf_free_vnics(pf);
return err;
}
@@ -489,8 +489,7 @@ static void nfp_net_pci_remove_finish(struct nfp_pf *pf)
{
nfp_net_debugfs_dir_clean(&pf->ddir);
- nfp_net_irqs_disable(pf->pdev);
- kfree(pf->irq_entries);
+ nfp_net_pf_free_irqs(pf);
nfp_net_pf_app_clean(pf);
@@ -691,14 +690,27 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
pf->ddir = nfp_net_debugfs_device_add(pf->pdev);
- err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, qc_bar, stride);
+ /* Allocate the vnics and do basic init */
+ err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);
if (err)
goto err_clean_ddir;
+ err = nfp_net_pf_alloc_irqs(pf);
+ if (err)
+ goto err_free_vnics;
+
+ err = nfp_net_pf_init_vnics(pf);
+ if (err)
+ goto err_free_irqs;
+
mutex_unlock(&pf->lock);
return 0;
+err_free_irqs:
+ nfp_net_pf_free_irqs(pf);
+err_free_vnics:
+ nfp_net_pf_free_vnics(pf);
err_clean_ddir:
nfp_net_debugfs_dir_clean(&pf->ddir);
nfp_net_pf_app_clean(pf);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 12/16] nfp: don't clutter init code passing fw_ver around
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
Reading fw version from the BAR is trivial. Don't pass it around
through layers of init functions, simply read it again where needed.
This commit has the side effect of each vNIC having the exact NFD
version from its own control memory, rather than all data vNICs
assuming the version of the first one. This should not result in
user-visible changes, though. Capabilities of data vNICs of trival
apps are identical.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 2a3b6deae607..82172665e023 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -277,8 +277,7 @@ static void nfp_net_pf_free_vnics(struct nfp_pf *pf)
static struct nfp_net *
nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
void __iomem *ctrl_bar, void __iomem *qc_bar,
- int stride, struct nfp_net_fw_version *fw_ver,
- unsigned int eth_id)
+ int stride, unsigned int eth_id)
{
u32 tx_base, rx_base, n_tx_rings, n_rx_rings;
struct nfp_net *nn;
@@ -295,7 +294,7 @@ nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
return nn;
nn->app = pf->app;
- nn->fw_ver = *fw_ver;
+ nfp_net_get_fw_version(&nn->fw_ver, ctrl_bar);
nn->dp.ctrl_bar = ctrl_bar;
nn->tx_bar = qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;
nn->rx_bar = qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ;
@@ -350,8 +349,7 @@ nfp_net_pf_init_vnic(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)
static int
nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
- void __iomem *qc_bar, int stride,
- struct nfp_net_fw_version *fw_ver)
+ void __iomem *qc_bar, int stride)
{
struct nfp_net *nn;
unsigned int i;
@@ -359,7 +357,7 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
for (i = 0; i < pf->max_data_vnics; i++) {
nn = nfp_net_pf_alloc_vnic(pf, true, ctrl_bar, qc_bar,
- stride, fw_ver, i);
+ stride, i);
if (IS_ERR(nn)) {
err = PTR_ERR(nn);
goto err_free_prev;
@@ -395,15 +393,14 @@ static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)
static int
nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
- void __iomem *ctrl_bar, void __iomem *qc_bar, int stride,
- struct nfp_net_fw_version *fw_ver)
+ void __iomem *ctrl_bar, void __iomem *qc_bar, int stride)
{
unsigned int id, wanted_irqs, num_irqs, vnics_left, irqs_left;
struct nfp_net *nn;
int err;
/* Allocate the vnics and do basic init */
- err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride, fw_ver);
+ err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);
if (err)
return err;
@@ -694,7 +691,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
pf->ddir = nfp_net_debugfs_device_add(pf->pdev);
- err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, qc_bar, stride, &fw_ver);
+ err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, qc_bar, stride);
if (err)
goto err_clean_ddir;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 11/16] nfp: map all queue controllers at once
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
RX and TX queue controllers are interleaved. Instead of creating
two mappings which map the same area at slightly different offset,
create only one mapping. Always map all queue controllers to simplify
the code and allow reusing the mapping for non-data vNICs.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_main.h | 6 +-
drivers/net/ethernet/netronome/nfp/nfp_net.h | 1 +
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 122 +++++-----------------
3 files changed, 28 insertions(+), 101 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h
index c46d00bbf19d..66b1e1490805 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h
@@ -63,8 +63,7 @@ struct nfp_nsp_identify;
* @cpp: Pointer to the CPP handle
* @app: Pointer to the APP handle
* @data_vnic_bar: Pointer to the CPP area for the data vNICs' BARs
- * @tx_area: Pointer to the CPP area for the TX queues
- * @rx_area: Pointer to the CPP area for the FL/RX queues
+ * @qc_area: Pointer to the CPP area for the queues
* @irq_entries: Array of MSI-X entries for all vNICs
* @limit_vfs: Number of VFs supported by firmware (~0 for PCI limit)
* @num_vfs: Number of SR-IOV VFs enabled
@@ -88,8 +87,7 @@ struct nfp_pf {
struct nfp_app *app;
struct nfp_cpp_area *data_vnic_bar;
- struct nfp_cpp_area *tx_area;
- struct nfp_cpp_area *rx_area;
+ struct nfp_cpp_area *qc_area;
struct msix_entry *irq_entries;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index eb849d26f4dd..02fd8d4e253c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -705,6 +705,7 @@ static inline void nn_pci_flush(struct nfp_net *nn)
* either add to a pointer or to read the pointer value.
*/
#define NFP_QCP_QUEUE_ADDR_SZ 0x800
+#define NFP_QCP_QUEUE_AREA_SZ 0x80000
#define NFP_QCP_QUEUE_OFF(_x) ((_x) * NFP_QCP_QUEUE_ADDR_SZ)
#define NFP_QCP_QUEUE_ADD_RPTR 0x0000
#define NFP_QCP_QUEUE_ADD_WPTR 0x0004
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 3644b12d93db..2a3b6deae607 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -223,31 +223,6 @@ static int nfp_net_pf_get_app_id(struct nfp_pf *pf)
NFP_APP_CORE_NIC);
}
-static unsigned int
-nfp_net_pf_total_qcs(struct nfp_pf *pf, void __iomem *ctrl_bar,
- unsigned int stride, u32 start_off, u32 num_off)
-{
- unsigned int i, min_qc, max_qc;
-
- min_qc = readl(ctrl_bar + start_off);
- max_qc = min_qc;
-
- for (i = 0; i < pf->max_data_vnics; i++) {
- /* To make our lives simpler only accept configuration where
- * queues are allocated to PFs in order (queues of PFn all have
- * indexes lower than PFn+1).
- */
- if (max_qc > readl(ctrl_bar + start_off))
- return 0;
-
- max_qc = readl(ctrl_bar + start_off);
- max_qc += readl(ctrl_bar + num_off) * stride;
- ctrl_bar += NFP_PF_CSR_SLICE_SIZE;
- }
-
- return max_qc - min_qc;
-}
-
static u8 __iomem *
nfp_net_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
unsigned int min_size, struct nfp_cpp_area **area)
@@ -301,15 +276,16 @@ static void nfp_net_pf_free_vnics(struct nfp_pf *pf)
static struct nfp_net *
nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
- void __iomem *ctrl_bar,
- void __iomem *tx_bar, void __iomem *rx_bar,
+ void __iomem *ctrl_bar, void __iomem *qc_bar,
int stride, struct nfp_net_fw_version *fw_ver,
unsigned int eth_id)
{
- u32 n_tx_rings, n_rx_rings;
+ u32 tx_base, rx_base, n_tx_rings, n_rx_rings;
struct nfp_net *nn;
int err;
+ tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
+ rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
n_tx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_TXRINGS);
n_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);
@@ -321,8 +297,8 @@ nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
nn->app = pf->app;
nn->fw_ver = *fw_ver;
nn->dp.ctrl_bar = ctrl_bar;
- nn->tx_bar = tx_bar;
- nn->rx_bar = rx_bar;
+ nn->tx_bar = qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;
+ nn->rx_bar = qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ;
nn->dp.is_vf = 0;
nn->stride_rx = stride;
nn->stride_tx = stride;
@@ -374,26 +350,15 @@ nfp_net_pf_init_vnic(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)
static int
nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
- void __iomem *tx_bar, void __iomem *rx_bar,
- int stride, struct nfp_net_fw_version *fw_ver)
+ void __iomem *qc_bar, int stride,
+ struct nfp_net_fw_version *fw_ver)
{
- u32 prev_tx_base, prev_rx_base, tgt_tx_base, tgt_rx_base;
struct nfp_net *nn;
unsigned int i;
int err;
- prev_tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
- prev_rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
-
for (i = 0; i < pf->max_data_vnics; i++) {
- tgt_tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
- tgt_rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
- tx_bar += (tgt_tx_base - prev_tx_base) * NFP_QCP_QUEUE_ADDR_SZ;
- rx_bar += (tgt_rx_base - prev_rx_base) * NFP_QCP_QUEUE_ADDR_SZ;
- prev_tx_base = tgt_tx_base;
- prev_rx_base = tgt_rx_base;
-
- nn = nfp_net_pf_alloc_vnic(pf, true, ctrl_bar, tx_bar, rx_bar,
+ nn = nfp_net_pf_alloc_vnic(pf, true, ctrl_bar, qc_bar,
stride, fw_ver, i);
if (IS_ERR(nn)) {
err = PTR_ERR(nn);
@@ -430,8 +395,7 @@ static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)
static int
nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
- void __iomem *ctrl_bar, void __iomem *tx_bar,
- void __iomem *rx_bar, int stride,
+ void __iomem *ctrl_bar, void __iomem *qc_bar, int stride,
struct nfp_net_fw_version *fw_ver)
{
unsigned int id, wanted_irqs, num_irqs, vnics_left, irqs_left;
@@ -439,8 +403,7 @@ nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
int err;
/* Allocate the vnics and do basic init */
- err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, tx_bar, rx_bar,
- stride, fw_ver);
+ err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride, fw_ver);
if (err)
return err;
@@ -534,8 +497,7 @@ static void nfp_net_pci_remove_finish(struct nfp_pf *pf)
nfp_net_pf_app_clean(pf);
- nfp_cpp_area_release_free(pf->rx_area);
- nfp_cpp_area_release_free(pf->tx_area);
+ nfp_cpp_area_release_free(pf->qc_area);
nfp_cpp_area_release_free(pf->data_vnic_bar);
}
@@ -659,11 +621,9 @@ int nfp_net_refresh_eth_port(struct nfp_port *port)
*/
int nfp_net_pci_probe(struct nfp_pf *pf)
{
- u32 ctrl_bar_sz, tx_area_sz, rx_area_sz;
- u8 __iomem *ctrl_bar, *tx_bar, *rx_bar;
- u32 total_tx_qcs, total_rx_qcs;
struct nfp_net_fw_version fw_ver;
- u32 start_q;
+ u8 __iomem *ctrl_bar, *qc_bar;
+ u32 ctrl_bar_sz;
int stride;
int err;
@@ -718,53 +678,23 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
}
}
- /* Find how many QC structs need to be mapped */
- total_tx_qcs = nfp_net_pf_total_qcs(pf, ctrl_bar, stride,
- NFP_NET_CFG_START_TXQ,
- NFP_NET_CFG_MAX_TXRINGS);
- total_rx_qcs = nfp_net_pf_total_qcs(pf, ctrl_bar, stride,
- NFP_NET_CFG_START_RXQ,
- NFP_NET_CFG_MAX_RXRINGS);
- if (!total_tx_qcs || !total_rx_qcs) {
- nfp_err(pf->cpp, "Invalid PF QC configuration [%d,%d]\n",
- total_tx_qcs, total_rx_qcs);
- err = -EINVAL;
- goto err_ctrl_unmap;
- }
-
- tx_area_sz = NFP_QCP_QUEUE_ADDR_SZ * total_tx_qcs;
- rx_area_sz = NFP_QCP_QUEUE_ADDR_SZ * total_rx_qcs;
-
- /* Map TX queues */
- start_q = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
- tx_bar = nfp_net_map_area(pf->cpp, "net.tx", 0, 0,
- NFP_PCIE_QUEUE(start_q),
- tx_area_sz, &pf->tx_area);
- if (IS_ERR(tx_bar)) {
- nfp_err(pf->cpp, "Failed to map TX area.\n");
- err = PTR_ERR(tx_bar);
+ /* Map queues */
+ qc_bar = nfp_net_map_area(pf->cpp, "net.qc", 0, 0,
+ NFP_PCIE_QUEUE(0), NFP_QCP_QUEUE_AREA_SZ,
+ &pf->qc_area);
+ if (IS_ERR(qc_bar)) {
+ nfp_err(pf->cpp, "Failed to map Queue Controller area.\n");
+ err = PTR_ERR(qc_bar);
goto err_ctrl_unmap;
}
- /* Map RX queues */
- start_q = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
- rx_bar = nfp_net_map_area(pf->cpp, "net.rx", 0, 0,
- NFP_PCIE_QUEUE(start_q),
- rx_area_sz, &pf->rx_area);
- if (IS_ERR(rx_bar)) {
- nfp_err(pf->cpp, "Failed to map RX area.\n");
- err = PTR_ERR(rx_bar);
- goto err_unmap_tx;
- }
-
err = nfp_net_pf_app_init(pf);
if (err)
- goto err_unmap_rx;
+ goto err_unmap_qc;
pf->ddir = nfp_net_debugfs_device_add(pf->pdev);
- err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, tx_bar, rx_bar,
- stride, &fw_ver);
+ err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, qc_bar, stride, &fw_ver);
if (err)
goto err_clean_ddir;
@@ -775,10 +705,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
err_clean_ddir:
nfp_net_debugfs_dir_clean(&pf->ddir);
nfp_net_pf_app_clean(pf);
-err_unmap_rx:
- nfp_cpp_area_release_free(pf->rx_area);
-err_unmap_tx:
- nfp_cpp_area_release_free(pf->tx_area);
+err_unmap_qc:
+ nfp_cpp_area_release_free(pf->qc_area);
err_ctrl_unmap:
nfp_cpp_area_release_free(pf->data_vnic_bar);
err_unlock:
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 05/16] nfp: prepare print macros for use without netdev
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
To be able to reuse print macros easily with control vNICs make the
macros check if netdev pointer is populated and use dev_* print
functions otherwise.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net.h | 33 +++++++++++++++++++++-------
1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 2e526338f678..b14aa31d494a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -50,15 +50,32 @@
#include "nfp_net_ctrl.h"
-#define nn_err(nn, fmt, args...) netdev_err((nn)->dp.netdev, fmt, ## args)
-#define nn_warn(nn, fmt, args...) netdev_warn((nn)->dp.netdev, fmt, ## args)
-#define nn_info(nn, fmt, args...) netdev_info((nn)->dp.netdev, fmt, ## args)
-#define nn_dbg(nn, fmt, args...) netdev_dbg((nn)->dp.netdev, fmt, ## args)
+#define nn_pr(nn, lvl, fmt, args...) \
+ ({ \
+ struct nfp_net *__nn = (nn); \
+ \
+ if (__nn->dp.netdev) \
+ netdev_printk(lvl, __nn->dp.netdev, fmt, ## args); \
+ else \
+ dev_printk(lvl, __nn->dp.dev, "ctrl: " fmt, ## args); \
+ })
+
+#define nn_err(nn, fmt, args...) nn_pr(nn, KERN_ERR, fmt, ## args)
+#define nn_warn(nn, fmt, args...) nn_pr(nn, KERN_WARNING, fmt, ## args)
+#define nn_info(nn, fmt, args...) nn_pr(nn, KERN_INFO, fmt, ## args)
+#define nn_dbg(nn, fmt, args...) nn_pr(nn, KERN_DEBUG, fmt, ## args)
+
#define nn_dp_warn(dp, fmt, args...) \
- do { \
- if (unlikely(net_ratelimit())) \
- netdev_warn((dp)->netdev, fmt, ## args); \
- } while (0)
+ ({ \
+ struct nfp_net_dp *__dp = (dp); \
+ \
+ if (unlikely(net_ratelimit())) { \
+ if (__dp->netdev) \
+ netdev_warn(__dp->netdev, fmt, ## args); \
+ else \
+ dev_warn(__dp->dev, fmt, ## args); \
+ } \
+ })
/* Max time to wait for NFP to respond on updates (in seconds) */
#define NFP_NET_POLL_TIMEOUT 5
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 07/16] nfp: allow allocation and initialization of netdev-less vNICs
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
vNICs used for sending and receiving control messages shouldn't
really have a netdev. Add the ability to initialize vNICs for
netdev-less operation.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net.h | 2 +-
.../net/ethernet/netronome/nfp/nfp_net_common.c | 170 ++++++++++++---------
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 7 +-
.../net/ethernet/netronome/nfp/nfp_netvf_main.c | 2 +-
4 files changed, 105 insertions(+), 76 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 3eec4195c155..6b21c4d0ccfa 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -831,7 +831,7 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
void __iomem *ctrl_bar);
struct nfp_net *
-nfp_net_alloc(struct pci_dev *pdev,
+nfp_net_alloc(struct pci_dev *pdev, bool needs_netdev,
unsigned int max_tx_rings, unsigned int max_rx_rings);
void nfp_net_free(struct nfp_net *nn);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index f8dba793a8fe..1cc7425ffd27 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -61,7 +61,7 @@
#include <linux/log2.h>
#include <linux/if_vlan.h>
#include <linux/random.h>
-
+#include <linux/vmalloc.h>
#include <linux/ktime.h>
#include <net/vxlan.h>
@@ -1820,7 +1820,7 @@ nfp_net_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
if (!tx_ring->txbufs)
goto err_alloc;
- if (!tx_ring->is_xdp)
+ if (!tx_ring->is_xdp && dp->netdev)
netif_set_xps_queue(dp->netdev, &r_vec->affinity_mask,
tx_ring->idx);
@@ -3034,30 +3034,39 @@ void nfp_net_info(struct nfp_net *nn)
/**
* nfp_net_alloc() - Allocate netdev and related structure
* @pdev: PCI device
+ * @needs_netdev: Whether to allocate a netdev for this vNIC
* @max_tx_rings: Maximum number of TX rings supported by device
* @max_rx_rings: Maximum number of RX rings supported by device
*
* This function allocates a netdev device and fills in the initial
- * part of the @struct nfp_net structure.
+ * part of the @struct nfp_net structure. In case of control device
+ * nfp_net structure is allocated without the netdev.
*
* Return: NFP Net device structure, or ERR_PTR on error.
*/
-struct nfp_net *nfp_net_alloc(struct pci_dev *pdev,
+struct nfp_net *nfp_net_alloc(struct pci_dev *pdev, bool needs_netdev,
unsigned int max_tx_rings,
unsigned int max_rx_rings)
{
- struct net_device *netdev;
struct nfp_net *nn;
- netdev = alloc_etherdev_mqs(sizeof(struct nfp_net),
- max_tx_rings, max_rx_rings);
- if (!netdev)
- return ERR_PTR(-ENOMEM);
+ if (needs_netdev) {
+ struct net_device *netdev;
- SET_NETDEV_DEV(netdev, &pdev->dev);
- nn = netdev_priv(netdev);
+ netdev = alloc_etherdev_mqs(sizeof(struct nfp_net),
+ max_tx_rings, max_rx_rings);
+ if (!netdev)
+ return ERR_PTR(-ENOMEM);
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ nn = netdev_priv(netdev);
+ nn->dp.netdev = netdev;
+ } else {
+ nn = vzalloc(sizeof(*nn));
+ if (!nn)
+ return ERR_PTR(-ENOMEM);
+ }
- nn->dp.netdev = netdev;
nn->dp.dev = &pdev->dev;
nn->pdev = pdev;
@@ -3091,7 +3100,10 @@ struct nfp_net *nfp_net_alloc(struct pci_dev *pdev,
*/
void nfp_net_free(struct nfp_net *nn)
{
- free_netdev(nn->dp.netdev);
+ if (nn->dp.netdev)
+ free_netdev(nn->dp.netdev);
+ else
+ vfree(nn);
}
/**
@@ -3162,52 +3174,13 @@ static void nfp_net_irqmod_init(struct nfp_net *nn)
nn->tx_coalesce_max_frames = 64;
}
-/**
- * nfp_net_init() - Initialise/finalise the nfp_net structure
- * @nn: NFP Net device structure
- *
- * Return: 0 on success or negative errno on error.
- */
-int nfp_net_init(struct nfp_net *nn)
+static void nfp_net_netdev_init(struct nfp_net *nn)
{
struct net_device *netdev = nn->dp.netdev;
- int err;
-
- nn->dp.rx_dma_dir = DMA_FROM_DEVICE;
-
- /* Get some of the read-only fields from the BAR */
- nn->cap = nn_readl(nn, NFP_NET_CFG_CAP);
- nn->max_mtu = nn_readl(nn, NFP_NET_CFG_MAX_MTU);
-
- /* Chained metadata is signalled by capabilities except in version 4 */
- nn->dp.chained_metadata_format = nn->fw_ver.major == 4 ||
- nn->cap & NFP_NET_CFG_CTRL_CHAIN_META;
- if (nn->dp.chained_metadata_format && nn->fw_ver.major != 4)
- nn->cap &= ~NFP_NET_CFG_CTRL_RSS;
nfp_net_write_mac_addr(nn, nn->dp.netdev->dev_addr);
- /* Determine RX packet/metadata boundary offset */
- if (nn->fw_ver.major >= 2) {
- u32 reg;
-
- reg = nn_readl(nn, NFP_NET_CFG_RX_OFFSET);
- if (reg > NFP_NET_MAX_PREPEND) {
- nn_err(nn, "Invalid rx offset: %d\n", reg);
- return -EINVAL;
- }
- nn->dp.rx_offset = reg;
- } else {
- nn->dp.rx_offset = NFP_NET_RX_OFFSET;
- }
-
- /* Set default MTU and Freelist buffer size */
- if (nn->max_mtu < NFP_NET_DEFAULT_MTU)
- netdev->mtu = nn->max_mtu;
- else
- netdev->mtu = NFP_NET_DEFAULT_MTU;
- nn->dp.mtu = netdev->mtu;
- nn->dp.fl_bufsz = nfp_net_calc_fl_bufsz(&nn->dp);
+ netdev->mtu = nn->dp.mtu;
/* Advertise/enable offloads based on capabilities
*
@@ -3237,12 +3210,8 @@ int nfp_net_init(struct nfp_net *nn)
nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
NFP_NET_CFG_CTRL_LSO;
}
- if (nn->cap & NFP_NET_CFG_CTRL_RSS_ANY) {
+ if (nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)
netdev->hw_features |= NETIF_F_RXHASH;
- nfp_net_rss_init(nn);
- nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RSS2 ?:
- NFP_NET_CFG_CTRL_RSS;
- }
if (nn->cap & NFP_NET_CFG_CTRL_VXLAN &&
nn->cap & NFP_NET_CFG_CTRL_NVGRE) {
if (nn->cap & NFP_NET_CFG_CTRL_LSO)
@@ -3277,6 +3246,68 @@ int nfp_net_init(struct nfp_net *nn)
netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
nn->dp.ctrl &= ~NFP_NET_CFG_CTRL_LSO_ANY;
+ /* Finalise the netdev setup */
+ netdev->netdev_ops = &nfp_net_netdev_ops;
+ netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
+
+ /* MTU range: 68 - hw-specific max */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = nn->max_mtu;
+
+ netif_carrier_off(netdev);
+
+ nfp_net_set_ethtool_ops(netdev);
+}
+
+/**
+ * nfp_net_init() - Initialise/finalise the nfp_net structure
+ * @nn: NFP Net device structure
+ *
+ * Return: 0 on success or negative errno on error.
+ */
+int nfp_net_init(struct nfp_net *nn)
+{
+ int err;
+
+ nn->dp.rx_dma_dir = DMA_FROM_DEVICE;
+
+ /* Get some of the read-only fields from the BAR */
+ nn->cap = nn_readl(nn, NFP_NET_CFG_CAP);
+ nn->max_mtu = nn_readl(nn, NFP_NET_CFG_MAX_MTU);
+
+ /* Chained metadata is signalled by capabilities except in version 4 */
+ nn->dp.chained_metadata_format = nn->fw_ver.major == 4 ||
+ nn->cap & NFP_NET_CFG_CTRL_CHAIN_META;
+ if (nn->dp.chained_metadata_format && nn->fw_ver.major != 4)
+ nn->cap &= ~NFP_NET_CFG_CTRL_RSS;
+
+ /* Determine RX packet/metadata boundary offset */
+ if (nn->fw_ver.major >= 2) {
+ u32 reg;
+
+ reg = nn_readl(nn, NFP_NET_CFG_RX_OFFSET);
+ if (reg > NFP_NET_MAX_PREPEND) {
+ nn_err(nn, "Invalid rx offset: %d\n", reg);
+ return -EINVAL;
+ }
+ nn->dp.rx_offset = reg;
+ } else {
+ nn->dp.rx_offset = NFP_NET_RX_OFFSET;
+ }
+
+ /* Set default MTU and Freelist buffer size */
+ if (nn->max_mtu < NFP_NET_DEFAULT_MTU)
+ nn->dp.mtu = nn->max_mtu;
+ else
+ nn->dp.mtu = NFP_NET_DEFAULT_MTU;
+ nn->dp.fl_bufsz = nfp_net_calc_fl_bufsz(&nn->dp);
+
+ if (nn->cap & NFP_NET_CFG_CTRL_RSS_ANY) {
+ nfp_net_rss_init(nn);
+ nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RSS2 ?:
+ NFP_NET_CFG_CTRL_RSS;
+ }
+
/* Allow L2 Broadcast and Multicast through by default, if supported */
if (nn->cap & NFP_NET_CFG_CTRL_L2BC)
nn->dp.ctrl |= NFP_NET_CFG_CTRL_L2BC;
@@ -3289,6 +3320,9 @@ int nfp_net_init(struct nfp_net *nn)
nn->dp.ctrl |= NFP_NET_CFG_CTRL_IRQMOD;
}
+ if (nn->dp.netdev)
+ nfp_net_netdev_init(nn);
+
/* Stash the re-configuration queue away. First odd queue in TX Bar */
nn->qcp_cfg = nn->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
@@ -3301,20 +3335,11 @@ int nfp_net_init(struct nfp_net *nn)
if (err)
return err;
- /* Finalise the netdev setup */
- netdev->netdev_ops = &nfp_net_netdev_ops;
- netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
-
- /* MTU range: 68 - hw-specific max */
- netdev->min_mtu = ETH_MIN_MTU;
- netdev->max_mtu = nn->max_mtu;
-
- netif_carrier_off(netdev);
-
- nfp_net_set_ethtool_ops(netdev);
nfp_net_vecs_init(nn);
- return register_netdev(netdev);
+ if (!nn->dp.netdev)
+ return 0;
+ return register_netdev(nn->dp.netdev);
}
/**
@@ -3323,6 +3348,9 @@ int nfp_net_init(struct nfp_net *nn)
*/
void nfp_net_clean(struct nfp_net *nn)
{
+ if (!nn->dp.netdev)
+ return;
+
unregister_netdev(nn->dp.netdev);
if (nn->dp.xdp_prog)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 7dd310911d9f..dd2a99fca716 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -303,7 +303,8 @@ static void nfp_net_pf_free_vnics(struct nfp_pf *pf)
}
static struct nfp_net *
-nfp_net_pf_alloc_vnic(struct nfp_pf *pf, void __iomem *ctrl_bar,
+nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
+ void __iomem *ctrl_bar,
void __iomem *tx_bar, void __iomem *rx_bar,
int stride, struct nfp_net_fw_version *fw_ver,
unsigned int eth_id)
@@ -316,7 +317,7 @@ nfp_net_pf_alloc_vnic(struct nfp_pf *pf, void __iomem *ctrl_bar,
n_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);
/* Allocate and initialise the vNIC */
- nn = nfp_net_alloc(pf->pdev, n_tx_rings, n_rx_rings);
+ nn = nfp_net_alloc(pf->pdev, needs_netdev, n_tx_rings, n_rx_rings);
if (IS_ERR(nn))
return nn;
@@ -395,7 +396,7 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
prev_tx_base = tgt_tx_base;
prev_rx_base = tgt_rx_base;
- nn = nfp_net_pf_alloc_vnic(pf, ctrl_bar, tx_bar, rx_bar,
+ nn = nfp_net_pf_alloc_vnic(pf, true, ctrl_bar, tx_bar, rx_bar,
stride, fw_ver, i);
if (IS_ERR(nn)) {
err = PTR_ERR(nn);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
index 3f1c7f0f392e..0bf3b0febd07 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
@@ -202,7 +202,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
rx_bar_off = NFP_PCIE_QUEUE(startq);
/* Allocate and initialise the netdev */
- nn = nfp_net_alloc(pdev, max_tx_rings, max_rx_rings);
+ nn = nfp_net_alloc(pdev, true, max_tx_rings, max_rx_rings);
if (IS_ERR(nn)) {
err = PTR_ERR(nn);
goto err_ctrl_unmap;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 08/16] nfp: prepare config and enable for working without netdevs
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
Out of the three stages of ifup/ifdown (allocate, configure, start)
- this commit prepares the configuration stage for working with
control vNICs.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 1cc7425ffd27..c47705861a81 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2236,9 +2236,10 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn)
nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, nn->dp.num_rx_rings == 64 ?
0xffffffffffffffffULL : ((u64)1 << nn->dp.num_rx_rings) - 1);
- nfp_net_write_mac_addr(nn, nn->dp.netdev->dev_addr);
+ if (nn->dp.netdev)
+ nfp_net_write_mac_addr(nn, nn->dp.netdev->dev_addr);
- nn_writel(nn, NFP_NET_CFG_MTU, nn->dp.netdev->mtu);
+ nn_writel(nn, NFP_NET_CFG_MTU, nn->dp.mtu);
bufsz = nn->dp.fl_bufsz - nn->dp.rx_dma_off - NFP_NET_RX_BUF_NON_DATA;
nn_writel(nn, NFP_NET_CFG_FLBUFSZ, bufsz);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 06/16] nfp: make sure debug accesses don't depend on netdevs
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
We want to be able to inspect the state of descriptor rings of
the control vNIC, so it will use the same interface as data vNICs.
Make sure the code doesn't use netdevs to determine state
of the rings and names things appropriately.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net.h | 11 +++++++++++
drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c | 9 ++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index b14aa31d494a..3eec4195c155 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -805,6 +805,17 @@ static inline u32 nfp_qcp_wr_ptr_read(u8 __iomem *q)
return _nfp_qcp_read(q, NFP_QCP_WRITE_PTR);
}
+static inline bool nfp_net_is_data_vnic(struct nfp_net *nn)
+{
+ WARN_ON_ONCE(!nn->dp.netdev && nn->port);
+ return !!nn->dp.netdev;
+}
+
+static inline bool nfp_net_running(struct nfp_net *nn)
+{
+ return nn->dp.ctrl & NFP_NET_CFG_CTRL_ENABLE;
+}
+
/* Globals */
extern const char nfp_driver_version[];
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
index 8c52c0e8379c..40217ece5fcb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
@@ -54,7 +54,7 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
goto out;
nn = r_vec->nfp_net;
rx_ring = r_vec->rx_ring;
- if (!netif_running(nn->dp.netdev))
+ if (!nfp_net_running(nn))
goto out;
rxd_cnt = rx_ring->cnt;
@@ -138,7 +138,7 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
if (!r_vec->nfp_net || !tx_ring)
goto out;
nn = r_vec->nfp_net;
- if (!netif_running(nn->dp.netdev))
+ if (!nfp_net_running(nn))
goto out;
txd_cnt = tx_ring->cnt;
@@ -209,7 +209,10 @@ void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir, int id)
if (IS_ERR_OR_NULL(nfp_dir))
return;
- sprintf(name, "vnic%d", id);
+ if (nfp_net_is_data_vnic(nn))
+ sprintf(name, "vnic%d", id);
+ else
+ strcpy(name, "ctrl-vnic");
nn->debugfs_dir = debugfs_create_dir(name, ddir);
if (IS_ERR_OR_NULL(nn->debugfs_dir))
return;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 04/16] nfp: move nfp_net_vecs_init()
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
Move nfp_net_vecs_init() after all datapath functions. We will need
to init poll() callbacks from this function soon.
No functional changes.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
.../net/ethernet/netronome/nfp/nfp_net_common.c | 54 +++++++++++-----------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 23419883cfd4..f8dba793a8fe 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -504,33 +504,6 @@ nfp_net_rx_ring_init(struct nfp_net_rx_ring *rx_ring,
}
/**
- * nfp_net_vecs_init() - Assign IRQs and setup rvecs.
- * @nn: NFP Network structure
- */
-static void nfp_net_vecs_init(struct nfp_net *nn)
-{
- struct nfp_net_r_vector *r_vec;
- int r;
-
- nn->lsc_handler = nfp_net_irq_lsc;
- nn->exn_handler = nfp_net_irq_exn;
-
- for (r = 0; r < nn->max_r_vecs; r++) {
- struct msix_entry *entry;
-
- entry = &nn->irq_entries[NFP_NET_NON_Q_VECTORS + r];
-
- r_vec = &nn->r_vecs[r];
- r_vec->nfp_net = nn;
- r_vec->handler = nfp_net_irq_rxtx;
- r_vec->irq_entry = entry->entry;
- r_vec->irq_vector = entry->vector;
-
- cpumask_set_cpu(r, &r_vec->affinity_mask);
- }
-}
-
-/**
* nfp_net_aux_irq_request() - Request an auxiliary interrupt (LSC or EXN)
* @nn: NFP Network structure
* @ctrl_offset: Control BAR offset where IRQ configuration should be written
@@ -1773,6 +1746,33 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
*/
/**
+ * nfp_net_vecs_init() - Assign IRQs and setup rvecs.
+ * @nn: NFP Network structure
+ */
+static void nfp_net_vecs_init(struct nfp_net *nn)
+{
+ struct nfp_net_r_vector *r_vec;
+ int r;
+
+ nn->lsc_handler = nfp_net_irq_lsc;
+ nn->exn_handler = nfp_net_irq_exn;
+
+ for (r = 0; r < nn->max_r_vecs; r++) {
+ struct msix_entry *entry;
+
+ entry = &nn->irq_entries[NFP_NET_NON_Q_VECTORS + r];
+
+ r_vec = &nn->r_vecs[r];
+ r_vec->nfp_net = nn;
+ r_vec->handler = nfp_net_irq_rxtx;
+ r_vec->irq_entry = entry->entry;
+ r_vec->irq_vector = entry->vector;
+
+ cpumask_set_cpu(r, &r_vec->affinity_mask);
+ }
+}
+
+/**
* nfp_net_tx_ring_free() - Free resources allocated to a TX ring
* @tx_ring: TX ring to free
*/
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 03/16] nfp: reuse ring free code on close
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
On the close path reuse the ring free helpers introduced for runtime
reconfiguration.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index bec51f4a9299..23419883cfd4 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2303,20 +2303,12 @@ static void nfp_net_close_free_all(struct nfp_net *nn)
{
unsigned int r;
- for (r = 0; r < nn->dp.num_rx_rings; r++) {
- nfp_net_rx_ring_bufs_free(&nn->dp, &nn->dp.rx_rings[r]);
- nfp_net_rx_ring_free(&nn->dp.rx_rings[r]);
- }
- for (r = 0; r < nn->dp.num_tx_rings; r++) {
- nfp_net_tx_ring_bufs_free(&nn->dp, &nn->dp.tx_rings[r]);
- nfp_net_tx_ring_free(&nn->dp.tx_rings[r]);
- }
+ nfp_net_tx_rings_free(&nn->dp);
+ nfp_net_rx_rings_free(&nn->dp);
+
for (r = 0; r < nn->dp.num_r_vecs; r++)
nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
- kfree(nn->dp.rx_rings);
- kfree(nn->dp.tx_rings);
-
nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 02/16] nfp: split out the allocation part of open
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
Our open/close implementations have 3 stages:
- allocation/freeing of ring resources, irqs etc.,
- device config,
- device/stack enable (can't fail).
Right now all of those stages are placed in separate functions,
apart from allocation during open. Fix that. It will make it
easier for us to allocate resources for netdev-less vNICs.
Because we want to reuse allocation code in netdev-less vNICs
leave the netif_set_real_num_[rt]x_queues() calls inside open.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
.../net/ethernet/netronome/nfp/nfp_net_common.c | 57 +++++++++++++---------
1 file changed, 35 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 770ef28c0380..bec51f4a9299 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2364,16 +2364,10 @@ static void nfp_net_open_stack(struct nfp_net *nn)
nfp_net_read_link_status(nn);
}
-static int nfp_net_netdev_open(struct net_device *netdev)
+static int nfp_net_open_alloc_all(struct nfp_net *nn)
{
- struct nfp_net *nn = netdev_priv(netdev);
int err, r;
- /* Step 1: Allocate resources for rings and the like
- * - Request interrupts
- * - Allocate RX and TX ring resources
- * - Setup initial RSS table
- */
err = nfp_net_aux_irq_request(nn, NFP_NET_CFG_EXN, "%s-exn",
nn->exn_name, sizeof(nn->exn_name),
NFP_NET_IRQ_EXN_IDX, nn->exn_handler);
@@ -2403,13 +2397,42 @@ static int nfp_net_netdev_open(struct net_device *netdev)
for (r = 0; r < nn->max_r_vecs; r++)
nfp_net_vector_assign_rings(&nn->dp, &nn->r_vecs[r], r);
+ return 0;
+
+err_free_rx_rings:
+ nfp_net_rx_rings_free(&nn->dp);
+err_cleanup_vec:
+ r = nn->dp.num_r_vecs;
+err_cleanup_vec_p:
+ while (r--)
+ nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
+ nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
+err_free_exn:
+ nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
+ return err;
+}
+
+static int nfp_net_netdev_open(struct net_device *netdev)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+ int err;
+
+ /* Step 1: Allocate resources for rings and the like
+ * - Request interrupts
+ * - Allocate RX and TX ring resources
+ * - Setup initial RSS table
+ */
+ err = nfp_net_open_alloc_all(nn);
+ if (err)
+ return err;
+
err = netif_set_real_num_tx_queues(netdev, nn->dp.num_stack_tx_rings);
if (err)
- goto err_free_rings;
+ goto err_free_all;
err = netif_set_real_num_rx_queues(netdev, nn->dp.num_rx_rings);
if (err)
- goto err_free_rings;
+ goto err_free_all;
/* Step 2: Configure the NFP
* - Enable rings from 0 to tx_rings/rx_rings - 1.
@@ -2420,7 +2443,7 @@ static int nfp_net_netdev_open(struct net_device *netdev)
*/
err = nfp_net_set_config_and_enable(nn);
if (err)
- goto err_free_rings;
+ goto err_free_all;
/* Step 3: Enable for kernel
* - put some freelist descriptors on each RX ring
@@ -2432,18 +2455,8 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return 0;
-err_free_rings:
- nfp_net_tx_rings_free(&nn->dp);
-err_free_rx_rings:
- nfp_net_rx_rings_free(&nn->dp);
-err_cleanup_vec:
- r = nn->dp.num_r_vecs;
-err_cleanup_vec_p:
- while (r--)
- nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
- nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
-err_free_exn:
- nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
+err_free_all:
+ nfp_net_close_free_all(nn);
return err;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 01/16] nfp: reorder open and close functions
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
In-Reply-To: <20170606000157.17556-1-jakub.kicinski@netronome.com>
We will soon reuse parts of .ndo_stop() for clean up after errors
in .ndo_open(). Reorder the associated functions to make that possible.
No functional changes.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
.../net/ethernet/netronome/nfp/nfp_net_common.c | 140 ++++++++++-----------
1 file changed, 70 insertions(+), 70 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index c3235d03b8eb..770ef28c0380 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2276,6 +2276,76 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn)
}
/**
+ * nfp_net_close_stack() - Quiesce the stack (part of close)
+ * @nn: NFP Net device to reconfigure
+ */
+static void nfp_net_close_stack(struct nfp_net *nn)
+{
+ unsigned int r;
+
+ disable_irq(nn->irq_entries[NFP_NET_IRQ_LSC_IDX].vector);
+ netif_carrier_off(nn->dp.netdev);
+ nn->link_up = false;
+
+ for (r = 0; r < nn->dp.num_r_vecs; r++) {
+ disable_irq(nn->r_vecs[r].irq_vector);
+ napi_disable(&nn->r_vecs[r].napi);
+ }
+
+ netif_tx_disable(nn->dp.netdev);
+}
+
+/**
+ * nfp_net_close_free_all() - Free all runtime resources
+ * @nn: NFP Net device to reconfigure
+ */
+static void nfp_net_close_free_all(struct nfp_net *nn)
+{
+ unsigned int r;
+
+ for (r = 0; r < nn->dp.num_rx_rings; r++) {
+ nfp_net_rx_ring_bufs_free(&nn->dp, &nn->dp.rx_rings[r]);
+ nfp_net_rx_ring_free(&nn->dp.rx_rings[r]);
+ }
+ for (r = 0; r < nn->dp.num_tx_rings; r++) {
+ nfp_net_tx_ring_bufs_free(&nn->dp, &nn->dp.tx_rings[r]);
+ nfp_net_tx_ring_free(&nn->dp.tx_rings[r]);
+ }
+ for (r = 0; r < nn->dp.num_r_vecs; r++)
+ nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
+
+ kfree(nn->dp.rx_rings);
+ kfree(nn->dp.tx_rings);
+
+ nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
+ nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
+}
+
+/**
+ * nfp_net_netdev_close() - Called when the device is downed
+ * @netdev: netdev structure
+ */
+static int nfp_net_netdev_close(struct net_device *netdev)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+
+ /* Step 1: Disable RX and TX rings from the Linux kernel perspective
+ */
+ nfp_net_close_stack(nn);
+
+ /* Step 2: Tell NFP
+ */
+ nfp_net_clear_config_and_disable(nn);
+
+ /* Step 3: Free resources
+ */
+ nfp_net_close_free_all(nn);
+
+ nn_dbg(nn, "%s down", netdev->name);
+ return 0;
+}
+
+/**
* nfp_net_open_stack() - Start the device from stack's perspective
* @nn: NFP Net device to reconfigure
*/
@@ -2377,76 +2447,6 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return err;
}
-/**
- * nfp_net_close_stack() - Quiescent the stack (part of close)
- * @nn: NFP Net device to reconfigure
- */
-static void nfp_net_close_stack(struct nfp_net *nn)
-{
- unsigned int r;
-
- disable_irq(nn->irq_entries[NFP_NET_IRQ_LSC_IDX].vector);
- netif_carrier_off(nn->dp.netdev);
- nn->link_up = false;
-
- for (r = 0; r < nn->dp.num_r_vecs; r++) {
- disable_irq(nn->r_vecs[r].irq_vector);
- napi_disable(&nn->r_vecs[r].napi);
- }
-
- netif_tx_disable(nn->dp.netdev);
-}
-
-/**
- * nfp_net_close_free_all() - Free all runtime resources
- * @nn: NFP Net device to reconfigure
- */
-static void nfp_net_close_free_all(struct nfp_net *nn)
-{
- unsigned int r;
-
- for (r = 0; r < nn->dp.num_rx_rings; r++) {
- nfp_net_rx_ring_bufs_free(&nn->dp, &nn->dp.rx_rings[r]);
- nfp_net_rx_ring_free(&nn->dp.rx_rings[r]);
- }
- for (r = 0; r < nn->dp.num_tx_rings; r++) {
- nfp_net_tx_ring_bufs_free(&nn->dp, &nn->dp.tx_rings[r]);
- nfp_net_tx_ring_free(&nn->dp.tx_rings[r]);
- }
- for (r = 0; r < nn->dp.num_r_vecs; r++)
- nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
-
- kfree(nn->dp.rx_rings);
- kfree(nn->dp.tx_rings);
-
- nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
- nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
-}
-
-/**
- * nfp_net_netdev_close() - Called when the device is downed
- * @netdev: netdev structure
- */
-static int nfp_net_netdev_close(struct net_device *netdev)
-{
- struct nfp_net *nn = netdev_priv(netdev);
-
- /* Step 1: Disable RX and TX rings from the Linux kernel perspective
- */
- nfp_net_close_stack(nn);
-
- /* Step 2: Tell NFP
- */
- nfp_net_clear_config_and_disable(nn);
-
- /* Step 3: Free resources
- */
- nfp_net_close_free_all(nn);
-
- nn_dbg(nn, "%s down", netdev->name);
- return 0;
-}
-
static void nfp_net_set_rx_mode(struct net_device *netdev)
{
struct nfp_net *nn = netdev_priv(netdev);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 00/16] nfp: ctrl vNIC
From: Jakub Kicinski @ 2017-06-06 0:01 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
Hi!
This series adds the ability to use one vNIC as a control channel
for passing messages to and from the application firmware. The
implementation restructures the existing netdev vNIC code to be able
to deal with nfp_nets with netdev pointer set to NULL. Control vNICs
are not visible to userspace (other than for dumping ring state), and
since they don't have netdevs we use a tasklet for RX and simple skb
list for TX queuing.
Due to special status of the control vNIC we have to reshuffle the
init code a bit to make sure control vNIC will be fully brought up
(and therefore communication with app FW can happen) before any netdev
or port is visible to user space.
FW will designate which vNIC is supposed to be used as control one
by setting _pf%u_net_ctrl_bar symbol. Some FWs depend on metadata
being prepended to control message, some prefer to look at queue ID
to decide that something is a control message. Our implementation
can cater to both.
First two users of this code will be eBPF maps and flower offloads.
Jakub Kicinski (16):
nfp: reorder open and close functions
nfp: split out the allocation part of open
nfp: reuse ring free code on close
nfp: move nfp_net_vecs_init()
nfp: prepare print macros for use without netdev
nfp: make sure debug accesses don't depend on netdevs
nfp: allow allocation and initialization of netdev-less vNICs
nfp: prepare config and enable for working without netdevs
nfp: add control vNIC datapath
nfp: make vNIC ctrl memory mapping function reusable
nfp: map all queue controllers at once
nfp: don't clutter init code passing fw_ver around
nfp: slice the netdev spawning function
nfp: allow non-equal distribution of IRQs
nfp: create control vNICs and wire up rx/tx
nfp: advertise support for NFD ABI 0.5
drivers/net/ethernet/netronome/nfp/nfp_app.c | 18 +
drivers/net/ethernet/netronome/nfp/nfp_app.h | 55 ++
drivers/net/ethernet/netronome/nfp/nfp_main.h | 13 +-
drivers/net/ethernet/netronome/nfp/nfp_net.h | 64 +-
.../net/ethernet/netronome/nfp/nfp_net_common.c | 709 +++++++++++++++------
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 3 +
.../net/ethernet/netronome/nfp/nfp_net_debugfs.c | 9 +-
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 365 ++++++-----
.../net/ethernet/netronome/nfp/nfp_netvf_main.c | 4 +-
9 files changed, 872 insertions(+), 368 deletions(-)
--
2.11.0
^ permalink raw reply
* Re: BUG: KASAN: use-after-free in free_old_xmit_skbs
From: Michael S. Tsirkin @ 2017-06-05 23:52 UTC (permalink / raw)
To: Jean-Philippe Menil
Cc: netdev, jasowang, John Fastabend, virtualization, qemu-devel
In-Reply-To: <20170605050423-mutt-send-email-mst@kernel.org>
On Mon, Jun 05, 2017 at 05:08:25AM +0300, Michael S. Tsirkin wrote:
> On Mon, Jun 05, 2017 at 12:48:53AM +0200, Jean-Philippe Menil wrote:
> > Hi,
> >
> > while playing with xdp and ebpf, i'm hitting the following:
> >
> > [ 309.993136]
> > ==================================================================
> > [ 309.994735] BUG: KASAN: use-after-free in
> > free_old_xmit_skbs.isra.29+0x2b7/0x2e0 [virtio_net]
> > [ 309.998396] Read of size 8 at addr ffff88006aa64220 by task sshd/323
> > [ 310.000650]
> > [ 310.002305] CPU: 1 PID: 323 Comm: sshd Not tainted 4.12.0-rc3+ #2
> > [ 310.004018] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> > 1.10.2-20170228_101828-anatol 04/01/2014
> > [ 310.006495] Call Trace:
> > [ 310.007610] dump_stack+0xb8/0x14c
> > [ 310.008748] ? _atomic_dec_and_lock+0x174/0x174
> > [ 310.009998] ? pm_qos_get_value.part.7+0x6/0x6
> > [ 310.011203] print_address_description+0x6f/0x280
> > [ 310.012416] kasan_report+0x27a/0x370
> > [ 310.013573] ? free_old_xmit_skbs.isra.29+0x2b7/0x2e0 [virtio_net]
> > [ 310.014900] __asan_report_load8_noabort+0x19/0x20
> > [ 310.016136] free_old_xmit_skbs.isra.29+0x2b7/0x2e0 [virtio_net]
> > [ 310.017467] ? virtnet_del_vqs+0xe0/0xe0 [virtio_net]
> > [ 310.018759] ? packet_rcv+0x20d0/0x20d0
> > [ 310.019950] ? dev_queue_xmit_nit+0x5cd/0xaf0
> > [ 310.021168] start_xmit+0x1b4/0x1b10 [virtio_net]
> > [ 310.022413] ? default_device_exit+0x2d0/0x2d0
> > [ 310.023634] ? virtnet_remove+0xf0/0xf0 [virtio_net]
> > [ 310.024874] ? update_load_avg+0x1281/0x29f0
> > [ 310.026059] dev_hard_start_xmit+0x1ea/0x7f0
> > [ 310.027247] ? validate_xmit_skb_list+0x100/0x100
> > [ 310.028470] ? validate_xmit_skb+0x7f/0xc10
> > [ 310.029731] ? netif_skb_features+0x920/0x920
> > [ 310.033469] ? __skb_tx_hash+0x2f0/0x2f0
> > [ 310.035615] ? validate_xmit_skb_list+0xa3/0x100
> > [ 310.037782] sch_direct_xmit+0x2eb/0x7a0
> > [ 310.039842] ? dev_deactivate_queue.constprop.29+0x230/0x230
> > [ 310.041980] ? netdev_pick_tx+0x212/0x2b0
> > [ 310.043868] __dev_queue_xmit+0x12fa/0x20b0
> > [ 310.045564] ? netdev_pick_tx+0x2b0/0x2b0
> > [ 310.047210] ? __account_cfs_rq_runtime+0x630/0x630
> > [ 310.048301] ? update_stack_state+0x402/0x780
> > [ 310.049307] ? account_entity_enqueue+0x730/0x730
> > [ 310.050322] ? __rb_erase_color+0x27d0/0x27d0
> > [ 310.051286] ? update_curr_fair+0x70/0x70
> > [ 310.052206] ? enqueue_entity+0x2450/0x2450
> > [ 310.053124] ? entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.054082] ? dequeue_entity+0x27a/0x1520
> > [ 310.054967] ? bpf_prog_alloc+0x320/0x320
> > [ 310.055822] ? yield_to_task_fair+0x110/0x110
> > [ 310.056708] ? set_next_entity+0x2f2/0xa90
> > [ 310.057574] ? dequeue_task_fair+0xc09/0x2ec0
> > [ 310.058457] dev_queue_xmit+0x10/0x20
> > [ 310.059298] ip_finish_output2+0xacf/0x12a0
> > [ 310.060160] ? dequeue_entity+0x1520/0x1520
> > [ 310.063410] ? ip_fragment.constprop.47+0x220/0x220
> > [ 310.065078] ? ring_buffer_set_clock+0x50/0x50
> > [ 310.066677] ? __switch_to+0x685/0xda0
> > [ 310.068166] ? load_balance+0x38f0/0x38f0
> > [ 310.069544] ? compat_start_thread+0x80/0x80
> > [ 310.070989] ? trace_find_cmdline+0x60/0x60
> > [ 310.072402] ? rt_cpu_seq_show+0x2d0/0x2d0
> > [ 310.073579] ip_finish_output+0x407/0x880
> > [ 310.074441] ? ip_finish_output+0x407/0x880
> > [ 310.075255] ? update_stack_state+0x402/0x780
> > [ 310.076076] ip_output+0x1c0/0x640
> > [ 310.076843] ? ip_mc_output+0x1350/0x1350
> > [ 310.077642] ? __sk_dst_check+0x164/0x370
> > [ 310.078441] ? complete_formation.isra.53+0xa30/0xa30
> > [ 310.079313] ? __read_once_size_nocheck.constprop.7+0x20/0x20
> > [ 310.080265] ? sock_prot_inuse_add+0xa0/0xa0
> > [ 310.081097] ? memcpy+0x45/0x50
> > [ 310.081850] ? __copy_skb_header+0x1fa/0x280
> > [ 310.082676] ip_local_out+0x70/0x90
> > [ 310.083448] ip_queue_xmit+0x8a1/0x22a0
> > [ 310.084236] ? ip_build_and_send_pkt+0xe80/0xe80
> > [ 310.085079] ? tcp_v4_md5_lookup+0x13/0x20
> > [ 310.085884] tcp_transmit_skb+0x187a/0x3e00
> > [ 310.086696] ? __tcp_select_window+0xaf0/0xaf0
> > [ 310.087524] ? sock_sendmsg+0xba/0xf0
> > [ 310.088298] ? __vfs_write+0x4e0/0x960
> > [ 310.089074] ? vfs_write+0x155/0x4b0
> > [ 310.089838] ? SyS_write+0xf7/0x240
> > [ 310.090593] ? do_syscall_64+0x235/0x5b0
> > [ 310.091372] ? entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.094690] ? sock_sendmsg+0xba/0xf0
> > [ 310.096133] ? do_syscall_64+0x235/0x5b0
> > [ 310.097593] ? entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.099157] ? tcp_init_tso_segs+0x1e0/0x1e0
> > [ 310.100539] ? radix_tree_lookup+0xd/0x10
> > [ 310.101894] ? get_work_pool+0xcd/0x150
> > [ 310.103216] ? check_flush_dependency+0x330/0x330
> > [ 310.104113] tcp_write_xmit+0x498/0x52a0
> > [ 310.104905] ? kasan_unpoison_shadow+0x35/0x50
> > [ 310.105729] ? kasan_kmalloc+0xad/0xe0
> > [ 310.106505] ? tcp_transmit_skb+0x3e00/0x3e00
> > [ 310.107331] ? memset+0x31/0x40
> > [ 310.108070] ? __check_object_size+0x22e/0x55c
> > [ 310.108895] ? skb_pull_rcsum+0x2b0/0x2b0
> > [ 310.109690] ? check_stack_object+0x120/0x120
> > [ 310.110512] ? tcp_v4_md5_lookup+0x13/0x20
> > [ 310.111315] __tcp_push_pending_frames+0x8d/0x2a0
> > [ 310.112159] tcp_push+0x47c/0xbd0
> > [ 310.112912] ? copy_from_iter_full+0x21e/0xc70
> > [ 310.113747] ? sock_warn_obsolete_bsdism+0x70/0x70
> > [ 310.114604] ? tcp_splice_data_recv+0x1c0/0x1c0
> > [ 310.115436] ? iov_iter_copy_from_user_atomic+0xeb0/0xeb0
> > [ 310.116324] tcp_sendmsg+0xd6d/0x43f0
> > [ 310.117106] ? tcp_sendpage+0x2170/0x2170
> > [ 310.117911] ? set_fd_set.part.1+0x50/0x50
> > [ 310.118718] ? remove_wait_queue+0x196/0x3b0
> > [ 310.119535] ? set_fd_set.part.1+0x50/0x50
> > [ 310.120365] ? add_wait_queue_exclusive+0x290/0x290
> > [ 310.121224] ? __wake_up+0x44/0x50
> > [ 310.121985] ? n_tty_read+0x9f9/0x19d0
> > [ 310.122898] ? __check_object_size+0x22e/0x55c
> > [ 310.125380] inet_sendmsg+0x111/0x590
> > [ 310.126863] ? inet_recvmsg+0x5e0/0x5e0
> > [ 310.128348] ? inet_recvmsg+0x5e0/0x5e0
> > [ 310.129817] sock_sendmsg+0xba/0xf0
> > [ 310.131110] sock_write_iter+0x2e4/0x6a0
> > [ 310.132433] ? core_sys_select+0x47d/0x780
> > [ 310.133779] ? sock_sendmsg+0xf0/0xf0
> > [ 310.134591] __vfs_write+0x4e0/0x960
> > [ 310.135351] ? kvm_clock_get_cycles+0x1e/0x20
> > [ 310.136160] ? __vfs_read+0x950/0x950
> > [ 310.136931] ? rw_verify_area+0xbd/0x2b0
> > [ 310.137711] vfs_write+0x155/0x4b0
> > [ 310.138454] SyS_write+0xf7/0x240
> > [ 310.139183] ? SyS_read+0x240/0x240
> > [ 310.139922] ? SyS_read+0x240/0x240
> > [ 310.140649] do_syscall_64+0x235/0x5b0
> > [ 310.141390] ? trace_raw_output_sys_exit+0xf0/0xf0
> > [ 310.142204] ? syscall_return_slowpath+0x240/0x240
> > [ 310.143018] ? trace_do_page_fault+0xc4/0x3a0
> > [ 310.143810] ? prepare_exit_to_usermode+0x124/0x160
> > [ 310.144634] ? perf_trace_sys_enter+0x1080/0x1080
> > [ 310.145447] entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.146257] RIP: 0033:0x7f6f868fb070
> > [ 310.146999] RSP: 002b:00007fffed379578 EFLAGS: 00000246 ORIG_RAX:
> > 0000000000000001
> > [ 310.148507] RAX: ffffffffffffffda RBX: 00000000000002e4 RCX:
> > 00007f6f868fb070
> > [ 310.149521] RDX: 00000000000002e4 RSI: 000055603b5cfc10 RDI:
> > 0000000000000003
> > [ 310.150532] RBP: 000055603b5aca60 R08: 0000000000000000 R09:
> > 0000000000003000
> > [ 310.151530] R10: 0000000000000008 R11: 0000000000000246 R12:
> > 0000000000000000
> > [ 310.152537] R13: 00007fffed37960f R14: 000055603a832e31 R15:
> > 0000000000000003
> > [ 310.153578]
> > [ 310.156362] Allocated by task 483:
> > [ 310.157812] save_stack_trace+0x1b/0x20
> > [ 310.159274] save_stack+0x43/0xd0
> > [ 310.160663] kasan_kmalloc+0xad/0xe0
> > [ 310.161943] __kmalloc+0x105/0x230
> > [ 310.163233] __vring_new_virtqueue+0xd1/0xee0
> > [ 310.164623] vring_create_virtqueue+0x2e3/0x5e0
> > [ 310.165536] setup_vq+0x136/0x620
> > [ 310.166286] vp_setup_vq+0x13d/0x6d0
> > [ 310.167059] vp_find_vqs_msix+0x46c/0xb50
> > [ 310.167855] vp_find_vqs+0x71/0x410
> > [ 310.168641] vp_modern_find_vqs+0x21/0x140
> > [ 310.169453] init_vqs+0x957/0x1390 [virtio_net]
> > [ 310.170306] virtnet_restore_up+0x4a/0x590 [virtio_net]
> > [ 310.171214] virtnet_xdp+0x89f/0xdf0 [virtio_net]
> > [ 310.172077] dev_change_xdp_fd+0x1ca/0x420
> > [ 310.172918] do_setlink+0x2c33/0x3bc0
> > [ 310.173703] rtnl_setlink+0x245/0x380
> > [ 310.174511] rtnetlink_rcv_msg+0x530/0x9b0
> > [ 310.175344] netlink_rcv_skb+0x213/0x450
> > [ 310.176166] rtnetlink_rcv+0x28/0x30
> > [ 310.176990] netlink_unicast+0x4a0/0x6c0
> > [ 310.177807] netlink_sendmsg+0x9ec/0xe50
> > [ 310.178646] sock_sendmsg+0xba/0xf0
> > [ 310.179435] SYSC_sendto+0x31d/0x620
> > [ 310.180229] SyS_sendto+0xe/0x10
> > [ 310.181004] do_syscall_64+0x235/0x5b0
> > [ 310.181783] return_from_SYSCALL_64+0x0/0x6a
> > [ 310.182595]
> > [ 310.183217] Freed by task 483:
> > [ 310.183934] save_stack_trace+0x1b/0x20
> > [ 310.184801] save_stack+0x43/0xd0
> > [ 310.187187] kasan_slab_free+0x72/0xc0
> > [ 310.188530] kfree+0x94/0x1a0
> > [ 310.189797] vring_del_virtqueue+0x19a/0x430
> > [ 310.191221] del_vq+0x11c/0x250
> > [ 310.192474] vp_del_vqs+0x379/0xc30
> > [ 310.193772] virtnet_del_vqs+0xad/0xe0 [virtio_net]
> > [ 310.195064] virtnet_xdp+0x836/0xdf0 [virtio_net]
> > [ 310.196231] dev_change_xdp_fd+0x37c/0x420
> > [ 310.197072] do_setlink+0x2c33/0x3bc0
> > [ 310.197804] rtnl_setlink+0x245/0x380
> > [ 310.198530] rtnetlink_rcv_msg+0x530/0x9b0
> > [ 310.199283] netlink_rcv_skb+0x213/0x450
> > [ 310.200036] rtnetlink_rcv+0x28/0x30
> > [ 310.200754] netlink_unicast+0x4a0/0x6c0
> > [ 310.201496] netlink_sendmsg+0x9ec/0xe50
> > [ 310.202236] sock_sendmsg+0xba/0xf0
> > [ 310.202947] SYSC_sendto+0x31d/0x620
> > [ 310.203660] SyS_sendto+0xe/0x10
> > [ 310.204340] do_syscall_64+0x235/0x5b0
> > [ 310.205050] return_from_SYSCALL_64+0x0/0x6a
> > [ 310.205792]
> > [ 310.206350] The buggy address belongs to the object at ffff88006aa64200
> > [ 310.206350] which belongs to the cache kmalloc-8192 of size 8192
> > [ 310.208149] The buggy address is located 32 bytes inside of
> > [ 310.208149] 8192-byte region [ffff88006aa64200, ffff88006aa66200)
> > [ 310.209929] The buggy address belongs to the page:
> > [ 310.210763] page:ffffea0001aa9800 count:1 mapcount:0 mapping: (null)
> > index:0x0 compound_mapcount: 0
> > [ 310.212499] flags: 0x1ffff8000008100(slab|head)
> > [ 310.213373] raw: 01ffff8000008100 0000000000000000 0000000000000000
> > 0000000100030003
> > [ 310.214481] raw: dead000000000100 dead000000000200 ffff88006cc02700
> > 0000000000000000
> > [ 310.215635] page dumped because: kasan: bad access detected
> > [ 310.218989]
> > [ 310.220398] Memory state around the buggy address:
> > [ 310.222141] ffff88006aa64100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> > fc fc
> > [ 310.223996] ffff88006aa64180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> > fc fc
> > [ 310.225469] >ffff88006aa64200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> > fb fb
> > [ 310.227400] ^
> > [ 310.228367] ffff88006aa64280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> > fb fb
> > [ 310.229510] ffff88006aa64300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> > fb fb
> > [ 310.230639]
> > ==================================================================
> > [ 310.231788] Disabling lock debugging due to kernel taint
> > [ 310.233499] kasan: CONFIG_KASAN_INLINE enabled
> > [ 310.236846] kasan: GPF could be caused by NULL-ptr deref or user memory
> > access
> > [ 310.239138] general protection fault: 0000 [#1] SMP KASAN
> > [ 310.240926] Modules linked in: joydev kvm_intel kvm psmouse irqbypass
> > i2c_piix4 qemu_fw_cfg ip_tables x_tables autofs4 serio_raw virtio_balloon
> > pata_acpi virtio_net virtio_blk
> > [ 310.243618] CPU: 0 PID: 352 Comm: sshd Tainted: G B 4.12.0-rc3+ #2
> > [ 310.245780] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> > 1.10.2-20170228_101828-anatol 04/01/2014
> > [ 310.249799] task: ffff880066ca8d80 task.stack: ffff880069e40000
> > [ 310.251090] RIP: 0010:free_old_xmit_skbs.isra.29+0x9d/0x2e0 [virtio_net]
> > [ 310.252403] RSP: 0018:ffff880069e46540 EFLAGS: 00010202
> > [ 310.253631] RAX: 0000000000000000 RBX: 0000000000000000 RCX:
> > 0000000000000004
> > [ 310.255916] RDX: dffffc0000000000 RSI: 0000000000000008 RDI:
> > 0000000000000020
> > [ 310.258017] RBP: ffff880069e465e8 R08: ffff880069e45f10 R09:
> > ffff880066b3c400
> > [ 310.259430] R10: ffff880069e45e98 R11: 1ffff1000cd952f3 R12:
> > ffff880066b3c400
> > [ 310.260797] R13: ffff880066b3c400 R14: ffff88006afc9156 R15:
> > ffff88006afc9001
> > [ 310.262139] FS: 00007f3020f26680(0000) GS:ffff88006d000000(0000)
> > knlGS:0000000000000000
> > [ 310.263564] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [ 310.264825] CR2: 00007efed4534010 CR3: 000000006986d000 CR4:
> > 00000000000006f0
> > [ 310.266178] Call Trace:
> > [ 310.267231] ? virtnet_del_vqs+0xe0/0xe0 [virtio_net]
> > [ 310.268453] ? packet_rcv+0x20d0/0x20d0
> > [ 310.269559] start_xmit+0x1b4/0x1b10 [virtio_net]
> > [ 310.270762] ? default_device_exit+0x2d0/0x2d0
> > [ 310.271910] ? virtnet_remove+0xf0/0xf0 [virtio_net]
> > [ 310.273076] ? update_load_avg+0x1281/0x29f0
> > [ 310.274189] dev_hard_start_xmit+0x1ea/0x7f0
> > [ 310.275295] ? validate_xmit_skb_list+0x100/0x100
> > [ 310.276425] ? validate_xmit_skb+0x7f/0xc10
> > [ 310.277548] ? rb_insert_color+0x1590/0x1590
> > [ 310.280172] ? netif_skb_features+0x920/0x920
> > [ 310.281275] ? __skb_tx_hash+0x2f0/0x2f0
> > [ 310.282362] ? validate_xmit_skb_list+0xa3/0x100
> > [ 310.283494] sch_direct_xmit+0x2eb/0x7a0
> > [ 310.284559] ? dev_deactivate_queue.constprop.29+0x230/0x230
> > [ 310.286448] ? netdev_pick_tx+0x212/0x2b0
> > [ 310.288251] ? __account_cfs_rq_runtime+0x630/0x630
> > [ 310.289707] __dev_queue_xmit+0x12fa/0x20b0
> > [ 310.290788] ? netdev_pick_tx+0x2b0/0x2b0
> > [ 310.291837] ? update_curr+0x1ef/0x750
> > [ 310.292826] ? update_stack_state+0x402/0x780
> > [ 310.293827] ? account_entity_enqueue+0x730/0x730
> > [ 310.294831] ? update_stack_state+0x402/0x780
> > [ 310.295818] ? update_curr_fair+0x70/0x70
> > [ 310.296737] ? entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.297693] ? dequeue_entity+0x27a/0x1520
> > [ 310.298591] ? bpf_prog_alloc+0x320/0x320
> > [ 310.299484] ? yield_to_task_fair+0x110/0x110
> > [ 310.300385] ? unwind_dump+0x4e0/0x4e0
> > [ 310.301246] ? __free_insn_slot+0x600/0x600
> > [ 310.302125] ? unwind_dump+0x4e0/0x4e0
> > [ 310.302975] ? dequeue_task_fair+0xc09/0x2ec0
> > [ 310.303883] dev_queue_xmit+0x10/0x20
> > [ 310.304711] ip_finish_output2+0xacf/0x12a0
> > [ 310.305558] ? dequeue_entity+0x1520/0x1520
> > [ 310.306393] ? ip_fragment.constprop.47+0x220/0x220
> > [ 310.307320] ? save_stack_trace+0x1b/0x20
> > [ 310.308133] ? save_stack+0x43/0xd0
> > [ 310.309081] ? kasan_slab_free+0x72/0xc0
> > [ 310.310614] ? kfree_skbmem+0xb6/0x1d0
> > [ 310.311406] ? tcp_ack+0x2730/0x7450
> > [ 310.312167] ? tcp_rcv_established+0xdbb/0x2db0
> > [ 310.312987] ? tcp_v4_do_rcv+0x2bb/0x7a0
> > [ 310.313769] ? __release_sock+0x14a/0x2b0
> > [ 310.314550] ? release_sock+0xa8/0x270
> > [ 310.315330] ? inet_sendmsg+0x111/0x590
> > [ 310.316100] ? sock_sendmsg+0xba/0xf0
> > [ 310.317403] ? sock_write_iter+0x2e4/0x6a0
> > [ 310.318759] ? __rb_erase_color+0x27d0/0x27d0
> > [ 310.319949] ? rt_cpu_seq_show+0x2d0/0x2d0
> > [ 310.320800] ? update_stack_state+0x402/0x780
> > [ 310.321590] ip_finish_output+0x407/0x880
> > [ 310.322347] ? ip_finish_output+0x407/0x880
> > [ 310.323138] ? update_stack_state+0x402/0x780
> > [ 310.323948] ip_output+0x1c0/0x640
> > [ 310.324661] ? ip_mc_output+0x1350/0x1350
> > [ 310.325415] ? __sk_dst_check+0x164/0x370
> > [ 310.326169] ? complete_formation.isra.53+0xa30/0xa30
> > [ 310.327013] ? __read_once_size_nocheck.constprop.7+0x20/0x20
> > [ 310.327896] ? sock_prot_inuse_add+0xa0/0xa0
> > [ 310.328684] ? memcpy+0x45/0x50
> > [ 310.329393] ? __copy_skb_header+0x1fa/0x280
> > [ 310.330180] ip_local_out+0x70/0x90
> > [ 310.330914] ip_queue_xmit+0x8a1/0x22a0
> > [ 310.331676] ? ip_build_and_send_pkt+0xe80/0xe80
> > [ 310.332517] ? tcp_v4_md5_lookup+0x13/0x20
> > [ 310.333298] tcp_transmit_skb+0x187a/0x3e00
> > [ 310.334085] ? __tcp_select_window+0xaf0/0xaf0
> > [ 310.334887] ? sock_sendmsg+0xba/0xf0
> > [ 310.335637] ? __vfs_write+0x4e0/0x960
> > [ 310.336391] ? vfs_write+0x155/0x4b0
> > [ 310.337135] ? SyS_write+0xf7/0x240
> > [ 310.337861] ? do_syscall_64+0x235/0x5b0
> > [ 310.338612] ? entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.339443] ? sock_sendmsg+0xba/0xf0
> > [ 310.341675] ? do_syscall_64+0x235/0x5b0
> > [ 310.342441] ? entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.343298] ? tcp_init_tso_segs+0x1e0/0x1e0
> > [ 310.344095] ? radix_tree_lookup+0xd/0x10
> > [ 310.344871] ? get_work_pool+0xcd/0x150
> > [ 310.345635] ? check_flush_dependency+0x330/0x330
> > [ 310.346466] tcp_write_xmit+0x498/0x52a0
> > [ 310.347826] ? kasan_unpoison_shadow+0x35/0x50
> > [ 310.349243] ? kasan_kmalloc+0xad/0xe0
> > [ 310.350156] ? tcp_transmit_skb+0x3e00/0x3e00
> > [ 310.351261] ? memset+0x31/0x40
> > [ 310.352054] ? __check_object_size+0x22e/0x55c
> > [ 310.352881] ? skb_pull_rcsum+0x2b0/0x2b0
> > [ 310.353686] ? check_stack_object+0x120/0x120
> > [ 310.354506] ? tcp_v4_md5_lookup+0x13/0x20
> > [ 310.355327] __tcp_push_pending_frames+0x8d/0x2a0
> > [ 310.356174] ? tcp_cwnd_restart+0x169/0x440
> > [ 310.357016] tcp_push+0x47c/0xbd0
> > [ 310.357777] ? copy_from_iter_full+0x21e/0xc70
> > [ 310.358618] ? tcp_splice_data_recv+0x1c0/0x1c0
> > [ 310.359463] ? iov_iter_copy_from_user_atomic+0xeb0/0xeb0
> > [ 310.360355] ? tcp_send_mss+0x24/0x2b0
> > [ 310.361135] tcp_sendmsg+0xd6d/0x43f0
> > [ 310.361908] ? select_estimate_accuracy+0x440/0x440
> > [ 310.362765] ? tcp_sendpage+0x2170/0x2170
> > [ 310.363583] ? set_fd_set.part.1+0x50/0x50
> > [ 310.364392] ? remove_wait_queue+0x196/0x3b0
> > [ 310.365205] ? set_fd_set.part.1+0x50/0x50
> > [ 310.366005] ? add_wait_queue_exclusive+0x290/0x290
> > [ 310.366865] ? __wake_up+0x44/0x50
> > [ 310.367637] ? n_tty_read+0x9f9/0x19d0
> > [ 310.368424] ? update_blocked_averages+0x9a0/0x9a0
> > [ 310.369283] ? __check_object_size+0x22e/0x55c
> > [ 310.370129] inet_sendmsg+0x111/0x590
> > [ 310.371104] ? inet_recvmsg+0x5e0/0x5e0
> > [ 310.372571] ? inet_recvmsg+0x5e0/0x5e0
> > [ 310.373449] sock_sendmsg+0xba/0xf0
> > [ 310.374217] sock_write_iter+0x2e4/0x6a0
> > [ 310.375005] ? core_sys_select+0x47d/0x780
> > [ 310.375822] ? sock_sendmsg+0xf0/0xf0
> > [ 310.376607] __vfs_write+0x4e0/0x960
> > [ 310.377463] ? kvm_clock_get_cycles+0x1e/0x20
> > [ 310.378864] ? __vfs_read+0x950/0x950
> > [ 310.380178] ? rw_verify_area+0xbd/0x2b0
> > [ 310.381092] vfs_write+0x155/0x4b0
> > [ 310.381877] SyS_write+0xf7/0x240
> > [ 310.382616] ? SyS_read+0x240/0x240
> > [ 310.383404] ? SyS_read+0x240/0x240
> > [ 310.384159] do_syscall_64+0x235/0x5b0
> > [ 310.384930] ? trace_raw_output_sys_exit+0xf0/0xf0
> > [ 310.385747] ? syscall_return_slowpath+0x240/0x240
> > [ 310.386564] ? trace_do_page_fault+0xc4/0x3a0
> > [ 310.387424] ? prepare_exit_to_usermode+0x124/0x160
> > [ 310.388524] ? perf_trace_sys_enter+0x1080/0x1080
> > [ 310.389347] entry_SYSCALL64_slow_path+0x25/0x25
> > [ 310.390164] RIP: 0033:0x7f301f83c070
> > [ 310.390906] RSP: 002b:00007ffff738fc78 EFLAGS: 00000246 ORIG_RAX:
> > 0000000000000001
> > [ 310.391943] RAX: ffffffffffffffda RBX: 0000000000000564 RCX:
> > 00007f301f83c070
> > [ 310.392938] RDX: 0000000000000564 RSI: 000055cf87fb0748 RDI:
> > 0000000000000003
> > [ 310.393947] RBP: 000055cf87f8f090 R08: 0000000000000000 R09:
> > 0000000000003000
> > [ 310.394948] R10: 0000000000000008 R11: 0000000000000246 R12:
> > 0000000000000000
> > [ 310.395967] R13: 00007ffff738fd0f R14: 000055cf873dde31 R15:
> > 0000000000000003
> > [ 310.396969] Code: 00 00 48 89 5d d0 31 db 80 3c 02 00 0f 85 05 02 00 00
> > 49 8b 45 00 48 ba 00 00 00 00 00 fc ff df 48 8d 78 20 48 89 f9 48 c1 e9 03
> > <80> 3c 11 00 0f 85 04 02 00 00 48 8b 58 20 48 ba 00 00 00 00 00
> > [ 310.399937] RIP: free_old_xmit_skbs.isra.29+0x9d/0x2e0 [virtio_net] RSP:
> > ffff880069e46540
> > [ 310.401120] ---[ end trace 89c5b0ea3f07debe ]---
> > [ 310.403923] Kernel panic - not syncing: Fatal exception in interrupt
> > [ 310.405942] Kernel Offset: 0x33200000 from 0xffffffff81000000 (relocation
> > range: 0xffffffff80000000-0xffffffffbfffffff)
> > [ 310.408133] ---[ end Kernel panic - not syncing: Fatal exception in
> > interrupt
> >
> >
> > (gdb) l *(free_old_xmit_skbs+0x2b7)
> > 0x22f7 is in free_old_xmit_skbs (drivers/net/virtio_net.c:1051).
> > 1046
> > 1047 static void free_old_xmit_skbs(struct send_queue *sq)
> > 1048 {
> > 1049 struct sk_buff *skb;
> > 1050 unsigned int len;
> > 1051 struct virtnet_info *vi = sq->vq->vdev->priv;
> > 1052 struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
> > 1053 unsigned int packets = 0;
> > 1054 unsigned int bytes = 0;
> > 1055
> >
> > Let me know if i need to provide more informations.
> >
> > Best regards.
> >
> > Jean-Philippe
>
> So del_vq done during xdp setup seems to race with regular xmit.
>
> Since commit 680557cf79f82623e2c4fd42733077d60a843513
> virtio_net: rework mergeable buffer handling
>
> we no longer must do the resets, we now have enough space
> to store a bit saying whether a buffer is xdp one or not.
>
> And that's probably a cleaner way to fix these issues than
> try to find and fix the race condition.
>
> John?
>
> --
> MST
I think I see the source of the race. virtio net calls
netif_device_detach and assumes no packets will be sent after
this point. However, all it does is stop all queues so
no new packets will be transmitted.
Try locking with HARD_TX_LOCK?
--
MST
^ permalink raw reply
* [PATCH] net: ethernet: ti: cpdma: do not enable host error misc irq
From: Grygorii Strashko @ 2017-06-05 23:23 UTC (permalink / raw)
To: David S. Miller, netdev, Sekhar Nori
Cc: linux-kernel, linux-omap, Grygorii Strashko
CPSW driver does not handle this interrupt, so there are no reasons to enable
it in hardware.
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/net/ethernet/ti/davinci_cpdma.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 7ecc6b7..e4d6edf 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -645,7 +645,7 @@ EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
{
unsigned long flags;
- int i, reg;
+ int i;
spin_lock_irqsave(&ctlr->lock, flags);
if (ctlr->state != CPDMA_STATE_ACTIVE) {
@@ -653,9 +653,6 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
return -EINVAL;
}
- reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
- dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
-
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
if (ctlr->channels[i])
cpdma_chan_int_ctrl(ctlr->channels[i], enable);
--
2.10.1
^ 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