* Re: [PATCH net-next] net: metrics: add proper netlink validation
From: Eric Dumazet @ 2018-06-04 23:58 UTC (permalink / raw)
To: David Ahern, Eric Dumazet, David S . Miller; +Cc: netdev
In-Reply-To: <abaa5381-157f-b66d-5f57-58436908bea4@gmail.com>
On 06/04/2018 04:54 PM, David Ahern wrote:
> On 6/4/18 4:46 PM, Eric Dumazet wrote:
>> Before using nla_get_u32(), better make sure the attribute
>> is of the proper size.
>>
>> Code recently was changed, but bug has been there from beginning
>> of git.
>>
> ...
>>
>> Fixes: a919525ad832 ("net: Move fib_convert_metrics to metrics file")
>
> That commit just moved the code from 1 file to another. The previous
> commit id is 6cf9dfd3bd62e, but it just moved code to a helper. The
> originating commit id for the ip_metrics_convert bug is:
>
Please read what I wrote.
I simply wanted to warn stable teams that your this patch is based on recent tree,
but bug has been there forever.
The Fixes: tag might help them to cook proper backports, thats is all.
A Fixes: tag does not blame the code, it simply gives some hints.
> ea697639992d9 ("net: tcp: add RTAX_CC_ALGO fib handling")
>
This patch has not added any bug, it was there already.
I can put a (long) list of tags, but ultimately the bug has been there forever.
^ permalink raw reply
* Re: [PATCH net-next v11 03/10] netdev: cavium: octeon: Add Octeon III BGX Ethernet Nexus
From: Andrew Lunn @ 2018-06-05 0:10 UTC (permalink / raw)
To: Steven J. Hill; +Cc: netdev, Carlos Munoz
In-Reply-To: <1528149617-8964-4-git-send-email-steven.hill@cavium.com>
> + /* Connect to PKI/PKO */
> + data = oct_csr_read(BGX_CMR_CONFIG(numa_node, interface, port));
> + if (is_mix)
> + data |= BIT(11);
> + else
> + data &= ~BIT(11);
> + oct_csr_write(data, BGX_CMR_CONFIG(numa_node, interface, port));
> +
Hi Steven
This driver has quite a lot of magic BIT macros. Can you add some
#defines with useful names?
Thanks
Andrew
^ permalink raw reply
* Re: [PATCH net-next v11 04/10] netdev: cavium: octeon: Add Octeon III BGX Ports
From: Andrew Lunn @ 2018-06-05 0:55 UTC (permalink / raw)
To: Steven J. Hill; +Cc: netdev, Carlos Munoz
In-Reply-To: <1528149617-8964-5-git-send-email-steven.hill@cavium.com>
> + if (status.link) {
> + /* Always full duplex */
> + status.duplex = DUPLEX_FULL;
> +
> + /* Speed */
> + speed = bgx_port_get_qlm_speed(priv, priv->qlm);
> + data = oct_csr_read(BGX_CMR_CONFIG(priv->node, priv->bgx,
> + priv->index));
> + switch ((data >> 8) & 7) {
> + default:
> + case 1:
> + speed = (speed * 8 + 5) / 10;
> + lanes = 4;
> + break;
Hi Steven
Here you add 5, which you did not in the other function dealing with
speed...
> + priv->phydev = of_phy_connect(netdev, priv->phy_np,
> + bgx_port_adjust_link, 0,
> + PHY_INTERFACE_MODE_SGMII);
> + if (!priv->phydev)
> + return -ENODEV;
> +
> + netif_carrier_off(netdev);
> +
> + if (priv->phydev)
> + phy_start_aneg(priv->phydev);
> + }
If you are using phylib, you should not need to make calls to
netif_carrier_*(). The phylib will do it for you.
Why hard code passing PHY_INTERFACE_MODE_SGMII? You also support
RGMII? It would be better to use of_get_phy_mode().
> +int bgx_port_change_mtu(struct net_device *netdev, int new_mtu)
> +{
> + struct bgx_port_priv *priv = bgx_port_netdev2priv(netdev);
> + int max_frame;
> +
> + if (new_mtu < 60 || new_mtu > 65392) {
> + netdev_warn(netdev, "Maximum MTU supported is 65392\n");
> + return -EINVAL;
> + }
The core can check this for you, if you tell it the MAX and Min.
Andrew
^ permalink raw reply
* Re: [PATCH 10/18] rhashtable: remove rhashtable_walk_peek()
From: NeilBrown @ 2018-06-05 1:00 UTC (permalink / raw)
To: Tom Herbert
Cc: Herbert Xu, Thomas Graf, Linux Kernel Network Developers, LKML,
Tom Herbert
In-Reply-To: <CALx6S35sf4oj=x73SfhUxi1e9-u4Stxgr9BAj5E7KKmbufntwg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2673 bytes --]
On Mon, Jun 04 2018, Tom Herbert wrote:
>>
>> Maybe a useful way forward would be for you to write documentation for
>> the rhashtable_walk_peek() interface which correctly describes what it
>> does and how it is used. Given that, I can implement that interface
>> with the stability improvements that I'm working on.
>>
>
> Here's how it's documented currently:
>
> "rhashtable_walk_peek - Return the next object but don't advance the iterator"
>
> I don't see what is incorrect about that.
rhashtable_walk_next is documented:
* rhashtable_walk_next - Return the next object and advance the iterator
So it seems reasonable to assume that you get the same object, no matter
which one you call. Yet this is not (necessarily) the case.
> Peek returns the next object
> in the walk, however does not move the iterator past that object, so
> sucessive calls to peek return the same object. In other words it's a
> way to inspect the next object but not "consume" it. This is what is
> needed when netlink returns in the middle of a walk. The last object
> retrieved from the table may not have been processed completely, so it
> needs to be the first one processed on the next invocation to netlink.
I completely agree with this last sentence.
We typically need to process the last object retrieved. This could also
be described as the previously retrieved object.
So rhashtable_walk_last() and rhashtable_walk_prev() might both be
suitable names, though each is open to misinterpretation.
I fail to see how the "last object retrieved" could be the same as
"the next object" which rhashtable_walk_peek claims to return.
>
> This is also easily distinguishable from
>
> "rhashtable_walk_next - Return the next object and advance the iterator"
>
> Where the only difference is that peek and walk is that, walk advances
> the iterator and peek does not. Hence why "peek" is a descriptive name
> for what is happening.
Maybe if we step back and go for a totally different API.
We could change rhashtable_walk_start() to return the object that was
current (most recently returned) when rhashtable_walk_stop() was called,
if it is still in the table, otherwise it returns NULL (as it would the
first time it was called).
This loses the option for rhashtable_walk_start() to return -EAGAIN, but
I would rather than rhashtable_walk_next() were the only thing to return
that.
The only time it really makes sense to call rhashtable_walk_peek() is
immediately after rhashtable_walk_start(), and this change would make
that fact clear in the API.
Thanks,
NeilBrown
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply
* Re: [net-next 00/12][pull request] Intel Wired LAN Driver Updates 2018-06-04
From: David Miller @ 2018-06-05 1:09 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, nhorman, sassmann, jogreene
In-Reply-To: <20180604175644.24293-1-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Mon, 4 Jun 2018 10:56:32 -0700
> This series contains a smorgasbord of updates to documentation, e1000e,
> igb, ixgbe, ixgbevf and i40e.
...
> The following are changes since commit 8284fd4cb85577eecca024fe1e7a35b39ed0f3f5:
> Merge branch 'selftests-net-various'
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue 10GbE
Pulled, thanks Jeff.
^ permalink raw reply
* Re: [PATCH 10/18] rhashtable: remove rhashtable_walk_peek()
From: NeilBrown @ 2018-06-05 1:24 UTC (permalink / raw)
To: Tom Herbert, Tom Herbert
Cc: Herbert Xu, Thomas Graf, Linux Kernel Network Developers, LKML
In-Reply-To: <CAPDqMeo0hV+-ijYPKhpzpHWVovYrS7s22tBfUZTfvXvNv_qpXw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 7501 bytes --]
On Mon, Jun 04 2018, Tom Herbert wrote:
> On Mon, Jun 4, 2018 at 2:31 PM, Tom Herbert <tom@herbertland.com> wrote:
>> On Sun, Jun 3, 2018 at 7:09 PM, NeilBrown <neilb@suse.com> wrote:
>>> On Sun, Jun 03 2018, Tom Herbert wrote:
>>>
>>>> On Sun, Jun 3, 2018 at 5:30 PM, NeilBrown <neilb@suse.com> wrote:
>>>>> On Sat, Jun 02 2018, Herbert Xu wrote:
>>>>>
>>>>>> On Fri, Jun 01, 2018 at 02:44:09PM +1000, NeilBrown wrote:
>>>>>>> This function has a somewhat confused behavior that is not properly
>>>>>>> described by the documentation.
>>>>>>> Sometimes is returns the previous object, sometimes it returns the
>>>>>>> next one.
>>>>>>> Sometimes it changes the iterator, sometimes it doesn't.
>>>>>>>
>>>>>>> This function is not currently used and is not worth keeping, so
>>>>>>> remove it.
>>>>>>>
>>>>>>> A future patch will introduce a new function with a
>>>>>>> simpler interface which can meet the same need that
>>>>>>> this was added for.
>>>>>>>
>>>>>>> Signed-off-by: NeilBrown <neilb@suse.com>
>>>>>>
>>>>>> Please keep Tom Herbert in the loop. IIRC he had an issue with
>>>>>> this patch.
>>>>>
>>>>> Yes you are right - sorry for forgetting to add Tom.
>>>>>
>>>>> My understanding of where this issue stands is that Tom raised issue and
>>>>> asked for clarification, I replied, nothing further happened.
>>>>>
>>>>> It summary, my position is that:
>>>>> - most users of my new rhashtable_walk_prev() will use it like
>>>>> rhasthable_talk_prev() ?: rhashtable_walk_next()
>>>>> which is close to what rhashtable_walk_peek() does
>>>>> - I know of no use-case that could not be solved if we only had
>>>>> the combined operation
>>>>> - BUT it is hard to document the combined operation, as it really
>>>>> does two things. If it is hard to document, then it might be
>>>>> hard to understand.
>>>>>
>>>>> So provide the most understandable/maintainable solution, I think
>>>>> we should provide rhashtable_walk_prev() as a separate interface.
>>>>>
>>>> I'm still missing why requiring two API operations instead of one is
>>>> simpler or easier to document. Also, I disagree that
>>>> rhashtable_walk_peek does two things-- it just does one which is to
>>>> return the current element in the walk without advancing to the next
>>>> one. The fact that the iterator may or may not move is immaterial in
>>>> the API, that is an implementation detail. In fact, it's conceivable
>>>> that we might completely reimplement this someday such that the
>>>> iterator works completely differently implementation semantics but the
>>>> API doesn't change. Also the naming in your proposal is confusing,
>>>> we'd have operations to get the previous, and the next next object--
>>>> so the user may ask where's the API to get the current object in the
>>>> walk? The idea that we get it by first trying to get the previous
>>>> object, and then if that fails getting the next object seems
>>>> counterintuitive.
>>>
>>> To respond to your points out of order:
>>>
>>> - I accept that "rhashtable_walk_prev" is not a perfect name. It
>>> suggests a stronger symmetry with rhasthable_walk_next than actually
>>> exist. I cannot think of a better name, but I think the
>>> description "Return the previously returned object if it is
>>> still in the table" is clear and simple and explains the name.
>>> I'm certainly open to suggestions for a better name.
>>>
>>> - I don't think it is meaningful to talk about a "current" element in a
>>> table where asynchronous insert/remove is to be expected.
>>> The best we can hope for is a "current location" is the sequence of
>>> objects in the table - a location which is after some objects and
>>> before all others. rhashtable_walk_next() returns the next object
>>> after the current location, and advances the location pointer past
>>> that object.
>>> rhashtable_walk_prev() *doesn't* return the previous object in the
>>> table. It returns the previously returned object. ("previous" in
>>> time, but not in space, if you like).
>>>
>>> - rhashtable_walk_peek() currently does one of two different things.
>>> It either returns the previously returned object (iter->p) if that
>>> is still in the table, or it find the next object, steps over it, and
>>> returns it.
>>>
>>> - I would like to suggest that when an API acts on a iterator object,
>>> the question of whether or not the iterator is advanced *must* be a
>>> fundamental question, not one that might change from time to time.
>>>
>>> Maybe a useful way forward would be for you to write documentation for
>>> the rhashtable_walk_peek() interface which correctly describes what it
>>> does and how it is used. Given that, I can implement that interface
>>> with the stability improvements that I'm working on.
>>>
>>
>> Here's how it's documented currently:
>>
>> "rhashtable_walk_peek - Return the next object but don't advance the iterator"
>>
>> I don't see what is incorrect about that. Peek returns the next object
>> in the walk, however does not move the iterator past that object, so
>> sucessive calls to peek return the same object. In other words it's a
>> way to inspect the next object but not "consume" it. This is what is
>> needed when netlink returns in the middle of a walk. The last object
>> retrieved from the table may not have been processed completely, so it
>> needs to be the first one processed on the next invocation to netlink.
>>
>> This is also easily distinguishable from
>>
>> "rhashtable_walk_next - Return the next object and advance the iterator"
>>
>> Where the only difference is that peek and walk is that, walk advances
>> the iterator and peek does not. Hence why "peek" is a descriptive name
>> for what is happening.
>>
>
> btw, we are using rhashtable_walk_peek with ILA code that hasn't been
> upstreamed yet. I'll (re)post the patches shortly, this demonstates
> why we need the peek functionality. If you think that
> rhashtable_walk_peek is nothing more than an inline that does "return
> rhashtable_walk_prev(iter) ? : rhashtable_walk_next(iter);" then maybe
> we could redefine rhashtable_walk_peek to be that. But, then I'll ask
> what the use case is for rhashtable_walk_prev as a standalone
> function? We created rhashtable_walk_peek for the netlink walk problem
> and I don't think any of the related use cases would ever call
> rhashtable_walk_prev without the rhashtable_walk_next fallback.
I think I did describe my particular use-case for rhashtable_walk_prev()
before, but it probably got buried in other things.
Lustre has a debugfs file which lists all the cached pages in all the
objects which are stored in a hash table.
It might get part-way through listing the cached pages for one object,
and then have to take a break (rhashtable_walk_stop()) until more output
space is available.
When it restarts, it needs to pick up where it left off.
If the same object is still in the cache, it needs to start at the page
address that it was up to. If the object is gone and it has to move on
to the next object, then it needs to start at page zero.
So I would do something like:
rhashtable_walk_start(hashtab, &state->riter);
obj = rhashtable_walk_prev(&state->riter);
addr = state->addr;
if (!obj) {
obj = rhashtable_walk_next(state->riter);
addr = 0;
}
then repeatedly format(obj,addr) and incrment addr or
(if past end-of-object) call rhashtable_walk_next and addr=0.
then
addr->addr = addr - 1;
rhashtable_walk_stop();
Thanks,
NeilBrown
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply
* [PATCH net-next v2] net: ipv6: Generate random IID for addresses on RAWIP devices
From: Subash Abhinov Kasiviswanathan @ 2018-06-05 1:26 UTC (permalink / raw)
To: davem, netdev, yoshfuji; +Cc: Subash Abhinov Kasiviswanathan, Sean Tranchetti
RAWIP devices such as rmnet do not have a hardware address and
instead require the kernel to generate a random IID for the
IPv6 addresses.
Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
v1->v2: Yoshfuji suggested to update the I/G and G/L bit.
Similar functionality is already implemented by addrconf_ifid_ip6tnl()
so use it.
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 4 ++++
net/ipv6/addrconf.c | 4 +++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
index cb02e1a..b9a7548 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -221,6 +221,10 @@ void rmnet_vnd_setup(struct net_device *rmnet_dev)
rmnet_dev->needs_free_netdev = true;
rmnet_dev->ethtool_ops = &rmnet_ethtool_ops;
+
+ /* This perm addr will be used as interface identifier by IPv6 */
+ rmnet_dev->addr_assign_type = NET_ADDR_RANDOM;
+ eth_random_addr(rmnet_dev->perm_addr);
}
/* Exposed API */
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f09afc2..5596d87 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2251,6 +2251,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
return addrconf_ifid_ieee1394(eui, dev);
case ARPHRD_TUNNEL6:
case ARPHRD_IP6GRE:
+ case ARPHRD_RAWIP:
return addrconf_ifid_ip6tnl(eui, dev);
}
return -1;
@@ -3286,7 +3287,8 @@ static void addrconf_dev_config(struct net_device *dev)
(dev->type != ARPHRD_IP6GRE) &&
(dev->type != ARPHRD_IPGRE) &&
(dev->type != ARPHRD_TUNNEL) &&
- (dev->type != ARPHRD_NONE)) {
+ (dev->type != ARPHRD_NONE) &&
+ (dev->type != ARPHRD_RAWIP)) {
/* Alas, we support only Ethernet autoconfiguration. */
return;
}
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v2] net: qualcomm: rmnet: Fix use after free while sending command ack
From: Subash Abhinov Kasiviswanathan @ 2018-06-05 1:43 UTC (permalink / raw)
To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
When sending an ack to a command packet, the skb is still referenced
after it is sent to the real device. Since the real device could
free the skb, the device pointer would be invalid.
Also, remove an unnecessary variable.
Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation")
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
v1->v2: Rebase change on net-next instead as mentioned by David.
Also remove an unnecessary variable.
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
index 56a93df..3ee8ae9 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
@@ -67,7 +67,7 @@ static void rmnet_map_send_ack(struct sk_buff *skb,
struct rmnet_port *port)
{
struct rmnet_map_control_command *cmd;
- int xmit_status;
+ struct net_device *dev = skb->dev;
if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)
skb_trim(skb,
@@ -78,9 +78,9 @@ static void rmnet_map_send_ack(struct sk_buff *skb,
cmd = RMNET_MAP_GET_CMD_START(skb);
cmd->cmd_type = type & 0x03;
- netif_tx_lock(skb->dev);
- xmit_status = skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev);
- netif_tx_unlock(skb->dev);
+ netif_tx_lock(dev);
+ dev->netdev_ops->ndo_start_xmit(skb, dev);
+ netif_tx_unlock(dev);
}
/* Process MAP command frame and send N/ACK message as appropriate. Message cmd
--
1.9.1
^ permalink raw reply related
* Re: AF_XDP. Was: [net-next 00/12][pull request] Intel Wired LAN Driver Updates 2018-06-04
From: Alexander Duyck @ 2018-06-05 1:45 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David Miller, Björn Töpel, Karlsson, Magnus,
Alexei Starovoitov, Daniel Borkmann, Or Gerlitz, Jeff Kirsher,
Netdev
In-Reply-To: <20180604233224.hjuh2hcbsnsn2lwr@ast-mbp>
On Mon, Jun 4, 2018 at 4:32 PM, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
> On Mon, Jun 04, 2018 at 03:02:31PM -0700, Alexander Duyck wrote:
>> On Mon, Jun 4, 2018 at 2:27 PM, David Miller <davem@davemloft.net> wrote:
>> > From: Or Gerlitz <gerlitz.or@gmail.com>
>> > Date: Tue, 5 Jun 2018 00:11:35 +0300
>> >
>> >> Just to make sure, is the AF_XDP ZC (Zero Copy) UAPI going to be
>> >> merged for this window -- AFAIU from [1], it's still under
>> >> examination/development/research for non Intel HWs, am I correct or
>> >> this is going to get in now?
>> >
>> > All of the pending AF_XDP changes will be merged this merge window.
>> >
>> > I think Intel folks need to review things as fast as possible because
>> > I pretty much refuse to revert the series or disable it in Kconfig at
>> > this point.
>> >
>> > Thank you.
>>
>> My understanding of things is that the current AF_XDP patches were
>> going to be updated to have more of a model agnostic API such that
>> they would work for either the "typewriter" mode or the descriptor
>> ring based approach. The current plan was to have the zero copy
>> patches be a follow-on after the vendor agnostic API bits in the
>> descriptors and such had been sorted out. I believe you guys have the
>> descriptor fixes already right?
>>
>> In my opinion the i40e code isn't mature enough yet to really go into
>> anything other than maybe net-next in a couple weeks. We are going to
>> need a while to get adequate testing in order to flush out all the
>> bugs and performance regressions we are likely to see coming out of
>> this change.
>
> I think the work everyone did in this release cycle increased my confidence
> that the way descriptors are defined and the rest of uapi are stable enough
> and i40e zero copy bits can land in the next release without uapi changes.
> In that sense even if we merge i40e parts now, the other nic vendors
> will be in the same situation and may find things that they would like
> to improve in uapi.
> So I propose we merge the first 7 patches of the last series now and
> let 3 remaining i40e patches go via intel trees for the next release.
> In the mean time other NIC vendors should start actively working
> on AF_XDP support as well.
> If somehow uapi would need tweaks, we can still do minor adjustments
> since 4.18 won't be released for ~10 weeks.
>
That works for me. Actually I think patch 11 can probably be included
as well since that is just sample code and could probably be used by
whatever drivers end up implementing this.
Thanks.
- Alex
^ permalink raw reply
* Re: [PATCH net-next] net: phy: broadcom: Enable 125 MHz clock on LED4 pin for BCM54612E by default.
From: Florian Fainelli @ 2018-06-05 1:45 UTC (permalink / raw)
To: Kun Yi, davem
Cc: netdev, Avi.Fishman, tali.perry, tomer.maimon, benjaminfair,
rlippert
In-Reply-To: <20180604201704.238472-1-kunyi@google.com>
Le 06/04/18 à 13:17, Kun Yi a écrit :
> BCM54612E have 4 multi-functional LED pins that can be configured
> through register setting; the LED4 pin can be configured to a 125MHz
> reference clock output by setting the spare register. Since the dedicated
> CLK125 reference clock pin is not brought out on the 48-Pin MLP, the LED4
> pin is the only pin to provide such function in this package, and therefore
> it is beneficial to just enable the reference clock by default.
Checked the data sheet and this appears to be absolutely correct:
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian
^ permalink raw reply
* [RFC PATCH] net: aquantia: hw_atl_utils_mpi_set_state() can be static
From: kbuild test robot @ 2018-06-05 10:22 UTC (permalink / raw)
To: Igor Russkikh
Cc: kbuild-all, David S . Miller, netdev, David Arcari, Pavel Belous,
Igor Russkikh
In-Reply-To: <cea8a6dadd0ddd48fd08c3c3b244fd4db149bf50.1527596210.git.igor.russkikh@aquantia.com>
Fixes: 45c5c36aa288 ("net: aquantia: Improve adapter init/deinit logic")
Signed-off-by: kbuild test robot <fengguang.wu@intel.com>
---
hw_atl_utils.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index 9d0a96d..3d60a48 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -533,8 +533,8 @@ int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
return 0;
}
-int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
- enum hal_atl_utils_fw_state_e state)
+static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
+ enum hal_atl_utils_fw_state_e state)
{
int err = 0;
u32 transaction_id = 0;
^ permalink raw reply related
* Re: [PATCH net-next 2/5] net: aquantia: Improve adapter init/deinit logic
From: kbuild test robot @ 2018-06-05 10:22 UTC (permalink / raw)
To: Igor Russkikh
Cc: kbuild-all, David S . Miller, netdev, David Arcari, Pavel Belous,
Igor Russkikh
In-Reply-To: <cea8a6dadd0ddd48fd08c3c3b244fd4db149bf50.1527596210.git.igor.russkikh@aquantia.com>
Hi Igor,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Igor-Russkikh/net-aquantia-Ethtool-based-ring-size-configuration/20180601-044445
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c:525:5: sparse: symbol 'hw_atl_utils_mpi_set_speed' was not declared. Should it be static?
>> drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c:536:5: sparse: symbol 'hw_atl_utils_mpi_set_state' was not declared. Should it be static?
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* [PATCH net-next] net/mlx5e: Make function mlx5e_change_rep_mtu() static
From: Wei Yongjun @ 2018-06-05 2:42 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Adi Nissim
Cc: Wei Yongjun, netdev, linux-rdma, kernel-janitors
Fixes the following sparse warning:
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c:903:5: warning:
symbol 'mlx5e_change_rep_mtu' was not declared. Should it be static?
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 3857f22..57987f6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -900,7 +900,7 @@ int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
.switchdev_port_attr_get = mlx5e_attr_get,
};
-int mlx5e_change_rep_mtu(struct net_device *netdev, int new_mtu)
+static int mlx5e_change_rep_mtu(struct net_device *netdev, int new_mtu)
{
return mlx5e_change_mtu(netdev, new_mtu, NULL);
}
^ permalink raw reply related
* [PATCH net-next] net/mlx5e: fix error return code in mlx5e_alloc_rq()
From: Wei Yongjun @ 2018-06-05 2:42 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan
Cc: Wei Yongjun, netdev, linux-rdma, kernel-janitors
Fix to return error code -ENOMEM from the kvzalloc_node() error handling
case instead of 0, as done elsewhere in this function.
Fixes: 069d11465a80 ("net/mlx5e: RX, Enhance legacy Receive Queue memory scheme")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 333d4ed..89c96a0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -566,8 +566,10 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
kvzalloc_node((wq_sz << rq->wqe.info.log_num_frags) *
sizeof(*rq->wqe.frags),
GFP_KERNEL, cpu_to_node(c->cpu));
- if (!rq->wqe.frags)
+ if (!rq->wqe.frags) {
+ err = -ENOMEM;
goto err_free;
+ }
err = mlx5e_init_di_list(rq, params, wq_sz, c->cpu);
if (err)
^ permalink raw reply related
* [PATCH net-next] bpfilter: switch to CC from HOSTCC
From: Alexei Starovoitov @ 2018-06-05 2:53 UTC (permalink / raw)
To: David S . Miller
Cc: daniel, netdev, linux-kernel, kernel-team, arnd, yamada.masahiro
check that CC can build executables and use that compiler instead of HOSTCC
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
Makefile | 5 +++++
net/Makefile | 4 ++++
net/bpfilter/Makefile | 2 ++
scripts/cc-can-link.sh | 11 +++++++++++
4 files changed, 22 insertions(+)
create mode 100755 scripts/cc-can-link.sh
diff --git a/Makefile b/Makefile
index 56ba070dfa09..62c110084fae 100644
--- a/Makefile
+++ b/Makefile
@@ -510,6 +510,11 @@ ifeq ($(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $
KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
endif
+ifeq ($(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/cc-can-link.sh $(CC)), y)
+ CC_CAN_LINK := y
+ export CC_CAN_LINK
+endif
+
ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
diff --git a/net/Makefile b/net/Makefile
index bdaf53925acd..13ec0d5415c7 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -20,7 +20,11 @@ obj-$(CONFIG_TLS) += tls/
obj-$(CONFIG_XFRM) += xfrm/
obj-$(CONFIG_UNIX) += unix/
obj-$(CONFIG_NET) += ipv6/
+ifneq ($(CC_CAN_LINK),y)
+$(warning CC cannot link executables. Skipping bpfilter.)
+else
obj-$(CONFIG_BPFILTER) += bpfilter/
+endif
obj-$(CONFIG_PACKET) += packet/
obj-$(CONFIG_NET_KEY) += key/
obj-$(CONFIG_BRIDGE) += bridge/
diff --git a/net/bpfilter/Makefile b/net/bpfilter/Makefile
index 3f3cb87c668f..aafa72001fcd 100644
--- a/net/bpfilter/Makefile
+++ b/net/bpfilter/Makefile
@@ -6,6 +6,8 @@
hostprogs-y := bpfilter_umh
bpfilter_umh-objs := main.o
HOSTCFLAGS += -I. -Itools/include/ -Itools/include/uapi
+HOSTCC := $(CC)
+
ifeq ($(CONFIG_BPFILTER_UMH), y)
# builtin bpfilter_umh should be compiled with -static
# since rootfs isn't mounted at the time of __init
diff --git a/scripts/cc-can-link.sh b/scripts/cc-can-link.sh
new file mode 100755
index 000000000000..208eb2825dab
--- /dev/null
+++ b/scripts/cc-can-link.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+cat << "END" | $@ -x c - -o /dev/null >/dev/null 2>&1 && echo "y"
+#include <stdio.h>
+int main(void)
+{
+ printf("");
+ return 0;
+}
+END
--
2.9.5
^ permalink raw reply related
* RE: [PATCH 09/10] dpaa_eth: add support for hardware timestamping
From: Y.b. Lu @ 2018-06-05 3:35 UTC (permalink / raw)
To: Richard Cochran
Cc: netdev@vger.kernel.org, Madalin-cristian Bucur, Rob Herring,
Shawn Guo, David S . Miller, devicetree@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20180604134920.ezhe6jz5ntpnqyzj@localhost>
Hi Richard,
> -----Original Message-----
> From: Richard Cochran [mailto:richardcochran@gmail.com]
> Sent: Monday, June 4, 2018 9:49 PM
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; Madalin-cristian Bucur
> <madalin.bucur@nxp.com>; Rob Herring <robh+dt@kernel.org>; Shawn Guo
> <shawnguo@kernel.org>; David S . Miller <davem@davemloft.net>;
> devicetree@vger.kernel.org; linuxppc-dev@lists.ozlabs.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 09/10] dpaa_eth: add support for hardware timestamping
>
> On Mon, Jun 04, 2018 at 03:08:36PM +0800, Yangbo Lu wrote:
>
> > +if FSL_DPAA_ETH
> > +config FSL_DPAA_ETH_TS
> > + bool "DPAA hardware timestamping support"
> > + select PTP_1588_CLOCK_QORIQ
> > + default n
> > + help
> > + Enable DPAA hardware timestamping support.
> > + This option is useful for applications to get
> > + hardware time stamps on the Ethernet packets
> > + using the SO_TIMESTAMPING API.
> > +endif
>
> You should drop this #ifdef. In general, if a MAC supports time stamping and
> PHC, then the driver support should simply be compiled in.
>
> [ When time stamping incurs a large run time performance penalty to
> non-PTP users, then it might make sense to have a Kconfig option to
> disable it, but that doesn't appear to be the case here. ]
[Y.b. Lu] Actually these timestamping codes affected DPAA networking performance in our previous performance test.
That's why we used ifdef for it.
>
> > @@ -1615,6 +1635,24 @@ static int dpaa_eth_refill_bpools(struct
> dpaa_priv *priv)
> > skbh = (struct sk_buff **)phys_to_virt(addr);
> > skb = *skbh;
> >
> > +#ifdef CONFIG_FSL_DPAA_ETH_TS
> > + if (priv->tx_tstamp &&
> > + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
>
> This condition fits on one line easily.
[Y.b. Lu] Right. I will use one line in next version.
>
> > + struct skb_shared_hwtstamps shhwtstamps;
> > + u64 ns;
>
> Local variables belong at the top of the function.
[Y.b. Lu] Ok, will move them to the top in next verison.
>
> > + memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> > +
> > + if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> > + priv->mac_dev->port[TX],
> > + (void *)skbh)) {
> > + shhwtstamps.hwtstamp = ns_to_ktime(ns);
> > + skb_tstamp_tx(skb, &shhwtstamps);
> > + } else {
> > + dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
> > + }
> > + }
> > +#endif
> > if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
> > nr_frags = skb_shinfo(skb)->nr_frags;
> > dma_unmap_single(dev, addr, qm_fd_get_offset(fd) + @@ -2086,6
> > +2124,14 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct
> net_device *net_dev)
> > if (unlikely(err < 0))
> > goto skb_to_fd_failed;
> >
> > +#ifdef CONFIG_FSL_DPAA_ETH_TS
> > + if (priv->tx_tstamp &&
> > + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
>
> One line please.
[Y.b. Lu] No problem.
>
> > + fd.cmd |= FM_FD_CMD_UPD;
> > + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> > + }
> > +#endif
> > +
> > if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
> > return NETDEV_TX_OK;
> >
>
> Thanks,
> Richard
^ permalink raw reply
* [PATCH net] failover: eliminate callback hell
From: Stephen Hemminger @ 2018-06-05 3:42 UTC (permalink / raw)
To: kys, haiyangz, davem, mst, sridhar.samudrala; +Cc: netdev, Stephen Hemminger
The net failover should be a simple library, not a virtual
object with function callbacks (see callback hell).
The code is simpler is smaller both for the netvsc and virtio use case.
The code is restructured in many ways. I should have given these
as review comments to net_failover during review
but did not want to overwhelm the original submitter.
Therefore it was merged prematurely.
Some of the many items changed are:
* The support routines should just be selected as needed in
kernel config, no need for them to be visible config items.
* Both netvsc and net_failover should keep their list of their
own devices. Not a common list.
* The matching of secondary device to primary device policy
is up to the network device. Both net_failover and netvsc
will use MAC for now but can change separately.
* The match policy is only used during initial discovery; after
that the secondary device knows what the upper device is because
of the parent/child relationship; no searching is required.
* Now, netvsc and net_failover use the same delayed work type
mechanism for setup. Previously, net_failover code was triggering off
name change but a similar policy was rejected for netvsc.
"what is good for the goose is good for the gander"
* The net_failover private device info 'struct net_failover_info'
should have been private to the driver file, not a visible
API.
* The net_failover device should use SET_NETDEV_DEV
that is intended only for physical devices not virtual devices.
* No point in having DocBook style comments on a driver file.
They only make sense on an external exposed API.
* net_failover only supports Ethernet, so use ether_addr_copy.
* Set permanent and current address of net_failover device
to match the primary.
* Carrier should be marked off before registering device
the net_failover device.
* Use netdev_XXX for log messages, in net_failover (not dev_xxx)
* Since failover infrastructure is about linking devices just
use RTNL no need for other locking in init and teardown.
* Don't bother with ERR_PTR() style return if only possible
return is success or no memory.
* As much as possible, the terms master and slave should be avoided
because of their cultural connotations.
Note; this code has been tested on Hyper-V
but is compile tested only on virtio.
Fixes: 30c8bd5aa8b2 ("net: Introduce generic failover module")
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
---
Although this patch needs to go into 4.18 (linux-net),
this version is based against net-next because net-next
hasn't been merged into linux-net yet.
drivers/net/hyperv/hyperv_net.h | 3 +-
drivers/net/hyperv/netvsc_drv.c | 173 +++++++++++------
drivers/net/net_failover.c | 312 ++++++++++++++++++++-----------
drivers/net/virtio_net.c | 9 +-
include/net/failover.h | 31 +---
include/net/net_failover.h | 32 +---
net/Kconfig | 13 +-
net/core/failover.c | 316 ++++----------------------------
8 files changed, 373 insertions(+), 516 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 99d8e7398a5b..c7d25d10765e 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -902,6 +902,8 @@ struct net_device_context {
struct hv_device *device_ctx;
/* netvsc_device */
struct netvsc_device __rcu *nvdev;
+ /* list of netvsc net_devices */
+ struct list_head list;
/* reconfigure work */
struct delayed_work dwork;
/* last reconfig time */
@@ -933,7 +935,6 @@ struct net_device_context {
/* Serial number of the VF to team with */
u32 vf_serial;
- struct failover *failover;
};
/* Per channel data */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index bef4d55a108c..074e6b8578df 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -70,6 +70,8 @@ static int debug = -1;
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+static LIST_HEAD(netvsc_dev_list);
+
static void netvsc_change_rx_flags(struct net_device *net, int change)
{
struct net_device_context *ndev_ctx = netdev_priv(net);
@@ -1846,101 +1848,120 @@ static void netvsc_vf_setup(struct work_struct *w)
}
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
- if (vf_netdev)
+ if (vf_netdev) {
__netvsc_vf_setup(ndev, vf_netdev);
-
+ dev_put(vf_netdev);
+ }
rtnl_unlock();
}
-static int netvsc_pre_register_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
+static struct net_device *get_netvsc_bymac(const u8 *mac)
{
- struct net_device_context *net_device_ctx;
- struct netvsc_device *netvsc_dev;
+ struct net_device_context *ndev_ctx;
- net_device_ctx = netdev_priv(ndev);
- netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
- if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
- return -ENODEV;
+ ASSERT_RTNL();
- return 0;
+ list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
+ struct net_device *dev = hv_get_drvdata(ndev_ctx->device_ctx);
+
+ if (ether_addr_equal(mac, dev->perm_addr))
+ return dev;
+ }
+
+ return NULL;
}
-static int netvsc_register_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
+static int netvsc_register_vf(struct net_device *vf_netdev)
{
- struct net_device_context *ndev_ctx = netdev_priv(ndev);
+ struct net_device *ndev;
+ struct net_device_context *ndev_ctx;
+
+ /* Must use Ethernet addresses */
+ if (vf_netdev->addr_len != ETH_ALEN)
+ return NOTIFY_DONE;
+
+ /* VF must be a physical device not VLAN, etc */
+ if (!vf_netdev->dev.parent)
+ return NOTIFY_DONE;
+
+ /* Use the MAC address to locate the synthetic interface to
+ * associate with the VF interface.
+ */
+ ndev = get_netvsc_bymac(vf_netdev->perm_addr);
+ if (!ndev)
+ return NOTIFY_DONE;
+
+ /* If network device is being removed, don't do anything */
+ ndev_ctx = netdev_priv(ndev);
+ if (!rtnl_dereference(ndev_ctx->nvdev))
+ return NOTIFY_DONE;
+
+ if (netdev_failover_join(vf_netdev, ndev, netvsc_vf_handle_frame)) {
+ netdev_err(vf_netdev, "could not join: %s", ndev->name);
+ return NOTIFY_DONE;
+ }
/* set slave flag before open to prevent IPv6 addrconf */
vf_netdev->flags |= IFF_SLAVE;
+ dev_hold(vf_netdev);
+
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
netdev_info(vf_netdev, "joined to %s\n", ndev->name);
- dev_hold(vf_netdev);
rcu_assign_pointer(ndev_ctx->vf_netdev, vf_netdev);
- return 0;
+ return NOTIFY_OK;
}
/* VF up/down change detected, schedule to change data path */
-static int netvsc_vf_changed(struct net_device *vf_netdev,
- struct net_device *ndev)
+static int netvsc_vf_changed(struct net_device *vf_netdev)
{
struct net_device_context *net_device_ctx;
struct netvsc_device *netvsc_dev;
+ struct net_device *ndev;
bool vf_is_up = netif_running(vf_netdev);
+ ndev = netdev_failover_upper_get(vf_netdev);
+ if (!ndev)
+ return NOTIFY_DONE;
+
net_device_ctx = netdev_priv(ndev);
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
if (!netvsc_dev)
- return -ENODEV;
+ return NOTIFY_DONE;
netvsc_switch_datapath(ndev, vf_is_up);
netdev_info(ndev, "Data path switched %s VF: %s\n",
vf_is_up ? "to" : "from", vf_netdev->name);
- return 0;
+ return NOTIFY_OK;
}
-static int netvsc_pre_unregister_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
+static int netvsc_unregister_vf(struct net_device *vf_netdev)
{
struct net_device_context *net_device_ctx;
+ struct net_device *ndev;
- net_device_ctx = netdev_priv(ndev);
- cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
-
- return 0;
-}
-
-static int netvsc_unregister_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
-{
- struct net_device_context *net_device_ctx;
+ ndev = netdev_failover_upper_get(vf_netdev);
+ if (!ndev)
+ return NOTIFY_DONE;
net_device_ctx = netdev_priv(ndev);
+ if (cancel_delayed_work_sync(&net_device_ctx->vf_takeover))
+ dev_put(vf_netdev);
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
+ netdev_failover_unjoin(vf_netdev, ndev);
RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
- dev_put(vf_netdev);
- return 0;
+ return NOTIFY_OK;
}
-static struct failover_ops netvsc_failover_ops = {
- .slave_pre_register = netvsc_pre_register_vf,
- .slave_register = netvsc_register_vf,
- .slave_pre_unregister = netvsc_pre_unregister_vf,
- .slave_unregister = netvsc_unregister_vf,
- .slave_link_change = netvsc_vf_changed,
- .slave_handle_frame = netvsc_vf_handle_frame,
-};
-
static int netvsc_probe(struct hv_device *dev,
const struct hv_vmbus_device_id *dev_id)
{
@@ -2009,6 +2030,8 @@ static int netvsc_probe(struct hv_device *dev,
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+ net->priv_flags |= IFF_FAILOVER;
+
/* hw_features computed in rndis_netdev_set_hwcaps() */
net->features = net->hw_features |
NETIF_F_HIGHDMA | NETIF_F_SG |
@@ -2024,23 +2047,19 @@ static int netvsc_probe(struct hv_device *dev,
else
net->max_mtu = ETH_DATA_LEN;
- ret = register_netdev(net);
+ rtnl_lock();
+ ret = register_netdevice(net);
if (ret != 0) {
pr_err("Unable to register netdev.\n");
goto register_failed;
}
- net_device_ctx->failover = failover_register(net, &netvsc_failover_ops);
- if (IS_ERR(net_device_ctx->failover)) {
- ret = PTR_ERR(net_device_ctx->failover);
- goto err_failover;
- }
-
- return ret;
+ list_add(&net_device_ctx->list, &netvsc_dev_list);
+ rtnl_unlock();
+ return 0;
-err_failover:
- unregister_netdev(net);
register_failed:
+ rtnl_unlock();
rndis_filter_device_remove(dev, nvdev);
rndis_failed:
free_percpu(net_device_ctx->vf_stats);
@@ -2079,15 +2098,17 @@ static int netvsc_remove(struct hv_device *dev)
*/
rtnl_lock();
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
- if (vf_netdev)
- failover_slave_unregister(vf_netdev);
+ if (vf_netdev) {
+ netdev_failover_unjoin(vf_netdev, net);
+ dev_put(vf_netdev);
+ }
if (nvdev)
rndis_filter_device_remove(dev, nvdev);
unregister_netdevice(net);
- failover_unregister(ndev_ctx->failover);
+ list_del(&ndev_ctx->list);
rtnl_unlock();
rcu_read_unlock();
@@ -2115,8 +2136,47 @@ static struct hv_driver netvsc_drv = {
.remove = netvsc_remove,
};
+/* On Hyper-V, every VF interface is matched with a corresponding
+ * synthetic interface. The synthetic interface is presented first
+ * to the guest. When the corresponding VF instance is registered,
+ * we will take care of switching the data path.
+ */
+static int netvsc_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+ /* Skip parent events */
+ if (netif_is_failover(event_dev))
+ return NOTIFY_DONE;
+
+ /* Avoid non-Ethernet type devices */
+ if (event_dev->type != ARPHRD_ETHER)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return netvsc_register_vf(event_dev);
+
+ case NETDEV_UNREGISTER:
+ return netvsc_unregister_vf(event_dev);
+
+ case NETDEV_UP:
+ case NETDEV_DOWN:
+ return netvsc_vf_changed(event_dev);
+
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block netvsc_netdev_notifier = {
+ .notifier_call = netvsc_netdev_event,
+};
+
static void __exit netvsc_drv_exit(void)
{
+ unregister_netdevice_notifier(&netvsc_netdev_notifier);
vmbus_driver_unregister(&netvsc_drv);
}
@@ -2136,6 +2196,7 @@ static int __init netvsc_drv_init(void)
if (ret)
return ret;
+ register_netdevice_notifier(&netvsc_netdev_notifier);
return 0;
}
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index 83f7420ddea5..e0d30527f748 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -28,6 +28,46 @@
#include <uapi/linux/if_arp.h>
#include <net/net_failover.h>
+static LIST_HEAD(net_failover_list);
+
+/* failover state */
+struct net_failover_info {
+ struct net_device *failover_dev;
+
+ /* list of failover virtual devices */
+ struct list_head list;
+
+ /* primary netdev with same MAC */
+ struct net_device __rcu *primary_dev;
+
+ /* standby netdev */
+ struct net_device __rcu *standby_dev;
+
+ /* primary netdev stats */
+ struct rtnl_link_stats64 primary_stats;
+
+ /* standby netdev stats */
+ struct rtnl_link_stats64 standby_stats;
+
+ /* aggregated stats */
+ struct rtnl_link_stats64 failover_stats;
+
+ /* spinlock while updating stats */
+ spinlock_t stats_lock;
+
+ /* delayed setup of slave */
+ struct delayed_work standby_init;
+};
+
+#define FAILOVER_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
+ NETIF_F_HIGHDMA | NETIF_F_LRO)
+
+#define FAILOVER_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
+
+#define FAILOVER_SETUP_INTERVAL (HZ / 10)
+
static bool net_failover_xmit_ready(struct net_device *dev)
{
return netif_running(dev) && netif_carrier_ok(dev);
@@ -460,22 +500,42 @@ static void net_failover_lower_state_changed(struct net_device *slave_dev,
netdev_lower_state_changed(slave_dev, &info);
}
-static int net_failover_slave_pre_register(struct net_device *slave_dev,
- struct net_device *failover_dev)
+static struct net_device *get_net_failover_bymac(const u8 *mac)
{
- struct net_device *standby_dev, *primary_dev;
+ struct net_failover_info *nfo_info;
+
+ ASSERT_RTNL();
+
+ list_for_each_entry(nfo_info, &net_failover_list, list) {
+ struct net_device *failover_dev = nfo_info->failover_dev;
+
+ if (ether_addr_equal(mac, failover_dev->perm_addr))
+ return failover_dev;
+ }
+
+ return NULL;
+}
+
+static int net_failover_register_event(struct net_device *slave_dev)
+{
+ struct net_device *failover_dev, *standby_dev, *primary_dev;
struct net_failover_info *nfo_info;
bool slave_is_standby;
+ failover_dev = get_net_failover_bymac(slave_dev->perm_addr);
+ if (!failover_dev)
+ return NOTIFY_DONE;
+
nfo_info = netdev_priv(failover_dev);
standby_dev = rtnl_dereference(nfo_info->standby_dev);
primary_dev = rtnl_dereference(nfo_info->primary_dev);
slave_is_standby = slave_dev->dev.parent == failover_dev->dev.parent;
if (slave_is_standby ? standby_dev : primary_dev) {
- netdev_err(failover_dev, "%s attempting to register as slave dev when %s already present\n",
+ netdev_err(failover_dev,
+ "%s attempting to register as slave dev when %s already present\n",
slave_dev->name,
slave_is_standby ? "standby" : "primary");
- return -EINVAL;
+ return NOTIFY_DONE;
}
/* We want to allow only a direct attached VF device as a primary
@@ -484,23 +544,33 @@ static int net_failover_slave_pre_register(struct net_device *slave_dev,
*/
if (!slave_is_standby && (!slave_dev->dev.parent ||
!dev_is_pci(slave_dev->dev.parent)))
- return -EINVAL;
+ return NOTIFY_DONE;
if (failover_dev->features & NETIF_F_VLAN_CHALLENGED &&
vlan_uses_dev(failover_dev)) {
- netdev_err(failover_dev, "Device %s is VLAN challenged and failover device has VLAN set up\n",
+ netdev_err(failover_dev,
+ "Device %s is VLAN challenged and failover device has VLAN set up\n",
failover_dev->name);
- return -EINVAL;
+ return NOTIFY_DONE;
}
- return 0;
+ if (netdev_failover_join(slave_dev, failover_dev,
+ net_failover_handle_frame)) {
+ netdev_err(failover_dev, "could not join: %s", slave_dev->name);
+ return NOTIFY_DONE;
+ }
+
+ /* Trigger rest of setup in process context */
+ schedule_delayed_work(&nfo_info->standby_init, FAILOVER_SETUP_INTERVAL);
+
+ return NOTIFY_OK;
}
-static int net_failover_slave_register(struct net_device *slave_dev,
- struct net_device *failover_dev)
+static void __net_failover_setup(struct net_device *failover_dev)
{
+ struct net_failover_info *nfo_info = netdev_priv(failover_dev);
+ struct net_device *slave_dev = rtnl_dereference(nfo_info->standby_dev);
struct net_device *standby_dev, *primary_dev;
- struct net_failover_info *nfo_info;
bool slave_is_standby;
u32 orig_mtu;
int err;
@@ -509,13 +579,12 @@ static int net_failover_slave_register(struct net_device *slave_dev,
orig_mtu = slave_dev->mtu;
err = dev_set_mtu(slave_dev, failover_dev->mtu);
if (err) {
- netdev_err(failover_dev, "unable to change mtu of %s to %u register failed\n",
+ netdev_err(failover_dev,
+ "unable to change mtu of %s to %u register failed\n",
slave_dev->name, failover_dev->mtu);
goto done;
}
- dev_hold(slave_dev);
-
if (netif_running(failover_dev)) {
err = dev_open(slave_dev);
if (err && (err != -EBUSY)) {
@@ -537,7 +606,6 @@ static int net_failover_slave_register(struct net_device *slave_dev,
goto err_vlan_add;
}
- nfo_info = netdev_priv(failover_dev);
standby_dev = rtnl_dereference(nfo_info->standby_dev);
primary_dev = rtnl_dereference(nfo_info->primary_dev);
slave_is_standby = slave_dev->dev.parent == failover_dev->dev.parent;
@@ -562,52 +630,56 @@ static int net_failover_slave_register(struct net_device *slave_dev,
netdev_info(failover_dev, "failover %s slave:%s registered\n",
slave_is_standby ? "standby" : "primary", slave_dev->name);
- return 0;
+ return;
err_vlan_add:
dev_uc_unsync(slave_dev, failover_dev);
dev_mc_unsync(slave_dev, failover_dev);
dev_close(slave_dev);
err_dev_open:
- dev_put(slave_dev);
dev_set_mtu(slave_dev, orig_mtu);
done:
- return err;
+ return;
}
-static int net_failover_slave_pre_unregister(struct net_device *slave_dev,
- struct net_device *failover_dev)
+static void net_failover_setup(struct work_struct *w)
{
- struct net_device *standby_dev, *primary_dev;
- struct net_failover_info *nfo_info;
+ struct net_failover_info *nfo_info
+ = container_of(w, struct net_failover_info, standby_init.work);
+ struct net_device *failover_dev = nfo_info->failover_dev;
- nfo_info = netdev_priv(failover_dev);
- primary_dev = rtnl_dereference(nfo_info->primary_dev);
- standby_dev = rtnl_dereference(nfo_info->standby_dev);
-
- if (slave_dev != primary_dev && slave_dev != standby_dev)
- return -ENODEV;
+ /* handle race with cancel delayed work on removal */
+ if (!rtnl_trylock()) {
+ schedule_delayed_work(&nfo_info->standby_init, 0);
+ return;
+ }
- return 0;
+ __net_failover_setup(failover_dev);
+ rtnl_unlock();
}
-static int net_failover_slave_unregister(struct net_device *slave_dev,
- struct net_device *failover_dev)
+static int net_failover_unregister_event(struct net_device *slave_dev)
{
- struct net_device *standby_dev, *primary_dev;
+ struct net_device *failover_dev, *primary_dev, *standby_dev;
struct net_failover_info *nfo_info;
bool slave_is_standby;
+ failover_dev = netdev_failover_upper_get(slave_dev);
+ if (!failover_dev)
+ return NOTIFY_DONE;
+
nfo_info = netdev_priv(failover_dev);
primary_dev = rtnl_dereference(nfo_info->primary_dev);
standby_dev = rtnl_dereference(nfo_info->standby_dev);
+ if (slave_dev != primary_dev && slave_dev != standby_dev)
+ return NOTIFY_DONE;
+
vlan_vids_del_by_dev(slave_dev, failover_dev);
dev_uc_unsync(slave_dev, failover_dev);
dev_mc_unsync(slave_dev, failover_dev);
dev_close(slave_dev);
- nfo_info = netdev_priv(failover_dev);
dev_get_stats(failover_dev, &nfo_info->failover_stats);
slave_is_standby = slave_dev->dev.parent == failover_dev->dev.parent;
@@ -628,22 +700,25 @@ static int net_failover_slave_unregister(struct net_device *slave_dev,
netdev_info(failover_dev, "failover %s slave:%s unregistered\n",
slave_is_standby ? "standby" : "primary", slave_dev->name);
- return 0;
+ return NOTIFY_OK;
}
-static int net_failover_slave_link_change(struct net_device *slave_dev,
- struct net_device *failover_dev)
+static int net_failover_link_event(struct net_device *slave_dev)
+
{
- struct net_device *primary_dev, *standby_dev;
+ struct net_device *failover_dev, *primary_dev, *standby_dev;
struct net_failover_info *nfo_info;
- nfo_info = netdev_priv(failover_dev);
+ failover_dev = netdev_failover_upper_get(slave_dev);
+ if (!failover_dev)
+ return NOTIFY_DONE;
+ nfo_info = netdev_priv(failover_dev);
primary_dev = rtnl_dereference(nfo_info->primary_dev);
standby_dev = rtnl_dereference(nfo_info->standby_dev);
if (slave_dev != primary_dev && slave_dev != standby_dev)
- return -ENODEV;
+ return NOTIFY_DONE;
if ((primary_dev && net_failover_xmit_ready(primary_dev)) ||
(standby_dev && net_failover_xmit_ready(standby_dev))) {
@@ -657,43 +732,11 @@ static int net_failover_slave_link_change(struct net_device *slave_dev,
net_failover_lower_state_changed(slave_dev, primary_dev, standby_dev);
- return 0;
+ return NOTIFY_DONE;
}
-static int net_failover_slave_name_change(struct net_device *slave_dev,
- struct net_device *failover_dev)
-{
- struct net_device *primary_dev, *standby_dev;
- struct net_failover_info *nfo_info;
-
- nfo_info = netdev_priv(failover_dev);
-
- primary_dev = rtnl_dereference(nfo_info->primary_dev);
- standby_dev = rtnl_dereference(nfo_info->standby_dev);
-
- if (slave_dev != primary_dev && slave_dev != standby_dev)
- return -ENODEV;
-
- /* We need to bring up the slave after the rename by udev in case
- * open failed with EBUSY when it was registered.
- */
- dev_open(slave_dev);
-
- return 0;
-}
-
-static struct failover_ops net_failover_ops = {
- .slave_pre_register = net_failover_slave_pre_register,
- .slave_register = net_failover_slave_register,
- .slave_pre_unregister = net_failover_slave_pre_unregister,
- .slave_unregister = net_failover_slave_unregister,
- .slave_link_change = net_failover_slave_link_change,
- .slave_name_change = net_failover_slave_name_change,
- .slave_handle_frame = net_failover_handle_frame,
-};
-
/**
- * net_failover_create - Create and register a failover instance
+ * net_failover_create - Create and register a failover device
*
* @dev: standby netdev
*
@@ -703,13 +746,12 @@ static struct failover_ops net_failover_ops = {
* the original standby netdev and a VF netdev with the same MAC gets
* registered as primary netdev.
*
- * Return: pointer to failover instance
+ * Return: pointer to failover network device
*/
-struct failover *net_failover_create(struct net_device *standby_dev)
+struct net_device *net_failover_create(struct net_device *standby_dev)
{
- struct device *dev = standby_dev->dev.parent;
+ struct net_failover_info *nfo_info;
struct net_device *failover_dev;
- struct failover *failover;
int err;
/* Alloc at least 2 queues, for now we are going with 16 assuming
@@ -717,18 +759,22 @@ struct failover *net_failover_create(struct net_device *standby_dev)
*/
failover_dev = alloc_etherdev_mq(sizeof(struct net_failover_info), 16);
if (!failover_dev) {
- dev_err(dev, "Unable to allocate failover_netdev!\n");
- return ERR_PTR(-ENOMEM);
+ netdev_err(standby_dev, "Unable to allocate failover_netdev!\n");
+ return NULL;
}
+ nfo_info = netdev_priv(failover_dev);
dev_net_set(failover_dev, dev_net(standby_dev));
- SET_NETDEV_DEV(failover_dev, dev);
+ nfo_info->failover_dev = failover_dev;
+ INIT_DELAYED_WORK(&nfo_info->standby_init, net_failover_setup);
failover_dev->netdev_ops = &failover_dev_ops;
failover_dev->ethtool_ops = &failover_ethtool_ops;
/* Initialize the device options */
- failover_dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
+ failover_dev->priv_flags |= IFF_UNICAST_FLT |
+ IFF_NO_QUEUE |
+ IFF_FAILOVER;
failover_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE |
IFF_TX_SKB_SHARING);
@@ -746,29 +792,38 @@ struct failover *net_failover_create(struct net_device *standby_dev)
failover_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
failover_dev->features |= failover_dev->hw_features;
- memcpy(failover_dev->dev_addr, standby_dev->dev_addr,
- failover_dev->addr_len);
+ ether_addr_copy(failover_dev->dev_addr, standby_dev->dev_addr);
+ ether_addr_copy(failover_dev->perm_addr, standby_dev->perm_addr);
failover_dev->min_mtu = standby_dev->min_mtu;
failover_dev->max_mtu = standby_dev->max_mtu;
- err = register_netdev(failover_dev);
+ netif_carrier_off(failover_dev);
+
+ rtnl_lock();
+ err = register_netdevice(failover_dev);
if (err) {
- dev_err(dev, "Unable to register failover_dev!\n");
+ netdev_err(standby_dev, "Unable to register failover_dev!\n");
goto err_register_netdev;
}
- netif_carrier_off(failover_dev);
+ err = netdev_failover_join(standby_dev, failover_dev,
+ net_failover_handle_frame);
+ if (err) {
+ netdev_err(failover_dev, "Unable to join with %s\n",
+ standby_dev->name);
+ goto err_failover_join;
+ }
- failover = failover_register(failover_dev, &net_failover_ops);
- if (IS_ERR(failover))
- goto err_failover_register;
+ list_add(&nfo_info->list, &net_failover_list);
+ rtnl_unlock();
- return failover;
+ return failover_dev;
-err_failover_register:
- unregister_netdev(failover_dev);
+err_failover_join:
+ unregister_netdevice(failover_dev);
err_register_netdev:
+ rtnl_unlock();
free_netdev(failover_dev);
return ERR_PTR(err);
@@ -786,31 +841,27 @@ EXPORT_SYMBOL_GPL(net_failover_create);
* netdev. Used by paravirtual drivers that use 3-netdev model.
*
*/
-void net_failover_destroy(struct failover *failover)
+void net_failover_destroy(struct net_device *failover_dev)
{
- struct net_failover_info *nfo_info;
- struct net_device *failover_dev;
+ struct net_failover_info *nfo_info = netdev_priv(failover_dev);
struct net_device *slave_dev;
- if (!failover)
- return;
-
- failover_dev = rcu_dereference(failover->failover_dev);
- nfo_info = netdev_priv(failover_dev);
-
netif_device_detach(failover_dev);
rtnl_lock();
-
slave_dev = rtnl_dereference(nfo_info->primary_dev);
- if (slave_dev)
- failover_slave_unregister(slave_dev);
+ if (slave_dev) {
+ netdev_failover_unjoin(slave_dev, failover_dev);
+ dev_put(slave_dev);
+ }
slave_dev = rtnl_dereference(nfo_info->standby_dev);
- if (slave_dev)
- failover_slave_unregister(slave_dev);
+ if (slave_dev) {
+ netdev_failover_unjoin(slave_dev, failover_dev);
+ dev_put(slave_dev);
+ }
- failover_unregister(failover);
+ list_del(&nfo_info->list);
unregister_netdevice(failover_dev);
@@ -820,9 +871,53 @@ void net_failover_destroy(struct failover *failover)
}
EXPORT_SYMBOL_GPL(net_failover_destroy);
+static int net_failover_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+ /* Skip parent events */
+ if (netif_is_failover(event_dev))
+ return NOTIFY_DONE;
+
+ /* Avoid non-Ethernet type devices */
+ if (event_dev->type != ARPHRD_ETHER)
+ return NOTIFY_DONE;
+
+ /* Avoid Vlan dev with same MAC registering as VF */
+ if (is_vlan_dev(event_dev))
+ return NOTIFY_DONE;
+
+ /* Avoid Bonding master dev with same MAC registering as VF */
+ if ((event_dev->priv_flags & IFF_BONDING) &&
+ (event_dev->flags & IFF_MASTER))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return net_failover_register_event(event_dev);
+
+ case NETDEV_UNREGISTER:
+ return net_failover_unregister_event(event_dev);
+
+ case NETDEV_UP:
+ case NETDEV_DOWN:
+ case NETDEV_CHANGE:
+ return net_failover_link_event(event_dev);
+
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block net_failover_notifier = {
+ .notifier_call = net_failover_event,
+};
+
static __init int
net_failover_init(void)
{
+ register_netdevice_notifier(&net_failover_notifier);
return 0;
}
module_init(net_failover_init);
@@ -830,6 +925,7 @@ module_init(net_failover_init);
static __exit
void net_failover_exit(void)
{
+ unregister_netdevice_notifier(&net_failover_notifier);
}
module_exit(net_failover_exit);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 6d710b8b41c5..b40ae28dac93 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -215,7 +215,7 @@ struct virtnet_info {
unsigned long guest_offloads;
/* failover when STANDBY feature enabled */
- struct failover *failover;
+ struct net_device *failover;
};
struct padded_vnet_hdr {
@@ -2930,11 +2930,10 @@ static int virtnet_probe(struct virtio_device *vdev)
virtnet_init_settings(dev);
if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
- vi->failover = net_failover_create(vi->dev);
- if (IS_ERR(vi->failover)) {
- err = PTR_ERR(vi->failover);
+ err = -ENOMEM;
+ vi->failover = net_failover_create(dev);
+ if (!vi->failover)
goto free_vqs;
- }
}
err = register_netdev(dev);
diff --git a/include/net/failover.h b/include/net/failover.h
index bb15438f39c7..22d6c1369101 100644
--- a/include/net/failover.h
+++ b/include/net/failover.h
@@ -6,31 +6,10 @@
#include <linux/netdevice.h>
-struct failover_ops {
- int (*slave_pre_register)(struct net_device *slave_dev,
- struct net_device *failover_dev);
- int (*slave_register)(struct net_device *slave_dev,
- struct net_device *failover_dev);
- int (*slave_pre_unregister)(struct net_device *slave_dev,
- struct net_device *failover_dev);
- int (*slave_unregister)(struct net_device *slave_dev,
- struct net_device *failover_dev);
- int (*slave_link_change)(struct net_device *slave_dev,
- struct net_device *failover_dev);
- int (*slave_name_change)(struct net_device *slave_dev,
- struct net_device *failover_dev);
- rx_handler_result_t (*slave_handle_frame)(struct sk_buff **pskb);
-};
-
-struct failover {
- struct list_head list;
- struct net_device __rcu *failover_dev;
- struct failover_ops __rcu *ops;
-};
-
-struct failover *failover_register(struct net_device *dev,
- struct failover_ops *ops);
-void failover_unregister(struct failover *failover);
-int failover_slave_unregister(struct net_device *slave_dev);
+int netdev_failover_join(struct net_device *lower, struct net_device *upper,
+ rx_handler_func_t *rx_handler);
+struct net_device *netdev_failover_upper_get(struct net_device *lower);
+void netdev_failover_unjoin(struct net_device *lower,
+ struct net_device *upper);
#endif /* _FAILOVER_H */
diff --git a/include/net/net_failover.h b/include/net/net_failover.h
index b12a1c469d1c..a99b3b00b4e3 100644
--- a/include/net/net_failover.h
+++ b/include/net/net_failover.h
@@ -6,35 +6,7 @@
#include <net/failover.h>
-/* failover state */
-struct net_failover_info {
- /* primary netdev with same MAC */
- struct net_device __rcu *primary_dev;
-
- /* standby netdev */
- struct net_device __rcu *standby_dev;
-
- /* primary netdev stats */
- struct rtnl_link_stats64 primary_stats;
-
- /* standby netdev stats */
- struct rtnl_link_stats64 standby_stats;
-
- /* aggregated stats */
- struct rtnl_link_stats64 failover_stats;
-
- /* spinlock while updating stats */
- spinlock_t stats_lock;
-};
-
-struct failover *net_failover_create(struct net_device *standby_dev);
-void net_failover_destroy(struct failover *failover);
-
-#define FAILOVER_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
- NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
- NETIF_F_HIGHDMA | NETIF_F_LRO)
-
-#define FAILOVER_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
- NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
+struct net_device *net_failover_create(struct net_device *standby_dev);
+void net_failover_destroy(struct net_device *failover_dev);
#endif /* _NET_FAILOVER_H */
diff --git a/net/Kconfig b/net/Kconfig
index f738a6f27665..697d84202695 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -433,17 +433,8 @@ config PAGE_POOL
bool
config FAILOVER
- tristate "Generic failover module"
- help
- The failover module provides a generic interface for paravirtual
- drivers to register a netdev and a set of ops with a failover
- instance. The ops are used as event handlers that get called to
- handle netdev register/unregister/link change/name change events
- on slave pci ethernet devices with the same mac address as the
- failover netdev. This enables paravirtual drivers to use a
- VF as an accelerated low latency datapath. It also allows live
- migration of VMs with direct attached VFs by failing over to the
- paravirtual datapath when the VF is unplugged.
+ bool
+ default n
endif # if NET
diff --git a/net/core/failover.c b/net/core/failover.c
index 4a92a98ccce9..499f0fd7e4d3 100644
--- a/net/core/failover.c
+++ b/net/core/failover.c
@@ -1,10 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */
-/* A common module to handle registrations and notifications for paravirtual
+/* A library for managing chained upper/oower devices such as
* drivers to enable accelerated datapath and support VF live migration.
- *
- * The notifier and event handling code is based on netvsc driver.
*/
#include <linux/module.h>
@@ -14,302 +12,62 @@
#include <linux/if_vlan.h>
#include <net/failover.h>
-static LIST_HEAD(failover_list);
-static DEFINE_SPINLOCK(failover_lock);
-
-static struct net_device *failover_get_bymac(u8 *mac, struct failover_ops **ops)
-{
- struct net_device *failover_dev;
- struct failover *failover;
-
- spin_lock(&failover_lock);
- list_for_each_entry(failover, &failover_list, list) {
- failover_dev = rtnl_dereference(failover->failover_dev);
- if (ether_addr_equal(failover_dev->perm_addr, mac)) {
- *ops = rtnl_dereference(failover->ops);
- spin_unlock(&failover_lock);
- return failover_dev;
- }
- }
- spin_unlock(&failover_lock);
- return NULL;
-}
-
-/**
- * failover_slave_register - Register a slave netdev
- *
- * @slave_dev: slave netdev that is being registered
- *
- * Registers a slave device to a failover instance. Only ethernet devices
- * are supported.
- */
-static int failover_slave_register(struct net_device *slave_dev)
+/* failover_join - Join an lower netdev with an upper device. */
+int netdev_failover_join(struct net_device *lower_dev,
+ struct net_device *upper_dev,
+ rx_handler_func_t *rx_handler)
{
- struct netdev_lag_upper_info lag_upper_info;
- struct net_device *failover_dev;
- struct failover_ops *fops;
int err;
- if (slave_dev->type != ARPHRD_ETHER)
- goto done;
-
ASSERT_RTNL();
- failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
- if (!failover_dev)
- goto done;
+ /* Don't allow joining devices of different protocols */
+ if (upper_dev->type != lower_dev->type)
+ return -EINVAL;
- if (fops && fops->slave_pre_register &&
- fops->slave_pre_register(slave_dev, failover_dev))
- goto done;
-
- err = netdev_rx_handler_register(slave_dev, fops->slave_handle_frame,
- failover_dev);
+ err = netdev_rx_handler_register(lower_dev, rx_handler, upper_dev);
if (err) {
- netdev_err(slave_dev, "can not register failover rx handler (err = %d)\n",
+ netdev_err(lower_dev,
+ "can not register failover rx handler (err = %d)\n",
err);
- goto done;
+ return err;
}
- lag_upper_info.tx_type = NETDEV_LAG_TX_TYPE_ACTIVEBACKUP;
- err = netdev_master_upper_dev_link(slave_dev, failover_dev, NULL,
- &lag_upper_info, NULL);
+ err = netdev_master_upper_dev_link(lower_dev, upper_dev, NULL,
+ NULL, NULL);
if (err) {
- netdev_err(slave_dev, "can not set failover device %s (err = %d)\n",
- failover_dev->name, err);
- goto err_upper_link;
+ netdev_err(lower_dev,
+ "can not set failover device %s (err = %d)\n",
+ upper_dev->name, err);
+ netdev_rx_handler_unregister(lower_dev);
+ return err;
}
- slave_dev->priv_flags |= IFF_FAILOVER_SLAVE;
-
- if (fops && fops->slave_register &&
- !fops->slave_register(slave_dev, failover_dev))
- return NOTIFY_OK;
-
- netdev_upper_dev_unlink(slave_dev, failover_dev);
- slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE;
-err_upper_link:
- netdev_rx_handler_unregister(slave_dev);
-done:
- return NOTIFY_DONE;
-}
-
-/**
- * failover_slave_unregister - Unregister a slave netdev
- *
- * @slave_dev: slave netdev that is being unregistered
- *
- * Unregisters a slave device from a failover instance.
- */
-int failover_slave_unregister(struct net_device *slave_dev)
-{
- struct net_device *failover_dev;
- struct failover_ops *fops;
-
- if (!netif_is_failover_slave(slave_dev))
- goto done;
-
- ASSERT_RTNL();
-
- failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
- if (!failover_dev)
- goto done;
-
- if (fops && fops->slave_pre_unregister &&
- fops->slave_pre_unregister(slave_dev, failover_dev))
- goto done;
-
- netdev_rx_handler_unregister(slave_dev);
- netdev_upper_dev_unlink(slave_dev, failover_dev);
- slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE;
-
- if (fops && fops->slave_unregister &&
- !fops->slave_unregister(slave_dev, failover_dev))
- return NOTIFY_OK;
-
-done:
- return NOTIFY_DONE;
+ dev_hold(lower_dev);
+ lower_dev->priv_flags |= IFF_FAILOVER_SLAVE;
+ return 0;
}
-EXPORT_SYMBOL_GPL(failover_slave_unregister);
+EXPORT_SYMBOL_GPL(netdev_failover_join);
-static int failover_slave_link_change(struct net_device *slave_dev)
+/* Find upper network device for failover slave device */
+struct net_device *netdev_failover_upper_get(struct net_device *lower_dev)
{
- struct net_device *failover_dev;
- struct failover_ops *fops;
-
- if (!netif_is_failover_slave(slave_dev))
- goto done;
-
- ASSERT_RTNL();
-
- failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
- if (!failover_dev)
- goto done;
-
- if (!netif_running(failover_dev))
- goto done;
+ if (!netif_is_failover_slave(lower_dev))
+ return NULL;
- if (fops && fops->slave_link_change &&
- !fops->slave_link_change(slave_dev, failover_dev))
- return NOTIFY_OK;
-
-done:
- return NOTIFY_DONE;
+ return netdev_master_upper_dev_get(lower_dev);
}
+EXPORT_SYMBOL_GPL(netdev_failover_upper_get);
-static int failover_slave_name_change(struct net_device *slave_dev)
+/* failover_unjoin - Break connection between lower and upper device. */
+void netdev_failover_unjoin(struct net_device *lower_dev,
+ struct net_device *upper_dev)
{
- struct net_device *failover_dev;
- struct failover_ops *fops;
-
- if (!netif_is_failover_slave(slave_dev))
- goto done;
-
ASSERT_RTNL();
- failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
- if (!failover_dev)
- goto done;
-
- if (!netif_running(failover_dev))
- goto done;
-
- if (fops && fops->slave_name_change &&
- !fops->slave_name_change(slave_dev, failover_dev))
- return NOTIFY_OK;
-
-done:
- return NOTIFY_DONE;
-}
-
-static int
-failover_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
- struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
-
- /* Skip parent events */
- if (netif_is_failover(event_dev))
- return NOTIFY_DONE;
-
- switch (event) {
- case NETDEV_REGISTER:
- return failover_slave_register(event_dev);
- case NETDEV_UNREGISTER:
- return failover_slave_unregister(event_dev);
- case NETDEV_UP:
- case NETDEV_DOWN:
- case NETDEV_CHANGE:
- return failover_slave_link_change(event_dev);
- case NETDEV_CHANGENAME:
- return failover_slave_name_change(event_dev);
- default:
- return NOTIFY_DONE;
- }
-}
-
-static struct notifier_block failover_notifier = {
- .notifier_call = failover_event,
-};
-
-static void
-failover_existing_slave_register(struct net_device *failover_dev)
-{
- struct net *net = dev_net(failover_dev);
- struct net_device *dev;
-
- rtnl_lock();
- for_each_netdev(net, dev) {
- if (netif_is_failover(dev))
- continue;
- if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr))
- failover_slave_register(dev);
- }
- rtnl_unlock();
-}
-
-/**
- * failover_register - Register a failover instance
- *
- * @dev: failover netdev
- * @ops: failover ops
- *
- * Allocate and register a failover instance for a failover netdev. ops
- * provides handlers for slave device register/unregister/link change/
- * name change events.
- *
- * Return: pointer to failover instance
- */
-struct failover *failover_register(struct net_device *dev,
- struct failover_ops *ops)
-{
- struct failover *failover;
-
- if (dev->type != ARPHRD_ETHER)
- return ERR_PTR(-EINVAL);
-
- failover = kzalloc(sizeof(*failover), GFP_KERNEL);
- if (!failover)
- return ERR_PTR(-ENOMEM);
-
- rcu_assign_pointer(failover->ops, ops);
- dev_hold(dev);
- dev->priv_flags |= IFF_FAILOVER;
- rcu_assign_pointer(failover->failover_dev, dev);
-
- spin_lock(&failover_lock);
- list_add_tail(&failover->list, &failover_list);
- spin_unlock(&failover_lock);
-
- netdev_info(dev, "failover master:%s registered\n", dev->name);
-
- failover_existing_slave_register(dev);
-
- return failover;
-}
-EXPORT_SYMBOL_GPL(failover_register);
-
-/**
- * failover_unregister - Unregister a failover instance
- *
- * @failover: pointer to failover instance
- *
- * Unregisters and frees a failover instance.
- */
-void failover_unregister(struct failover *failover)
-{
- struct net_device *failover_dev;
-
- failover_dev = rcu_dereference(failover->failover_dev);
-
- netdev_info(failover_dev, "failover master:%s unregistered\n",
- failover_dev->name);
-
- failover_dev->priv_flags &= ~IFF_FAILOVER;
- dev_put(failover_dev);
-
- spin_lock(&failover_lock);
- list_del(&failover->list);
- spin_unlock(&failover_lock);
-
- kfree(failover);
+ netdev_rx_handler_unregister(lower_dev);
+ netdev_upper_dev_unlink(lower_dev, upper_dev);
+ dev_put(lower_dev);
+ lower_dev->priv_flags &= ~IFF_FAILOVER_SLAVE;
}
-EXPORT_SYMBOL_GPL(failover_unregister);
-
-static __init int
-failover_init(void)
-{
- register_netdevice_notifier(&failover_notifier);
-
- return 0;
-}
-module_init(failover_init);
-
-static __exit
-void failover_exit(void)
-{
- unregister_netdevice_notifier(&failover_notifier);
-}
-module_exit(failover_exit);
-
-MODULE_DESCRIPTION("Generic failover infrastructure/interface");
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL_GPL(netdev_failover_unjoin);
--
2.17.1
^ permalink raw reply related
* [PATCH net] sctp: not allow transport timeout value less than HZ/5 for hb_timer
From: Xin Long @ 2018-06-05 4:16 UTC (permalink / raw)
To: network dev, linux-sctp
Cc: davem, Eric Dumazet, Marcelo Ricardo Leitner, Neil Horman,
Dmitry Vyukov, syzkaller
syzbot reported a rcu_sched self-detected stall on CPU which is caused
by too small value set on rto_min with SCTP_RTOINFO sockopt. With this
value, hb_timer will get stuck there, as in its timer handler it starts
this timer again with this value, then goes to the timer handler again.
This problem is there since very beginning, and thanks to Eric for the
reproducer shared from a syzbot mail.
This patch fixes it by not allowing sctp_transport_timeout to return a
smaller value than HZ/5 for hb_timer, which is based on TCP's min rto.
Note that it doesn't fix this issue by limiting rto_min, as some users
are still using small rto and no proper value was found for it yet.
Reported-by: syzbot+3dcd59a1f907245f891f@syzkaller.appspotmail.com
Suggested-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/transport.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 47f82bd..03fc2c4 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -634,7 +634,7 @@ unsigned long sctp_transport_timeout(struct sctp_transport *trans)
trans->state != SCTP_PF)
timeout += trans->hbinterval;
- return timeout;
+ return max_t(unsigned long, timeout, HZ / 5);
}
/* Reset transport variables to their initial values */
--
2.1.0
^ permalink raw reply related
* Re: [PATCH net-next] net/mlx5e: Make function mlx5e_change_rep_mtu() static
From: Leon Romanovsky @ 2018-06-05 4:20 UTC (permalink / raw)
To: Wei Yongjun
Cc: Saeed Mahameed, Adi Nissim, netdev, linux-rdma, kernel-janitors
In-Reply-To: <1528166565-54828-1-git-send-email-weiyongjun1@huawei.com>
[-- Attachment #1: Type: text/plain, Size: 472 bytes --]
On Tue, Jun 05, 2018 at 02:42:45AM +0000, Wei Yongjun wrote:
> Fixes the following sparse warning:
>
> drivers/net/ethernet/mellanox/mlx5/core/en_rep.c:903:5: warning:
> symbol 'mlx5e_change_rep_mtu' was not declared. Should it be static?
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
> ---
> drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
Thanks,
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [RFC PATCH 0/2] net: macb: Disable TX checksum offloading on all Zynq
From: Harini Katakam @ 2018-06-05 4:51 UTC (permalink / raw)
To: Nicolas Ferre
Cc: Jennifer Dahm, netdev, David S . Miller, Nathan Sullivan,
Rafal Ozieblo, Claudiu Beznea, Harini Katakam
In-Reply-To: <d3fe52fa-ae42-f818-4494-8352323cc489@microchip.com>
Hi Jeniffer,
On Mon, Jun 4, 2018 at 8:35 PM, Nicolas Ferre
<nicolas.ferre@microchip.com> wrote:
> Jennifer,
>
> On 25/05/2018 at 23:44, Jennifer Dahm wrote:
>>
>> During testing, I discovered that the Zynq GEM hardware overwrites all
>> outgoing UDP packet checksums, which is illegal in packet forwarding
>> cases. This happens both with and without the checksum-zeroing
>> behavior introduced in 007e4ba3ee137f4700f39aa6dbaf01a71047c5f6
>> ("net: macb: initialize checksum when using checksum offloading"). The
>> only solution to both the small packet bug and the packet forwarding
>> bug that I can find is to disable TX checksum offloading entirely.
>
>
Thanks for the extensive testing.
I'll try to reproduce and see if it is something to be fixed in the driver.
> Are the bugs listed above present in all revisions of the GEM IP, only for
> some revisions?
> Is there an errata that describe this issue for the Zynq GEM?
@Nicolas, AFAIK, there is no errata for this in either Cadence or
Zynq documentation.
Regards,
Harini
^ permalink raw reply
* general protection fault in sockfs_setattr
From: shankarapailoor @ 2018-06-05 4:53 UTC (permalink / raw)
To: davem; +Cc: linux-kernel, syzkaller, netdev
Hi,
I have been fuzzing Linux 4.17-rc7 with Syzkaller and found the
following crash: https://pastebin.com/ixX3RB9j
Syzkaller isolated the cause of the bug to the following program:
socketpair$unix(0x1, 0x1, 0x0,
&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
getresuid(&(0x7f0000000080)=<r2=>0x0, &(0x7f00000000c0),
&(0x7f0000000700))r3 = getegid()
fchownat(r0, &(0x7f0000000040)='\x00', r2, r3, 0x1000)
dup3(r1, r0, 0x80000)
The problematic area appears to be here:
static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
{
int err = simple_setattr(dentry, iattr);
if (!err && (iattr->ia_valid & ATTR_UID)) {
struct socket *sock = SOCKET_I(d_inode(dentry));
sock->sk->sk_uid = iattr->ia_uid; //KASAN GPF
}
return err;
}
If dup3 is called concurrently with fchownat then can sock->sk be NULL?
--
Regards,
Shankara Pailoor
^ permalink raw reply
* [PATCH] r8169: Reinstate ALDPS and ASPM support
From: Kai-Heng Feng @ 2018-06-05 4:58 UTC (permalink / raw)
To: davem
Cc: hayeswang, hkallweit1, romieu, netdev, linux-kernel,
Kai-Heng Feng, Ryankao
This patch reinstate ALDPS and ASPM support on r8169.
On some Intel platforms, ASPM support on r8169 is the key factor to let
Package C-State achieve PC8. Without ASPM support, the deepest Package
C-State can hit is PC3. PC8 can save additional ~3W in comparison with
PC3.
This patch is from Realtek.
Fixes: e0c075577965 ("r8169: enable ALDPS for power saving")
Fixes: d64ec841517a ("r8169: enable internal ASPM and clock request settings")
Cc: Ryankao <ryankao@realtek.com>
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
drivers/net/ethernet/realtek/r8169.c | 190 +++++++++++++++++++++------
1 file changed, 151 insertions(+), 39 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 75dfac0248f4..a28ef20be221 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -319,6 +319,8 @@ static const struct pci_device_id rtl8169_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
+static int enable_aspm = 1;
+static int enable_aldps = 1;
static int use_dac = -1;
static struct {
u32 msg_enable;
@@ -817,6 +819,10 @@ struct rtl8169_private {
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
+module_param(enable_aspm, int, 0);
+MODULE_PARM_DESC(enable_aspm, "Enable ASPM");
+module_param(enable_aldps, int, 0);
+MODULE_PARM_DESC(enable_aldps, "Enable ALDPS");
module_param(use_dac, int, 0);
MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
module_param_named(debug, debug.msg_enable, int, 0);
@@ -1567,25 +1573,6 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
}
}
-static void rtl8169_check_link_status(struct net_device *dev,
- struct rtl8169_private *tp)
-{
- struct device *d = tp_to_dev(tp);
-
- if (tp->link_ok(tp)) {
- rtl_link_chg_patch(tp);
- /* This is to cancel a scheduled suspend if there's one. */
- pm_request_resume(d);
- netif_carrier_on(dev);
- if (net_ratelimit())
- netif_info(tp, ifup, dev, "link up\n");
- } else {
- netif_carrier_off(dev);
- netif_info(tp, ifdown, dev, "link down\n");
- pm_runtime_idle(d);
- }
-}
-
#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
@@ -3520,6 +3507,15 @@ static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x0d, 0x4007);
rtl_writephy(tp, 0x0e, 0x0000);
rtl_writephy(tp, 0x0d, 0x0000);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
+ else if (rtl_readphy(tp, 0x15) & 0x1000)
+ rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1000);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
@@ -3627,6 +3623,15 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
/* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
+ else if (rtl_readphy(tp, 0x15) & 0x1000)
+ rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1000);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
@@ -3649,6 +3654,15 @@ static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x05, 0x8b86);
rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
+ else if (rtl_readphy(tp, 0x15) & 0x1000)
+ rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1000);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3865,7 +3879,9 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
+ else if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
@@ -3874,6 +3890,14 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp)
{
rtl_apply_firmware(tp);
+
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
+ else if (rtl_readphy(tp, 0x10) & 0x0004)
+ rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3980,7 +4004,9 @@ static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
+ else if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
@@ -4053,7 +4079,9 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
+ else if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
@@ -4095,7 +4123,9 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
+ else if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
@@ -4186,7 +4216,9 @@ static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp)
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
+ else if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
@@ -4233,6 +4265,15 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
rtl_apply_firmware(tp);
rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x18, 0x1000, 0x0000);
+ else if (rtl_readphy(tp, 0x18) & 0x1000)
+ rtl_w0w1_phy(tp, 0x18, 0x0000, 0x1000);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
@@ -4250,6 +4291,15 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x10, 0x401f);
rtl_writephy(tp, 0x19, 0x7030);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x18, 0x1000, 0x0000);
+ else if (rtl_readphy(tp, 0x18) & 0x1000)
+ rtl_w0w1_phy(tp, 0x18, 0x0000, 0x1000);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
@@ -4272,6 +4322,15 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ if (enable_aldps)
+ rtl_w0w1_phy(tp, 0x18, 0x1000, 0x0000);
+ else if (rtl_readphy(tp, 0x18) & 0x1000)
+ rtl_w0w1_phy(tp, 0x18, 0x0000, 0x1000);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl_hw_phy_config(struct net_device *dev)
@@ -5290,6 +5349,18 @@ static void rtl_pcie_state_l2l3_enable(struct rtl8169_private *tp, bool enable)
RTL_W8(tp, Config3, data);
}
+static void rtl_hw_internal_aspm_clkreq_enable(struct rtl8169_private *tp,
+ bool enable)
+{
+ if (enable) {
+ RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
+ RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
+ } else {
+ RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
+ RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ }
+}
+
static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
{
RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
@@ -5646,9 +5717,10 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
rtl_hw_start_8168g(tp);
/* disable aspm and clock request before access ephy */
- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ rtl_hw_internal_aspm_clkreq_enable(tp, false);
rtl_ephy_init(tp, e_info_8168g_1, ARRAY_SIZE(e_info_8168g_1));
+ if (enable_aspm)
+ rtl_hw_internal_aspm_clkreq_enable(tp, true);
}
static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
@@ -5681,9 +5753,10 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
rtl_hw_start_8168g(tp);
/* disable aspm and clock request before access ephy */
- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ rtl_hw_internal_aspm_clkreq_enable(tp, false);
rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2));
+ if (enable_aspm)
+ rtl_hw_internal_aspm_clkreq_enable(tp, true);
}
static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
@@ -5700,8 +5773,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
};
/* disable aspm and clock request before access ephy */
- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ rtl_hw_internal_aspm_clkreq_enable(tp, false);
rtl_ephy_init(tp, e_info_8168h_1, ARRAY_SIZE(e_info_8168h_1));
RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | TXCFG_AUTO_FIFO);
@@ -5780,6 +5852,9 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
r8168_mac_ocp_write(tp, 0xc094, 0x0000);
r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
+
+ if (enable_aspm)
+ rtl_hw_internal_aspm_clkreq_enable(tp, true);
}
static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
@@ -5831,11 +5906,13 @@ static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
};
/* disable aspm and clock request before access ephy */
- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ rtl_hw_internal_aspm_clkreq_enable(tp, false);
rtl_ephy_init(tp, e_info_8168ep_1, ARRAY_SIZE(e_info_8168ep_1));
rtl_hw_start_8168ep(tp);
+
+ if (enable_aspm)
+ rtl_hw_internal_aspm_clkreq_enable(tp, true);
}
static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
@@ -5847,14 +5924,16 @@ static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
};
/* disable aspm and clock request before access ephy */
- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ rtl_hw_internal_aspm_clkreq_enable(tp, false);
rtl_ephy_init(tp, e_info_8168ep_2, ARRAY_SIZE(e_info_8168ep_2));
rtl_hw_start_8168ep(tp);
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
+
+ if (enable_aspm)
+ rtl_hw_internal_aspm_clkreq_enable(tp, true);
}
static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
@@ -5868,8 +5947,7 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
};
/* disable aspm and clock request before access ephy */
- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
+ rtl_hw_internal_aspm_clkreq_enable(tp, false);
rtl_ephy_init(tp, e_info_8168ep_3, ARRAY_SIZE(e_info_8168ep_3));
rtl_hw_start_8168ep(tp);
@@ -5889,6 +5967,9 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
data = r8168_mac_ocp_read(tp, 0xe860);
data |= 0x0080;
r8168_mac_ocp_write(tp, 0xe860, data);
+
+ if (enable_aspm)
+ rtl_hw_internal_aspm_clkreq_enable(tp, true);
}
static void rtl_hw_start_8168(struct rtl8169_private *tp)
@@ -6364,7 +6445,7 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
tp->cur_tx = tp->dirty_tx = 0;
}
-static void rtl_reset_work(struct rtl8169_private *tp)
+static void _rtl_reset_work(struct rtl8169_private *tp)
{
struct net_device *dev = tp->dev;
int i;
@@ -6384,6 +6465,33 @@ static void rtl_reset_work(struct rtl8169_private *tp)
napi_enable(&tp->napi);
rtl_hw_start(tp);
netif_wake_queue(dev);
+}
+
+static void rtl8169_check_link_status(struct net_device *dev,
+ struct rtl8169_private *tp)
+{
+ struct device *d = tp_to_dev(tp);
+
+ if (tp->link_ok(tp)) {
+ rtl_link_chg_patch(tp);
+ /* This is to cancel a scheduled suspend if there's one. */
+ if (pm_request_resume(d))
+ _rtl_reset_work(tp);
+ netif_carrier_on(dev);
+ if (net_ratelimit())
+ netif_info(tp, ifup, dev, "link up\n");
+ } else {
+ netif_carrier_off(dev);
+ netif_info(tp, ifdown, dev, "link down\n");
+ pm_runtime_idle(d);
+ }
+}
+
+static void rtl_reset_work(struct rtl8169_private *tp)
+{
+ struct net_device *dev = tp->dev;
+
+ _rtl_reset_work(tp);
rtl8169_check_link_status(dev, tp);
}
@@ -7649,8 +7757,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* disable ASPM completely as that cause random device stop working
* problems as well as full system hangs for some PCIe devices users */
- pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
- PCIE_LINK_STATE_CLKPM);
+ if (!enable_aspm) {
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
+ PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM);
+ netif_info(tp, probe, dev, "ASPM disabled\n");
+ }
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pcim_enable_device(pdev);
--
2.17.0
^ permalink raw reply related
* Re: [PATCH] r8169: Reinstate ALDPS and ASPM support
From: Kai Heng Feng @ 2018-06-05 5:02 UTC (permalink / raw)
To: jrg.otte
Cc: David Miller, Hayes Wang, hkallweit1, romieu, Linux Netdev List,
Linux Kernel Mailing List, Ryankao
In-Reply-To: <20180605045812.17977-1-kai.heng.feng@canonical.com>
Hi Jörg Otte,
Can you give this patch a try?
Since you are the only one that reported ALDPS/ASPM regression,
And I think this patch should solve the issue you had [1].
Hopefully we don't need to go down the rabbit hole of blacklist/whitelist...
Kai-Heng
[1] https://lkml.org/lkml/2013/1/5/36
> On Jun 5, 2018, at 12:58 PM, Kai-Heng Feng <kai.heng.feng@canonical.com>
> wrote:
>
> This patch reinstate ALDPS and ASPM support on r8169.
>
> On some Intel platforms, ASPM support on r8169 is the key factor to let
> Package C-State achieve PC8. Without ASPM support, the deepest Package
> C-State can hit is PC3. PC8 can save additional ~3W in comparison with
> PC3.
>
> This patch is from Realtek.
>
> Fixes: e0c075577965 ("r8169: enable ALDPS for power saving")
> Fixes: d64ec841517a ("r8169: enable internal ASPM and clock request
> settings")
>
> Cc: Ryankao <ryankao@realtek.com>
> Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> ---
> drivers/net/ethernet/realtek/r8169.c | 190 +++++++++++++++++++++------
> 1 file changed, 151 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/net/ethernet/realtek/r8169.c
> b/drivers/net/ethernet/realtek/r8169.c
> index 75dfac0248f4..a28ef20be221 100644
> --- a/drivers/net/ethernet/realtek/r8169.c
> +++ b/drivers/net/ethernet/realtek/r8169.c
> @@ -319,6 +319,8 @@ static const struct pci_device_id rtl8169_pci_tbl[] = {
>
> MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
>
> +static int enable_aspm = 1;
> +static int enable_aldps = 1;
> static int use_dac = -1;
> static struct {
> u32 msg_enable;
> @@ -817,6 +819,10 @@ struct rtl8169_private {
>
> MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
> MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
> +module_param(enable_aspm, int, 0);
> +MODULE_PARM_DESC(enable_aspm, "Enable ASPM");
> +module_param(enable_aldps, int, 0);
> +MODULE_PARM_DESC(enable_aldps, "Enable ALDPS");
> module_param(use_dac, int, 0);
> MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
> module_param_named(debug, debug.msg_enable, int, 0);
> @@ -1567,25 +1573,6 @@ static void rtl_link_chg_patch(struct
> rtl8169_private *tp)
> }
> }
>
> -static void rtl8169_check_link_status(struct net_device *dev,
> - struct rtl8169_private *tp)
> -{
> - struct device *d = tp_to_dev(tp);
> -
> - if (tp->link_ok(tp)) {
> - rtl_link_chg_patch(tp);
> - /* This is to cancel a scheduled suspend if there's one. */
> - pm_request_resume(d);
> - netif_carrier_on(dev);
> - if (net_ratelimit())
> - netif_info(tp, ifup, dev, "link up\n");
> - } else {
> - netif_carrier_off(dev);
> - netif_info(tp, ifdown, dev, "link down\n");
> - pm_runtime_idle(d);
> - }
> -}
> -
> #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
>
> static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
> @@ -3520,6 +3507,15 @@ static void rtl8168e_1_hw_phy_config(struct
> rtl8169_private *tp)
> rtl_writephy(tp, 0x0d, 0x4007);
> rtl_writephy(tp, 0x0e, 0x0000);
> rtl_writephy(tp, 0x0d, 0x0000);
> +
> + /* Check ALDPS bit, disable it if enabled */
> + rtl_writephy(tp, 0x1f, 0x0000);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
> + else if (rtl_readphy(tp, 0x15) & 0x1000)
> + rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1000);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
> @@ -3627,6 +3623,15 @@ static void rtl8168e_2_hw_phy_config(struct
> rtl8169_private *tp)
>
> /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
> rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
> +
> + /* Check ALDPS bit, disable it if enabled */
> + rtl_writephy(tp, 0x1f, 0x0000);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
> + else if (rtl_readphy(tp, 0x15) & 0x1000)
> + rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1000);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
> @@ -3649,6 +3654,15 @@ static void rtl8168f_hw_phy_config(struct
> rtl8169_private *tp)
> rtl_writephy(tp, 0x05, 0x8b86);
> rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000);
> rtl_writephy(tp, 0x1f, 0x0000);
> +
> + /* Check ALDPS bit, disable it if enabled */
> + rtl_writephy(tp, 0x1f, 0x0000);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x15, 0x1000, 0x0000);
> + else if (rtl_readphy(tp, 0x15) & 0x1000)
> + rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1000);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
> @@ -3865,7 +3879,9 @@ static void rtl8168g_1_hw_phy_config(struct
> rtl8169_private *tp)
>
> /* Check ALDPS bit, disable it if enabled */
> rtl_writephy(tp, 0x1f, 0x0a43);
> - if (rtl_readphy(tp, 0x10) & 0x0004)
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
> + else if (rtl_readphy(tp, 0x10) & 0x0004)
> rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
>
> rtl_writephy(tp, 0x1f, 0x0000);
> @@ -3874,6 +3890,14 @@ static void rtl8168g_1_hw_phy_config(struct
> rtl8169_private *tp)
> static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp)
> {
> rtl_apply_firmware(tp);
> +
> + rtl_writephy(tp, 0x1f, 0x0a43);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
> + else if (rtl_readphy(tp, 0x10) & 0x0004)
> + rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
> @@ -3980,7 +4004,9 @@ static void rtl8168h_1_hw_phy_config(struct
> rtl8169_private *tp)
>
> /* Check ALDPS bit, disable it if enabled */
> rtl_writephy(tp, 0x1f, 0x0a43);
> - if (rtl_readphy(tp, 0x10) & 0x0004)
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
> + else if (rtl_readphy(tp, 0x10) & 0x0004)
> rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
>
> rtl_writephy(tp, 0x1f, 0x0000);
> @@ -4053,7 +4079,9 @@ static void rtl8168h_2_hw_phy_config(struct
> rtl8169_private *tp)
>
> /* Check ALDPS bit, disable it if enabled */
> rtl_writephy(tp, 0x1f, 0x0a43);
> - if (rtl_readphy(tp, 0x10) & 0x0004)
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
> + else if (rtl_readphy(tp, 0x10) & 0x0004)
> rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
>
> rtl_writephy(tp, 0x1f, 0x0000);
> @@ -4095,7 +4123,9 @@ static void rtl8168ep_1_hw_phy_config(struct
> rtl8169_private *tp)
>
> /* Check ALDPS bit, disable it if enabled */
> rtl_writephy(tp, 0x1f, 0x0a43);
> - if (rtl_readphy(tp, 0x10) & 0x0004)
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
> + else if (rtl_readphy(tp, 0x10) & 0x0004)
> rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
>
> rtl_writephy(tp, 0x1f, 0x0000);
> @@ -4186,7 +4216,9 @@ static void rtl8168ep_2_hw_phy_config(struct
> rtl8169_private *tp)
>
> /* Check ALDPS bit, disable it if enabled */
> rtl_writephy(tp, 0x1f, 0x0a43);
> - if (rtl_readphy(tp, 0x10) & 0x0004)
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x10, 0x0004, 0x0000);
> + else if (rtl_readphy(tp, 0x10) & 0x0004)
> rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
>
> rtl_writephy(tp, 0x1f, 0x0000);
> @@ -4233,6 +4265,15 @@ static void rtl8105e_hw_phy_config(struct
> rtl8169_private *tp)
> rtl_apply_firmware(tp);
>
> rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
> +
> + /* Check ALDPS bit, disable it if enabled */
> + rtl_writephy(tp, 0x1f, 0x0000);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x18, 0x1000, 0x0000);
> + else if (rtl_readphy(tp, 0x18) & 0x1000)
> + rtl_w0w1_phy(tp, 0x18, 0x0000, 0x1000);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
> @@ -4250,6 +4291,15 @@ static void rtl8402_hw_phy_config(struct
> rtl8169_private *tp)
> rtl_writephy(tp, 0x10, 0x401f);
> rtl_writephy(tp, 0x19, 0x7030);
> rtl_writephy(tp, 0x1f, 0x0000);
> +
> + /* Check ALDPS bit, disable it if enabled */
> + rtl_writephy(tp, 0x1f, 0x0000);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x18, 0x1000, 0x0000);
> + else if (rtl_readphy(tp, 0x18) & 0x1000)
> + rtl_w0w1_phy(tp, 0x18, 0x0000, 0x1000);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
> @@ -4272,6 +4322,15 @@ static void rtl8106e_hw_phy_config(struct
> rtl8169_private *tp)
> rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
>
> rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
> +
> + /* Check ALDPS bit, disable it if enabled */
> + rtl_writephy(tp, 0x1f, 0x0000);
> + if (enable_aldps)
> + rtl_w0w1_phy(tp, 0x18, 0x1000, 0x0000);
> + else if (rtl_readphy(tp, 0x18) & 0x1000)
> + rtl_w0w1_phy(tp, 0x18, 0x0000, 0x1000);
> +
> + rtl_writephy(tp, 0x1f, 0x0000);
> }
>
> static void rtl_hw_phy_config(struct net_device *dev)
> @@ -5290,6 +5349,18 @@ static void rtl_pcie_state_l2l3_enable(struct
> rtl8169_private *tp, bool enable)
> RTL_W8(tp, Config3, data);
> }
>
> +static void rtl_hw_internal_aspm_clkreq_enable(struct rtl8169_private *tp,
> + bool enable)
> +{
> + if (enable) {
> + RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
> + RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
> + } else {
> + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + }
> +}
> +
> static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
> {
> RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
> @@ -5646,9 +5717,10 @@ static void rtl_hw_start_8168g_1(struct
> rtl8169_private *tp)
> rtl_hw_start_8168g(tp);
>
> /* disable aspm and clock request before access ephy */
> - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + rtl_hw_internal_aspm_clkreq_enable(tp, false);
> rtl_ephy_init(tp, e_info_8168g_1, ARRAY_SIZE(e_info_8168g_1));
> + if (enable_aspm)
> + rtl_hw_internal_aspm_clkreq_enable(tp, true);
> }
>
> static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
> @@ -5681,9 +5753,10 @@ static void rtl_hw_start_8411_2(struct
> rtl8169_private *tp)
> rtl_hw_start_8168g(tp);
>
> /* disable aspm and clock request before access ephy */
> - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + rtl_hw_internal_aspm_clkreq_enable(tp, false);
> rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2));
> + if (enable_aspm)
> + rtl_hw_internal_aspm_clkreq_enable(tp, true);
> }
>
> static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
> @@ -5700,8 +5773,7 @@ static void rtl_hw_start_8168h_1(struct
> rtl8169_private *tp)
> };
>
> /* disable aspm and clock request before access ephy */
> - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + rtl_hw_internal_aspm_clkreq_enable(tp, false);
> rtl_ephy_init(tp, e_info_8168h_1, ARRAY_SIZE(e_info_8168h_1));
>
> RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | TXCFG_AUTO_FIFO);
> @@ -5780,6 +5852,9 @@ static void rtl_hw_start_8168h_1(struct
> rtl8169_private *tp)
> r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
> r8168_mac_ocp_write(tp, 0xc094, 0x0000);
> r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
> +
> + if (enable_aspm)
> + rtl_hw_internal_aspm_clkreq_enable(tp, true);
> }
>
> static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
> @@ -5831,11 +5906,13 @@ static void rtl_hw_start_8168ep_1(struct
> rtl8169_private *tp)
> };
>
> /* disable aspm and clock request before access ephy */
> - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + rtl_hw_internal_aspm_clkreq_enable(tp, false);
> rtl_ephy_init(tp, e_info_8168ep_1, ARRAY_SIZE(e_info_8168ep_1));
>
> rtl_hw_start_8168ep(tp);
> +
> + if (enable_aspm)
> + rtl_hw_internal_aspm_clkreq_enable(tp, true);
> }
>
> static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
> @@ -5847,14 +5924,16 @@ static void rtl_hw_start_8168ep_2(struct
> rtl8169_private *tp)
> };
>
> /* disable aspm and clock request before access ephy */
> - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + rtl_hw_internal_aspm_clkreq_enable(tp, false);
> rtl_ephy_init(tp, e_info_8168ep_2, ARRAY_SIZE(e_info_8168ep_2));
>
> rtl_hw_start_8168ep(tp);
>
> RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
> RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
> +
> + if (enable_aspm)
> + rtl_hw_internal_aspm_clkreq_enable(tp, true);
> }
>
> static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
> @@ -5868,8 +5947,7 @@ static void rtl_hw_start_8168ep_3(struct
> rtl8169_private *tp)
> };
>
> /* disable aspm and clock request before access ephy */
> - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> + rtl_hw_internal_aspm_clkreq_enable(tp, false);
> rtl_ephy_init(tp, e_info_8168ep_3, ARRAY_SIZE(e_info_8168ep_3));
>
> rtl_hw_start_8168ep(tp);
> @@ -5889,6 +5967,9 @@ static void rtl_hw_start_8168ep_3(struct
> rtl8169_private *tp)
> data = r8168_mac_ocp_read(tp, 0xe860);
> data |= 0x0080;
> r8168_mac_ocp_write(tp, 0xe860, data);
> +
> + if (enable_aspm)
> + rtl_hw_internal_aspm_clkreq_enable(tp, true);
> }
>
> static void rtl_hw_start_8168(struct rtl8169_private *tp)
> @@ -6364,7 +6445,7 @@ static void rtl8169_tx_clear(struct rtl8169_private
> *tp)
> tp->cur_tx = tp->dirty_tx = 0;
> }
>
> -static void rtl_reset_work(struct rtl8169_private *tp)
> +static void _rtl_reset_work(struct rtl8169_private *tp)
> {
> struct net_device *dev = tp->dev;
> int i;
> @@ -6384,6 +6465,33 @@ static void rtl_reset_work(struct rtl8169_private
> *tp)
> napi_enable(&tp->napi);
> rtl_hw_start(tp);
> netif_wake_queue(dev);
> +}
> +
> +static void rtl8169_check_link_status(struct net_device *dev,
> + struct rtl8169_private *tp)
> +{
> + struct device *d = tp_to_dev(tp);
> +
> + if (tp->link_ok(tp)) {
> + rtl_link_chg_patch(tp);
> + /* This is to cancel a scheduled suspend if there's one. */
> + if (pm_request_resume(d))
> + _rtl_reset_work(tp);
> + netif_carrier_on(dev);
> + if (net_ratelimit())
> + netif_info(tp, ifup, dev, "link up\n");
> + } else {
> + netif_carrier_off(dev);
> + netif_info(tp, ifdown, dev, "link down\n");
> + pm_runtime_idle(d);
> + }
> +}
> +
> +static void rtl_reset_work(struct rtl8169_private *tp)
> +{
> + struct net_device *dev = tp->dev;
> +
> + _rtl_reset_work(tp);
> rtl8169_check_link_status(dev, tp);
> }
>
> @@ -7649,8 +7757,12 @@ static int rtl_init_one(struct pci_dev *pdev,
> const struct pci_device_id *ent)
>
> /* disable ASPM completely as that cause random device stop working
> * problems as well as full system hangs for some PCIe devices users */
> - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
> - PCIE_LINK_STATE_CLKPM);
> + if (!enable_aspm) {
> + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
> + PCIE_LINK_STATE_L1 |
> + PCIE_LINK_STATE_CLKPM);
> + netif_info(tp, probe, dev, "ASPM disabled\n");
> + }
>
> /* enable device (incl. PCI PM wakeup and hotplug setup) */
> rc = pcim_enable_device(pdev);
> --
> 2.17.0
^ permalink raw reply
* Re: [PATCH net-next] net: metrics: add proper netlink validation
From: Eric Dumazet @ 2018-06-05 5:48 UTC (permalink / raw)
To: Eric Dumazet, David S . Miller; +Cc: netdev, Eric Dumazet, David Ahern
In-Reply-To: <20180604234601.261823-1-edumazet@google.com>
On 06/04/2018 04:46 PM, Eric Dumazet wrote:
> Before using nla_get_u32(), better make sure the attribute
> is of the proper size.
>
>
> Fixes: a919525ad832 ("net: Move fib_convert_metrics to metrics file")
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reported-by: syzbot <syzkaller@googlegroups.com>
> Cc: David Ahern <dsahern@gmail.com>
> ---
> net/ipv4/fib_semantics.c | 2 ++
> net/ipv4/metrics.c | 2 ++
> 2 files changed, 4 insertions(+)
>
> diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
> index 6608db23f54b6afdac0455650b47d64b1b22b255..9a890be8a0265edb78da225a82e2cac120f2150f 100644
> --- a/net/ipv4/fib_semantics.c
> +++ b/net/ipv4/fib_semantics.c
> @@ -717,6 +717,8 @@ bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi)
> nla_strlcpy(tmp, nla, sizeof(tmp));
> val = tcp_ca_get_key_by_name(fi->fib_net, tmp, &ecn_ca);
> } else {
> + if (nla_len(nla) != sizeof(u32)
Oh well, stupid typo.
> + return false;
> val = nla_get_u32(nla);
I will send a V2.
^ permalink raw reply
* Re: [PATCH net-next 3/3] mlxsw: Add extack messages for port_{un,}split failures
From: Ido Schimmel @ 2018-06-05 5:56 UTC (permalink / raw)
To: dsahern; +Cc: netdev, idosch, jiri, jakub.kicinski, David Ahern
In-Reply-To: <20180604221503.20329-4-dsahern@kernel.org>
On Mon, Jun 04, 2018 at 03:15:03PM -0700, dsahern@kernel.org wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Return messages in extack for port split/unsplit errors. e.g.,
> $ devlink port split swp1s1 count 4
> Error: mlxsw_spectrum: Port cannot be split further.
> devlink answers: Invalid argument
>
> $ devlink port unsplit swp4
> Error: mlxsw_spectrum: Port was not split.
> devlink answers: Invalid argument
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Thanks!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox