Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH stable 3.4 v2 1/2] ipv4: move route garbage collector to work queue
From: Marcelo Ricardo Leitner @ 2014-08-19 20:38 UTC (permalink / raw)
  To: David Miller; +Cc: hannes, netdev, eric.dumazet
In-Reply-To: <20140819.133422.1451297160651259753.davem@davemloft.net>

Em 19-08-2014 17:34, David Miller escreveu:
> From: Marcelo Ricardo Leitner <mleitner@redhat.com>
> Date: Tue, 19 Aug 2014 17:31:50 -0300
>
>> Sorry to bother you but WDYT, is this patchset more appropriate?
>
> Yes it is and it's queued up in patchwork for -stable.

Ohh, right, thanks!

Marcelo

^ permalink raw reply

* Re: [patch net-next] bonding: create netlink event when bonding option is changed
From: Jiri Pirko @ 2014-08-19 20:37 UTC (permalink / raw)
  To: Andy Gospodarek
  Cc: netdev, davem, j.vosburgh, vfalico, andy, nikolay, dingtianhong,
	sfeldma
In-Reply-To: <20140819203401.GA1954@gospo.home.greyhouse.net>

Tue, Aug 19, 2014 at 10:34:01PM CEST, gospo@cumulusnetworks.com wrote:
>On Tue, Aug 19, 2014 at 04:02:12PM +0200, Jiri Pirko wrote:
>> Userspace needs to be notified if one changes some option.
>> 
>> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
>> ---
>>  drivers/net/bonding/bond_options.c | 2 ++
>>  include/linux/netdevice.h          | 1 +
>>  2 files changed, 3 insertions(+)
>> 
>> diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
>> index dc73463..d8dc17f 100644
>> --- a/drivers/net/bonding/bond_options.c
>> +++ b/drivers/net/bonding/bond_options.c
>> @@ -625,6 +625,8 @@ int __bond_opt_set(struct bonding *bond,
>>  out:
>>  	if (ret)
>>  		bond_opt_error_interpret(bond, opt, ret, val);
>> +	else
>> +		call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
>Is this valuable where the configuration change to the bonding driver
>came from netlink.  Do you have a good example why this useful in the
>netlink path as well as when using sysfs?  It would seem more logical to
>add call_netdevice_notifiers to bonding_sysfs_store_option so anything
>listening to netlink messages or the netlink cache can know to check for
>changes.

But this is called for sysfs as well.

Example of use is that application can monitor rtnetlink to see if for
example active slave changed, or whatever other option changed.

>
>>  
>>  	return ret;
>>  }
>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> index 967ddcc..44bc4bd 100644
>> --- a/include/linux/netdevice.h
>> +++ b/include/linux/netdevice.h
>> @@ -2017,6 +2017,7 @@ struct pcpu_sw_netstats {
>>  #define NETDEV_CHANGEUPPER	0x0015
>>  #define NETDEV_RESEND_IGMP	0x0016
>>  #define NETDEV_PRECHANGEMTU	0x0017 /* notify before mtu change happened */
>> +#define NETDEV_CHANGEINFODATA	0x0018
>>  
>>  int register_netdevice_notifier(struct notifier_block *nb);
>>  int unregister_netdevice_notifier(struct notifier_block *nb);
>> -- 
>> 1.9.3
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net] vxlan: fix incorrect initializer in union vxlan_addr
From: Gerhard Stenzel @ 2014-08-19 20:36 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20140818.101143.2274310300741627370.davem@davemloft.net>

Trying again ... 

On 08/18/2014 07:11 PM, David Miller wrote:
...
> 
> Your patch was corrupted by your email client, also please do not
> indent your signoff.
> 
> THanks.
> 


The first initializer in the following

        union vxlan_addr ipa = {
            .sin.sin_addr.s_addr = tip,
            .sa.sa_family = AF_INET,
        };

is optimised away by the compiler, due to the second initializer,
therefore initialising .sin.sin_addr.s_addr always to 0.
This results in netlink messages indicating a L3 miss never contain the
missed IP address. This was observed with GCC 4.8 and 4.9. I do not know about previous versions.
The problem affects user space programs relying on an IP address being
sent as part of a netlink message indicating a L3 miss.

Changing
            .sa.sa_family = AF_INET,
to
            .sin.sin_family = AF_INET,
fixes the problem.

Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com>

--- 

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 1fb7b37..beb377b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1327,7 +1327,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 	} else if (vxlan->flags & VXLAN_F_L3MISS) {
 		union vxlan_addr ipa = {
 			.sin.sin_addr.s_addr = tip,
-			.sa.sa_family = AF_INET,
+			.sin.sin_family = AF_INET,
 		};
 
 		vxlan_ip_miss(dev, &ipa);
@@ -1488,7 +1488,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
 	} else if (vxlan->flags & VXLAN_F_L3MISS) {
 		union vxlan_addr ipa = {
 			.sin6.sin6_addr = msg->target,
-			.sa.sa_family = AF_INET6,
+			.sin6.sin6_family = AF_INET6,
 		};
 
 		vxlan_ip_miss(dev, &ipa);
@@ -1521,7 +1521,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 		if (!n && (vxlan->flags & VXLAN_F_L3MISS)) {
 			union vxlan_addr ipa = {
 				.sin.sin_addr.s_addr = pip->daddr,
-				.sa.sa_family = AF_INET,
+				.sin.sin_family = AF_INET,
 			};
 
 			vxlan_ip_miss(dev, &ipa);
@@ -1542,7 +1542,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 		if (!n && (vxlan->flags & VXLAN_F_L3MISS)) {
 			union vxlan_addr ipa = {
 				.sin6.sin6_addr = pip6->daddr,
-				.sa.sa_family = AF_INET6,
+				.sin6.sin6_family = AF_INET6,
 			};
 
 			vxlan_ip_miss(dev, &ipa);

^ permalink raw reply related

* Re: [PATCH stable 3.4 v2 1/2] ipv4: move route garbage collector to work queue
From: David Miller @ 2014-08-19 20:34 UTC (permalink / raw)
  To: mleitner; +Cc: hannes, netdev, eric.dumazet
In-Reply-To: <53F3B436.8050407@redhat.com>

From: Marcelo Ricardo Leitner <mleitner@redhat.com>
Date: Tue, 19 Aug 2014 17:31:50 -0300

> Sorry to bother you but WDYT, is this patchset more appropriate?

Yes it is and it's queued up in patchwork for -stable.

^ permalink raw reply

* Re: [patch net-next] bonding: create netlink event when bonding option is changed
From: Andy Gospodarek @ 2014-08-19 20:34 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, j.vosburgh, vfalico, andy, nikolay, dingtianhong,
	sfeldma
In-Reply-To: <1408456932-10318-1-git-send-email-jiri@resnulli.us>

On Tue, Aug 19, 2014 at 04:02:12PM +0200, Jiri Pirko wrote:
> Userspace needs to be notified if one changes some option.
> 
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> ---
>  drivers/net/bonding/bond_options.c | 2 ++
>  include/linux/netdevice.h          | 1 +
>  2 files changed, 3 insertions(+)
> 
> diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
> index dc73463..d8dc17f 100644
> --- a/drivers/net/bonding/bond_options.c
> +++ b/drivers/net/bonding/bond_options.c
> @@ -625,6 +625,8 @@ int __bond_opt_set(struct bonding *bond,
>  out:
>  	if (ret)
>  		bond_opt_error_interpret(bond, opt, ret, val);
> +	else
> +		call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
Is this valuable where the configuration change to the bonding driver
came from netlink.  Do you have a good example why this useful in the
netlink path as well as when using sysfs?  It would seem more logical to
add call_netdevice_notifiers to bonding_sysfs_store_option so anything
listening to netlink messages or the netlink cache can know to check for
changes.

>  
>  	return ret;
>  }
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 967ddcc..44bc4bd 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -2017,6 +2017,7 @@ struct pcpu_sw_netstats {
>  #define NETDEV_CHANGEUPPER	0x0015
>  #define NETDEV_RESEND_IGMP	0x0016
>  #define NETDEV_PRECHANGEMTU	0x0017 /* notify before mtu change happened */
> +#define NETDEV_CHANGEINFODATA	0x0018
>  
>  int register_netdevice_notifier(struct notifier_block *nb);
>  int unregister_netdevice_notifier(struct notifier_block *nb);
> -- 
> 1.9.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH stable 3.4 v2 1/2] ipv4: move route garbage collector to work queue
From: Marcelo Ricardo Leitner @ 2014-08-19 20:31 UTC (permalink / raw)
  To: davem; +Cc: hannes, netdev, eric.dumazet
In-Reply-To: <547688b69ee9a258cc04e4dad17a90ca6ab182d0.1408045325.git.mleitner@redhat.com>

Em 14-08-2014 16:44, Marcelo Ricardo Leitner escreveu:
> Currently the route garbage collector gets called by dst_alloc() if it
> have more entries than the threshold. But it's an expensive call, that
> don't really need to be done by then.
>
> Another issue with current way is that it allows running the garbage
> collector with the same start parameters on multiple CPUs at once, which
> is not optimal. A system may even soft lockup if the cache is big enough
> as the garbage collectors will be fighting over the hash lock entries.
>
> This patch thus moves the garbage collector to run asynchronously on a
> work queue, much similar to how rt_expire_check runs.
>
> There is one condition left that allows multiple executions, which is
> handled by the next patch.
>
> Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---
>
> Notes:
>      Hi,
>
>      This set is needed for stables <= 3.4, as the IPv4 route cache was
>      removed after that.
>
>      v1->v2: addressed indentation issue noticed by David Miller
>
>      Thanks!
>

Hi Dave,

Sorry to bother you but WDYT, is this patchset more appropriate?

Thanks,
Marcelo

^ permalink raw reply

* Re: [PATCH] TCP: add option for silent port knocking with integrity protection
From: Alexander Holler @ 2014-08-19 19:36 UTC (permalink / raw)
  To: Eric Dumazet, Christian Grothoff
  Cc: Jacob Appelbaum, Andi Kleen, Stephen Hemminger, David Miller,
	netdev, linux-kernel, knock
In-Reply-To: <1386858864.19078.60.camel@edumazet-glaptop2.roam.corp.google.com>

Am 12.12.2013 15:34, schrieb Eric Dumazet:

A bit late, but I've just stumbled over that feature which I do like a lot.

> Very soon you'll need to support different secrets. You do not want all
> clients share a common secret, do you ? How can a server change its
> secret without disrupting clients ?

Impossible because you already need a channel if you want to identify 
the client. But that isn't the intention of the patch. You still have 
the usual authentication stuff in the service you want to hide. It's 
about hiding (from someone outside a closed group) the possibility to 
authenticate.

> How having a constant initial sequence number can even be valid ?
> What about TCP timestamps being not available at all ?
> How typical servers can be behind a load balancer ?
> Or am I missing something ?

It doesn't have to work in every environment and it doesn't have to 
solve all existing problems in the world. ;)

But it enables people to protect a bit more against malicious people or 
governments.

And it is really very easy to use. It took me around half an hour to 
find the places in openvpn and openssh where I had to add the 
setsockopt() call and it can be used even easier with preloading 
libknockify.so.

There can be found much more useless options in the kernel. At least I 
like it and it fits my needs too.

Regards,

Alexander Holler

^ permalink raw reply

* Deprecating the *generation* of IPv6 atomic fragments (Fwd: DoS attacks (ICMPv6-based) resulting from IPv6 EH drops)
From: Fernando Gont @ 2014-08-19 18:58 UTC (permalink / raw)
  To: netdev
In-Reply-To: <53F33C4F.2070807@si6networks.com>

Folks,

(Heads up):
<http://www.ietf.org/id/draft-gont-6man-deprecate-atomfrag-generation-00.txt>
     -- (Rationale below)

Other than the IPv6 stack update, being able to filter packets based on
the "Next-Hop MTU" field of ICMPv6 Packet Too Big messages could be a
nice thing to have.

Thanks!

Cheers,
Fernando




-------- Forwarded Message --------
Subject: DoS attacks (ICMPv6-based) resulting from IPv6 EH drops
Date: Tue, 19 Aug 2014 09:00:15 -0300
From: Fernando Gont <fgont@si6networks.com>
To: IPv6 Operations <v6ops@ietf.org>
CC: 'opsec@ietf.org' <opsec@ietf.org>

Folks,

Ten days ago or so we published this I-D:
<http://www.ietf.org/internet-drafts/draft-gont-v6ops-ipv6-ehs-in-real-world-00.txt>

Section 5.2 of the I-D discusses a possible attack vector based on a
combination of "forged" ICMPv6 PTB messages and IPv6 frag drops by
operators, along with proposed countermeasures -- on which we'd like to
hear your comments.

Since Section 5.2 is in the draft, let me offer a more informal and
practical explanation:

1) It is known that filtering of packets containing IPv6 Extension
Headers (including the Fragment Header) is widespread (see our I-D above)

2) Let us assume that Host A is communicating with Server B, and that
some node filters fragments between Host A and Server B.

3) An attacker sends a spoofed ICMPv6 PTB to server B, with a "Next Hop
MTU<1280), in the hopes of eliciting "atomic fragments" (see
<http://tools.ietf.org/rfc/rfc6946.txt>) from now on.

4) Now server B starts sending IPv6 atomic fragments... And since they
include a frag header (and in '2)' above we noted that frags are dropped
on that path), these packets get dropped (i.e., DoS).


"Demo" with the icmp6 tool
(<http://www.si6networks.com/tools/ipv6toolkit>) -- (some addresses have
been changed (anonimized), but it is trivial to pick a victim server...)

"2001:db8:1:10:0:1991:8:25" is the server, and
"2001:5c0:1000:a::e7d" is my own address):

---- cut here ----
***** First of all, I telnet to port 80 of the server, and
everything works as expected ****

fgont@satellite:~$ telnet 2001:db8:1:10:0:1991:8:25 80
Trying 2001:db8:1:10:0:1991:8:25...
Connected to 2001:db8:1:10:0:1991:8:25.
Escape character is '^]'.
^CConnection closed by foreign host.

**** Now I send the forget ICMPv6 PTB ****

fgont@satellite:~$ sudo icmp6  --icmp6-packet-too-big -d
2001:db8:1:10:0:1991:8:25 --peer-addr 2001:5c0:1000:a::e7d --mtu 1000 -o
80 -v
icmp6: Security assessment tool for attack vectors based on ICMPv6 error
messages

IPv6 Source Address: 2001:5c0:1000:a::e7d (automatically selected)
IPv6 Destination Address: 2001:db8:1:10:0:1991:8:25
IPv6 Hop Limit: 227 (randomized)
ICMPv6 Packet Too Big (Type 2), Code 0
Next-Hop MTU: 1000
Payload Type: IPv6/TCP (default)
Source Address: 2001:db8:1:10:0:1991:8:25 (automatically-selected)
Destination Address: 2001:5c0:1000:a::e7d
Hop Limit: 237 (randomized)
Source Port: 80	Destination Port: 38189 (randomized)
SEQ Number: 734463213 (randomized)	ACK Number: 866605720 (randomized)
Flags: A (default)	Window: 18944 (randomized)	URG Pointer: 0 (default)
Initial attack packet(s) sent successfully.


***** And now I try the same telnet command as above... but it fails,
because the frags from the server to me are getting dropped somewhere ****

fgont@satellite:~$ telnet 2001:db8:1:10:0:1991:8:25 80
Trying 2001:db8:1:10:0:1991:8:25...
[timeout]
---- cut here ----


Of course, in this particular case I just "shot myself". But one could
do this to DoS connections between mailservers, etc.

A nice question is: what if e.g....

1) some BGP servers accept ICMPv6 PTB that claim an MTU < 1280, and
react (as expected) by generating atomic fragments, *and*,

2) These same BGP servers deem fragmentation as "harmful", and hence
drop such fragments

you could essentially DoS traffic between them

As noted in the I-D, the mitigations seem to be:

1) Artificially limit your packets to 1280, and drop all incoming ICMPv6
PTB, or,

2) Have your device just drop ICMPv6 PTB that claim a Next-Hop MTU
smaller than 1280.

Thoughts?
-- 
Fernando Gont
SI6 Networks
e-mail: fgont@si6networks.com
PGP Fingerprint: 6666 31C6 D484 63B2 8FB1 E3C4 AE25 0D55 1D4E 7492







-- 
Fernando Gont
e-mail: fernando@gont.com.ar || fgont@si6networks.com
PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1

^ permalink raw reply

* Re: [PATCH] ath9k_htc: advertise support for TDLS
From: Csaba Kiraly @ 2014-08-19 19:00 UTC (permalink / raw)
  To: Oleksij Rempel, linville; +Cc: linux-wireless, ath9k-devel, netdev
In-Reply-To: <53F30A8B.6000202@rempel-privat.de>

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

On 19/08/2014 10:27, Oleksij Rempel wrote:
> Oppss... wrong email address.
>
> Am 19.08.2014 um 10:25 schrieb Oleksij Rempel:
>> Am 18.08.2014 um 01:53 schrieb Csaba Kiraly:
>>> Based on a quick test with AR9271, TDLS seems to be working fine.
>>>
>>> Tests were done with 2 Atheros AR9271 based devices with firmware
>>> 1.3 (sha1 8d49f928aa40ac53c729189bff1333cd373a7fb5), associated
>>> with a WAP54G access point.
>>
>> please, don't use firmware 1.3. Use git source, or you can get
>> precompiled version here:
>> https://github.com/olerem/ath9k-htc-firmware-blob

I have just tried it with the latest firmware from git 
(dc465e811c0272df7ec93b67de393129ff614173). Works fine.

>>
>>> TDLS worked fine both in WPA2 mode and
>>> without encryption. Stations maintained ping flood traffic between
>>> each other and towards the AP without significant losses.
>>>
>>> Not tested with AR7010.
>>
>> Seems ok for me. How can i reproduce testing environment?

Here it comes. I try to give a detailed description, although I suppose
you don't need most of it :)
I have used two laptops, two TP-Link TL-WN722N USB devices, and a
Linksys WAP54g AP.

# 0) stop conflicting services, clean up files
service network-manager stop
killall wpa_supplicant
killall dhclient
rm -rf /run/wpa_supplicant

# 1) on both nodes, start wpa_supplicant and connect to the same AP.
# Conf files attached
hostap/wpa_supplicant/wpa_supplicant -D nl80211 -i wlan2 -c wpa_supplicant_wap54g_WPA2.conf

# 2) on each node, configure IP addresses (or start dhclient)
ifconfig wlan2 $IP1
ifconfig wlan2 $IP2

# 3) start pinging the other node
ping $IP2

# 4) start pinging the AP
ping $IPAP

# 5) get MAC of node2's Atheros card
# get it on node2, or directly on node1 from the arp cache
arp -n

# 6) on node1, start wpa_cli
hostap/wpa_supplicant/wpa_cli -i wlan2

# 7) on node1, in wpa_cli, start the TDLS setup
tdls_setup <MAC2>

# 8) verify that TDLS works
# - ping time will reduce (in my case it went from 1.6 ms to 1 ms)
# - ping time to the AP should remain the same
# - node2's MAC will appear in ath9k_htc debugfs
ls /sys/kernel/debug/ieee80211/phy1/netdev:wlan2/stations
# - look inside the debugfs folder for more details

# 9) stress test
ping -f $IP2

# 10) disable encryption in the AP and repeat the same with the "open" config file

# pitfalls and notes
- APs could interfere in various ways with the test. Some models could
set the TDLS prohibit flag. Others (like my Huawei E587) could
work at the beginning but deauthenticate the nodes after 20-30 seconds.
- I didn't check 802.11n
- I have used the stock 3.16.0 kernel as the base, since 
wireless-testing with tag master-2014-08-11 gave kernel panic
during wlan scan, even without my patch (but this is for another mail)
- use wpa_passphrase to generate the wpa_supplicant WPA2 config file

Csaba

>>
>>> TDLS was enabled in earlier patches the same way for other
>>> Atheros drivers:
>>> ath9k (fd6562344dea2b8b2a5d644cf971f4e56004500a),
>>> and carl9170 (d1f3de71a584a82ee4e84505fce9acccf40215ff).
>>>
>>> Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
>>> ---
>>>   drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 ++
>>>   1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
>>> index 8a3bd5f..d779f4f 100644
>>> --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
>>> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
>>> @@ -592,6 +592,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
>>>   	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
>>>   			    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
>>>
>>> +	hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
>>> +
>>>   	hw->queues = 4;
>>>   	hw->max_listen_interval = 1;
>>>
>>>
>>
>>
>
>


[-- Attachment #2: wpa_supplicant_wap54g_open.conf --]
[-- Type: text/plain, Size: 109 bytes --]

ctrl_interface=/run/wpa_supplicant
# reading passphrase from stdin
network={
	ssid="wap54g"
	key_mgmt=NONE
}

[-- Attachment #3: wpa_supplicant_wap54g_WPA2.conf --]
[-- Type: text/plain, Size: 184 bytes --]

ctrl_interface=/run/wpa_supplicant
# reading passphrase from stdin
network={
	ssid="wap54g"
	#psk="atheros9271"
	psk=d5b66e5d295afb5892f2a8ad79d8a82b35f4554f8cc917b06085f8b7ffb5dd13
}

^ permalink raw reply

* [PATCH 3/3] tg3: Fix tx_pending check for MAX_SKB_FRAGS
From: Benjamin Poirier @ 2014-08-19 18:52 UTC (permalink / raw)
  To: Prashant Sreedharan, Michael Chan; +Cc: netdev, linux-kernel
In-Reply-To: <1408474371-19509-1-git-send-email-bpoirier@suse.de>

The rest of the driver assumes at least one free descriptor in the tx ring.
Therefore, since an skb with max frags takes up (MAX_SKB_FRAGS + 1)
descriptors, tx_pending must be > (MAX_SKB_FRAGS + 1).

Signed-off-by: Benjamin Poirier <bpoirier@suse.de>
---

Currently, it is possible to set tx_pending = MAX_SKB_FRAGS + 1. This leads to
a netdev watchdog tx timeout. Depending on whether the previous patches in
this series are applied or not, the timeout happens as soon as tx_pending is
updated or after an skb with max frags is submitted for transmission.

I reproduced this bug using the same approach explained in patch 1.
The bug reproduces with tx_pending = 18

---
 drivers/net/ethernet/broadcom/tg3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 7022f6d..27e2701 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12328,7 +12328,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 	if ((ering->rx_pending > tp->rx_std_ring_mask) ||
 	    (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) ||
 	    (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
-	    (ering->tx_pending <= MAX_SKB_FRAGS))
+	    (ering->tx_pending <= MAX_SKB_FRAGS + 1))
 		return -EINVAL;
 
 	if (netif_running(dev)) {
-- 
1.8.4.5

^ permalink raw reply related

* [PATCH 1/3] tg3: Limit minimum tx queue wakeup threshold
From: Benjamin Poirier @ 2014-08-19 18:52 UTC (permalink / raw)
  To: Prashant Sreedharan, Michael Chan; +Cc: netdev, linux-kernel

tx_pending may be set by the user (via ethtool -G) to a low enough value that
TG3_TX_WAKEUP_THRESH becomes smaller than MAX_SKB_FRAGS + 1. This may cause
the tx queue to be waked when there are in fact not enough descriptors to
handle an skb with max frags. This in turn causes tg3_start_xmit() to return
NETDEV_TX_BUSY and print error messages. Fix the problem by putting a limit to
how low TG3_TX_WAKEUP_THRESH can go.

Signed-off-by: Benjamin Poirier <bpoirier@suse.de>
---

I noticed the problem in a 3.0 kernel when setting `ethtool eth0 -G tx 50` and
running a netperf TCP_STREAM test. The console fills up with 
[10597.596155] tg3 0000:06:00.0: eth0: BUG! Tx Ring full when queue awake!
The problem in tg3 remains in current kernels though it does not reproduce as
easily since "5640f76 net: use a per task frag allocator (v3.7-rc1)". I
reproduced on current kernels by using the fail_page_alloc fault injection
mechanism to force the creation of skbs with many order-0 frags. Note that the
following script may also trigger another bug (NETDEV WATCHDOG), which is
fixed in the next patch.

$ cat /tmp/doit.sh
#!/bin/bash

F="/sys/kernel/debug/fail_page_alloc"

echo -1 > "$F/times"
echo 0 > "$F/verbose"
echo 0 > "$F/ignore-gfp-wait"
echo 1 > "$F/task-filter"
echo 100 > "$F/probability"

netperf -H 192.168.9.30 -l100 -t omni -- -d send &

n=$!

sleep 0.3
echo 1 > "/proc/$n/make-it-fail"
sleep 10

kill "$n"

---
 drivers/net/ethernet/broadcom/tg3.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 3ac5d23..b11c0fd 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -202,7 +202,8 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 #endif
 
 /* minimum number of free TX descriptors required to wake up TX process */
-#define TG3_TX_WAKEUP_THRESH(tnapi)		((tnapi)->tx_pending / 4)
+#define TG3_TX_WAKEUP_THRESH(tnapi)	max_t(u32, (tnapi)->tx_pending / 4, \
+					      MAX_SKB_FRAGS + 1)
 #define TG3_TX_BD_DMA_MAX_2K		2048
 #define TG3_TX_BD_DMA_MAX_4K		4096
 
-- 
1.8.4.5

^ permalink raw reply related

* [PATCH 2/3] tg3: Fix tx_pending checks for tg3_tso_bug
From: Benjamin Poirier @ 2014-08-19 18:52 UTC (permalink / raw)
  To: Prashant Sreedharan, Michael Chan; +Cc: netdev, linux-kernel
In-Reply-To: <1408474371-19509-1-git-send-email-bpoirier@suse.de>

In tg3_set_ringparam(), the tx_pending test to cover the cases where
tg3_tso_bug() is entered has two problems
1) the check is only done for certain hardware whereas the workaround
is now used more broadly. IOW, the check may not be performed when it
is needed.
2) the check is too optimistic.

For example, with a 5761 (SHORT_DMA_BUG), tg3_set_ringparam() skips over the
"tx_pending <= (MAX_SKB_FRAGS * 3)" check because TSO_BUG is false. Even if it
did do the check, with a full sized skb, frag_cnt_est = 135 but the check is
for <= MAX_SKB_FRAGS * 3 (= 17 * 3 = 51). So the check is insufficient. This
leads to the following situation: by setting, ex. tx_pending = 100, there can
be an skb that triggers tg3_tso_bug() and that is large enough to cause
tg3_tso_bug() to stop the queue even when it is empty. We then end up with a
netdev watchdog transmit timeout.

Given that 1) some of the conditions tested for in tg3_tx_frag_set() apply
regardless of the chipset flags and that 2) it is difficult to estimate ahead
of time the max possible number of frames that a large skb may be split into
by gso, we instead take the approach of adjusting dev->gso_max_segs according
to the requested tx_pending size.

This puts us in the exceptional situation that a single skb that triggers
tg3_tso_bug() may require the entire tx ring. Usually the tx queue is woken up
when at least a quarter of it is available (TG3_TX_WAKEUP_THRESH) but that
would be insufficient now. To avoid useless wakeups, the tx queue wake up
threshold is made dynamic.

Signed-off-by: Benjamin Poirier <bpoirier@suse.de>
---

I reproduced this bug using the same approach explained in patch 1.
The bug reproduces with tx_pending <= 135

---
 drivers/net/ethernet/broadcom/tg3.c | 31 ++++++++++++++++++++-----------
 drivers/net/ethernet/broadcom/tg3.h |  1 +
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index b11c0fd..7022f6d 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6609,10 +6609,10 @@ static void tg3_tx(struct tg3_napi *tnapi)
 	smp_mb();
 
 	if (unlikely(netif_tx_queue_stopped(txq) &&
-		     (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))) {
+		     (tg3_tx_avail(tnapi) > tnapi->wakeup_thresh))) {
 		__netif_tx_lock(txq, smp_processor_id());
 		if (netif_tx_queue_stopped(txq) &&
-		    (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))
+		    (tg3_tx_avail(tnapi) > tnapi->wakeup_thresh))
 			netif_tx_wake_queue(txq);
 		__netif_tx_unlock(txq);
 	}
@@ -7838,11 +7838,14 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 		       struct netdev_queue *txq, struct sk_buff *skb)
 {
 	struct sk_buff *segs, *nskb;
-	u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
 
-	/* Estimate the number of fragments in the worst case */
-	if (unlikely(tg3_tx_avail(tnapi) <= frag_cnt_est)) {
+	if (unlikely(tg3_tx_avail(tnapi) <= skb_shinfo(skb)->gso_segs)) {
+		trace_printk("stopping queue, %d <= %d\n",
+			     tg3_tx_avail(tnapi), skb_shinfo(skb)->gso_segs);
 		netif_tx_stop_queue(txq);
+		trace_printk("stopped queue\n");
+		tnapi->wakeup_thresh = skb_shinfo(skb)->gso_segs;
+		BUG_ON(tnapi->wakeup_thresh >= tnapi->tx_pending);
 
 		/* netif_tx_stop_queue() must be done before checking
 		 * checking tx index in tg3_tx_avail() below, because in
@@ -7850,7 +7853,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 		 * netif_tx_queue_stopped().
 		 */
 		smp_mb();
-		if (tg3_tx_avail(tnapi) <= frag_cnt_est)
+		if (tg3_tx_avail(tnapi) <= tnapi->wakeup_thresh)
 			return NETDEV_TX_BUSY;
 
 		netif_tx_wake_queue(txq);
@@ -7905,12 +7908,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (unlikely(budget <= (skb_shinfo(skb)->nr_frags + 1))) {
 		if (!netif_tx_queue_stopped(txq)) {
 			netif_tx_stop_queue(txq);
+			tnapi->wakeup_thresh = TG3_TX_WAKEUP_THRESH(tnapi);
 
 			/* This is a hard error, log it. */
 			netdev_err(dev,
 				   "BUG! Tx Ring full when queue awake!\n");
 		}
-		return NETDEV_TX_BUSY;
+		smp_mb();
+		if (tg3_tx_avail(tnapi) <= tnapi->wakeup_thresh)
+			return NETDEV_TX_BUSY;
+
+		netif_tx_wake_queue(txq);
 	}
 
 	entry = tnapi->tx_prod;
@@ -8089,6 +8097,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	tnapi->tx_prod = entry;
 	if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) {
 		netif_tx_stop_queue(txq);
+		tnapi->wakeup_thresh = TG3_TX_WAKEUP_THRESH(tnapi);
 
 		/* netif_tx_stop_queue() must be done before checking
 		 * checking tx index in tg3_tx_avail() below, because in
@@ -8096,7 +8105,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		 * netif_tx_queue_stopped().
 		 */
 		smp_mb();
-		if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi))
+		if (tg3_tx_avail(tnapi) > tnapi->wakeup_thresh)
 			netif_tx_wake_queue(txq);
 	}
 
@@ -12319,9 +12328,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 	if ((ering->rx_pending > tp->rx_std_ring_mask) ||
 	    (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) ||
 	    (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
-	    (ering->tx_pending <= MAX_SKB_FRAGS) ||
-	    (tg3_flag(tp, TSO_BUG) &&
-	     (ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
+	    (ering->tx_pending <= MAX_SKB_FRAGS))
 		return -EINVAL;
 
 	if (netif_running(dev)) {
@@ -12341,6 +12348,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 	if (tg3_flag(tp, JUMBO_RING_ENABLE))
 		tp->rx_jumbo_pending = ering->rx_jumbo_pending;
 
+	dev->gso_max_segs = ering->tx_pending - 1;
 	for (i = 0; i < tp->irq_max; i++)
 		tp->napi[i].tx_pending = ering->tx_pending;
 
@@ -17817,6 +17825,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 		else
 			sndmbx += 0xc;
 	}
+	dev->gso_max_segs = TG3_DEF_TX_RING_PENDING - 1;
 
 	tg3_init_coal(tp);
 
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 461acca..6a7e13d 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -3006,6 +3006,7 @@ struct tg3_napi {
 	u32				tx_pending;
 	u32				last_tx_cons;
 	u32				prodmbox;
+	u32				wakeup_thresh;
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct tg3_tx_ring_info		*tx_buffers;
 
-- 
1.8.4.5

^ permalink raw reply related

* Re: [PATCH RFC v4 net-next 17/26] tracing: allow eBPF programs to be attached to events
From: Alexei Starovoitov @ 2014-08-19 18:39 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Daniel Borkmann, H. Peter Anvin, Andrew Morton, Linux API,
	Chema Gonzalez, Eric Dumazet, David S. Miller, Brendan Gregg,
	Linus Torvalds, Steven Rostedt, LKML, Peter Zijlstra, Kees Cook,
	Network Development, Ingo Molnar
In-Reply-To: <CALCETrUqop+UB-BhyX4Y41kELO+6kcFdS1F7ZyN0CzRwg4UGhA@mail.gmail.com>

On Fri, Aug 15, 2014 at 12:18 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Fri, Aug 15, 2014 at 12:16 PM, Alexei Starovoitov <ast@plumgrid.com> wrote:
>> This bpf_context struct for tracing is trying to answer the question:
>>  'what's the most convenient way to access tracepoint arguments
>> from a script'.
>> When kernel code has something like:
>>  trace_kfree_skb(skb, net_tx_action);
>> the script needs to be able to access this 'skb' and 'net_tx_action'
>> values through _single_ data structure.
>> In this proposal they are ctx->arg1 and ctx->arg2.
>> I've considered having different bpf_context's for every event, but
>> the complexity explodes. I need to hack all event definitions and so on.
>> imo it's better to move complexity to userspace, so program author
>> or high level language abstracts these details.
>
> I still don't understand why making them long instead of u64 is
> helpful, though.  I feel like I'm missing obvious here.

The problem statement:
- tracepoint events are defined as:
  TRACE_EVENT(sock_exceed_buf_limit,
    TP_PROTO(struct sock *sk, struct proto *prot, long allocated),
    TP_ARGS(sk, prot, allocated),

- from eBPF C program (or higher level language) I would like
  to access these tracepoint arguments as
  ctx->arg1, ctx->arg2, ctx->arg3

- accessing tracepoint fields after buffer copy is not an option,
  since it's unnecessary alloc/copy/free of a lot of values
  (including strings) per event that programs will mostly ignore.
  If needed, programs can fetch them on demand.

Bad approach #1
- define different bpf_context per event and customize eBPF verifier
  to have different program types per event, so particular program
  can be attached to one particular event only
Cons: quite complex, require trace/events/*.h hacking,
  one ebpf program cannot be used to attach to multiple events
So #1 is no go.

Approach #2
- define bpf_context once for all tracepoint events as:
  struct bpf_context {
    unsigned long arg1, arg2, arg3, ...
  };
  and main ftrace.h macro as:
    struct bpf_context ctx;
    populate_bpf_context(&ctx, args, 0, 0, 0, 0, 0);
    trace_filter_call_bpf(ftrace_file->filter, &ctx);
  where 'args' is a macro taken from TP_ARGS above and
  /* called from ftrace_raw_event_*() to copy args */
  void populate_bpf_context(struct bpf_context *ctx, ...)
  {
    va_start(args, ctx);
    ctx->arg1 = va_arg(args, unsigned long);
    ctx->arg2 = va_arg(args, unsigned long);
this approach relies on type promotion when args are passed
into vararg function.
On 64-bit arch our tracepoint arguments 'sk, prot, allocated' will
get stored into arg1, arg2, arg3 and the rest of argX will be zeros.
On 32-bit 'u64' types will be passed in two 'long' slots of vararg.
Obviously changing 'long' to 'u64' in bpf_context and in
populate_bpf_context() will not work, because types
are promoted to 'long'.
Disadvantage of this approach is that 32 vs 64 bit archs need to
deal with argX differently.
That's what you saw in this patch.

New approach #3
just discovered __MAPx() macro used by syscalls.h which can
be massaged for this use case, so define:
struct bpf_context {
  u64 arg1, arg2, arg3,...
};
and argument casting macro as:
#define __BPF_CAST1(a,...) __CAST_TO_U64(a)
#define __BPF_CAST2(a,...) __CAST_TO_U64(a), __BPF_CAST1(__VA_ARGS__)
..
#define __BPF_CAST(a,...)  __CAST_TO_U64(a), __BPF_CAST6(__VA_ARGS__)

so main ftrace.h macro becomes:
struct bpf_context __ctx = ((struct bpf_context) {
  __BPF_CAST(args, 0, 0, 0, 0, 0, 0)
});
trace_filter_call_bpf(ftrace_file->filter, &__ctx);

where 'args' is still the same 'sk, prot, allocated' from TP_ARGS.
Casting macro will cast 'sk' to u64 and will assign into arg1,
'prot' will be casted to u64 and assigned to arg2, etc

All good, but the tricky part is how to cast all arguments passed
into tracepoint events into u64 without warnings on
32-bit and 64-bit architectures.
The following:
#define __CAST_TO_U64(expr) (u64) expr
will not work, since compiler will be spewing warnings about
casting pointer to integer...
The following
#define __CAST_TO_U64(expr) (u64) (long) expr
will work fine on 64-bit architectures, since all integer and
pointer types will be warning-free casted and stored
in arg1, arg2, arg3, ...
but it won't work on 32-bit architectures, since full u64
tracepoint arguments will be chopped to 'long'.

It took a lot of macro wizardry to come up with the following:
/* cast any interger or pointer type to u64 without warnings */
#define __CAST_TO_U64(expr) \
         __builtin_choose_expr(sizeof(long) < sizeof(expr), \
                               (u64) (expr - ((typeof(expr))0)), \
                               (u64) (long) expr)
the tricky part is that GCC syntax-parses and warns
in both sides of __builtin_choose_expr(), so u64 case in 32-bit
archs needs to be fancy, so all types can go through it
warning free.
Though it's tricky the end result is nice.
The disadvantages of approach #2 are solved and tracepoint
arguments are stored into 'u64 argX' on both 32 and 64-bit archs.
The extra benefit is that this casting macro is way faster than
vararg approach #2.
So in V5 of this series I'm planning to use this new approach
unless there are better ideas.
full diff of this approach:
https://git.kernel.org/cgit/linux/kernel/git/ast/bpf.git/commit/?id=235d87dd7afd8d5262556cba7882d6efb25d8305

^ permalink raw reply

* Re: [PATCH v4 2/2] net: moxa: replace build_skb() with netdev_alloc_skb_ip_align() / memcpy()
From: Eric Dumazet @ 2014-08-19 18:31 UTC (permalink / raw)
  To: Jonas Jensen
  Cc: netdev, davem, linux-arm-kernel, linux-kernel, f.fainelli,
	bhutchings
In-Reply-To: <1408459784-9385-2-git-send-email-jonas.jensen@gmail.com>

On Tue, 2014-08-19 at 16:49 +0200, Jonas Jensen wrote:
> build_skb() is used to make skbs out of existing RX ring memory
> which is bad because the RX ring is allocated only once, on probe.
> Memory corruption occur because said memory is reclaimed, i.e.
> __kfree_skb() (and eventually put_page()).
> 
> Replace build_skb() with netdev_alloc_skb_ip_align() and use memcpy().
> Also, synchronize DMA memory before passing skb to napi_gro_receive().
> 
> Addresses https://bugzilla.kernel.org/show_bug.cgi?id=69041

Wow, this driver was really buggy.

Patch is not complete.

Instead of :

priv->rx_buf_size = RX_BUF_SIZE + 
		SKB_DATA_ALIGN(sizeof(struct skb_shared_info));

I think rx_buf_size can now be RX_BUF_SIZE

Another point is that priv->stats seems not needed, as ndev->stats could
be used instead (and remove moxart_mac_get_stats())

^ permalink raw reply

* Re: [PATCH v2] drivers: net: ethernet: intel: e1000: e1000_ethertoo.c coding style fixes
From: Joe Perches @ 2014-08-19 18:01 UTC (permalink / raw)
  To: Krzysztof Majzerowicz-Jaszcz; +Cc: Jeff Kirsher, Alexander Duyck, netdev, LKML
In-Reply-To: <53F38A84.3070702@vipserv.org>

On Tue, 2014-08-19 at 19:33 +0200, Krzysztof Majzerowicz-Jaszcz wrote:
> On 19/08/14 18:04, Jeff Kirsher wrote:
> > On Mon, Aug 18, 2014 at 3:21 PM, Krzysztof Majzerowicz-Jaszcz
> > <cristos@vipserv.org> wrote:
> >> Fixed many errors/warnings and checks in e1000_ethtool.c reported by checkpatch.pl
> >> Suggestions from Joe Perches and Alexander Duyck applied as well
> >>
> >> Signed-off-by: Krzysztof Majzerowicz-Jaszcz <cristos@vipserv.org>
> >> ---
> >>  drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 155 ++++++++++++-----------
> >>  1 file changed, 79 insertions(+), 76 deletions(-)
> >>
> > 
> > Thanks Krzysztof, I will add your patch to my queue and I can fix up
> > the patch title for you. :-)
> >
> 
> Thank you :). Sorry for that patch title - I guess that 'first pancake is always spoiled'.
> Nonetheless, that makes my first successful contribution to the kernel <yay> ;)

Yay for Krzysztof.

Now you could fix the same "*(foo + bar) == 0xXX" uses
in drivers/net/ethernet/intel/e1000e/ethtool.c

drivers/net/ethernet/intel/e1000e/ethtool.c:	if (*(skb->data + 3) == 0xFF)
drivers/net/ethernet/intel/e1000e/ethtool.c:		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
drivers/net/ethernet/intel/e1000e/ethtool.c:		    (*(skb->data + frame_size / 2 + 12) == 0xAF))

as well if you wanted to follow up on your first success.

^ permalink raw reply

* Re: [PATCH net v2 0/2] cbq: incorrectly low bandwidth blocks limited traffic
From: David Miller @ 2014-08-19 18:00 UTC (permalink / raw)
  To: vvs; +Cc: netdev, jhs, eric.dumazet, kuznet
In-Reply-To: <53EC72F1.5000501@parallels.com>

From: Vasily Averin <vvs@parallels.com>
Date: Thu, 14 Aug 2014 12:27:29 +0400

> v2: patch description changes
> Fixes: f0f6ee1f70c4 ("cbq: incorrect processing of high limits")
> 
> Mainstream commit f0f6ee1f70c4 ("cbq: incorrect processing of high limits")
> have side effect: if cbq bandwidth setting is less than real interface
> throughput non-limited traffic can delay limited traffic for a very long time.
> 
> This happen because of q->now changes incorrectly in cbq_dequeue():
> in described scenario L2T is much greater than real time delay,
> and q->now gets an extra boost for each transmitted packet.
> 
> Accumulated boost prevents update q->now, and blocked class can wait
> very long time until (q->now >= cl->undertime) will be true again.
> 
> More detailed problem description can be found here:
> http://www.spinics.net/lists/netdev/msg292493.html
> 
> Following patches should fix the problem.

Series applied, thanks.

^ permalink raw reply

* [PATCH net-next v2] r8169:add support for RTL8168H and RTL8107E
From: Chun-Hao Lin @ 2014-08-19 17:54 UTC (permalink / raw)
  To: netdev; +Cc: nic_swsd, linux-kernel, Chun-Hao Lin

RTL8168H is Realtek PCIe Gigabit Ethernet controller.
RTL8107E is Realtek PCIe Fast Ethernet controller.

This patch add support for these two chips.

Signed-off-by: Chun-Hao Lin <hau@realtek.com>
---
 drivers/net/ethernet/realtek/r8169.c | 470 +++++++++++++++++++++++++++++++++--
 1 file changed, 452 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 91652e7..c8375f6 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -52,6 +52,10 @@
 #define FIRMWARE_8106E_2	"rtl_nic/rtl8106e-2.fw"
 #define FIRMWARE_8168G_2	"rtl_nic/rtl8168g-2.fw"
 #define FIRMWARE_8168G_3	"rtl_nic/rtl8168g-3.fw"
+#define FIRMWARE_8168H_1	"rtl_nic/rtl8168h-1.fw"
+#define FIRMWARE_8168H_2	"rtl_nic/rtl8168h-2.fw"
+#define FIRMWARE_8107E_1	"rtl_nic/rtl8107e-1.fw"
+#define FIRMWARE_8107E_2	"rtl_nic/rtl8107e-2.fw"
 
 #ifdef RTL8169_DEBUG
 #define assert(expr) \
@@ -147,6 +151,10 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_42,
 	RTL_GIGA_MAC_VER_43,
 	RTL_GIGA_MAC_VER_44,
+	RTL_GIGA_MAC_VER_45,
+	RTL_GIGA_MAC_VER_46,
+	RTL_GIGA_MAC_VER_47,
+	RTL_GIGA_MAC_VER_48,
 	RTL_GIGA_MAC_NONE   = 0xff,
 };
 
@@ -282,6 +290,18 @@ static const struct {
 	[RTL_GIGA_MAC_VER_44] =
 		_R("RTL8411",		RTL_TD_1, FIRMWARE_8411_2,
 							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_45] =
+		_R("RTL8168h/8111h",	RTL_TD_1, FIRMWARE_8168H_1,
+							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_46] =
+		_R("RTL8168h/8111h",	RTL_TD_1, FIRMWARE_8168H_2,
+							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_47] =
+		_R("RTL8107e",		RTL_TD_1, FIRMWARE_8107E_1,
+							JUMBO_1K, false),
+	[RTL_GIGA_MAC_VER_48] =
+		_R("RTL8107e",		RTL_TD_1, FIRMWARE_8107E_2,
+							JUMBO_1K, false),
 };
 #undef _R
 
@@ -410,6 +430,7 @@ enum rtl8168_8101_registers {
 #define	EPHYAR_DATA_MASK		0xffff
 	DLLPR			= 0xd0,
 #define	PFM_EN				(1 << 6)
+#define	TX_10M_PS_EN			(1 << 7)
 	DBG_REG			= 0xd1,
 #define	FIX_NAK_1			(1 << 4)
 #define	FIX_NAK_2			(1 << 3)
@@ -429,6 +450,8 @@ enum rtl8168_8101_registers {
 #define	EFUSEAR_REG_MASK		0x03ff
 #define	EFUSEAR_REG_SHIFT		8
 #define	EFUSEAR_DATA_MASK		0xff
+	MISC_1			= 0xf2,
+#define	PFM_D3COLD_EN			(1 << 6)
 };
 
 enum rtl8168_registers {
@@ -447,6 +470,7 @@ enum rtl8168_registers {
 #define ERIAR_MASK_SHIFT		12
 #define ERIAR_MASK_0001			(0x1 << ERIAR_MASK_SHIFT)
 #define ERIAR_MASK_0011			(0x3 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_0100			(0x4 << ERIAR_MASK_SHIFT)
 #define ERIAR_MASK_0101			(0x5 << ERIAR_MASK_SHIFT)
 #define ERIAR_MASK_1111			(0xf << ERIAR_MASK_SHIFT)
 	EPHY_RXER_NUM		= 0x7c,
@@ -598,6 +622,9 @@ enum rtl_register_content {
 
 	/* DumpCounterCommand */
 	CounterDump	= 0x8,
+
+	/* magic enable v2 */
+	MagicPacket_v2	= (1 << 16),	/* Wake up when receives a Magic Packet */
 };
 
 enum rtl_desc_bit {
@@ -823,6 +850,8 @@ MODULE_FIRMWARE(FIRMWARE_8106E_1);
 MODULE_FIRMWARE(FIRMWARE_8106E_2);
 MODULE_FIRMWARE(FIRMWARE_8168G_2);
 MODULE_FIRMWARE(FIRMWARE_8168G_3);
+MODULE_FIRMWARE(FIRMWARE_8168H_1);
+MODULE_FIRMWARE(FIRMWARE_8168H_2);
 
 static void rtl_lock_work(struct rtl8169_private *tp)
 {
@@ -1514,8 +1543,17 @@ static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
 	options = RTL_R8(Config3);
 	if (options & LinkUp)
 		wolopts |= WAKE_PHY;
-	if (options & MagicPacket)
-		wolopts |= WAKE_MAGIC;
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+		if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
+			wolopts |= WAKE_MAGIC;
+		break;
+	default:
+		if (options & MagicPacket)
+			wolopts |= WAKE_MAGIC;
+		break;
+	}
 
 	options = RTL_R8(Config5);
 	if (options & UWF)
@@ -1543,24 +1581,48 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
-	unsigned int i;
+	unsigned int i, tmp;
 	static const struct {
 		u32 opt;
 		u16 reg;
 		u8  mask;
 	} cfg[] = {
 		{ WAKE_PHY,   Config3, LinkUp },
-		{ WAKE_MAGIC, Config3, MagicPacket },
 		{ WAKE_UCAST, Config5, UWF },
 		{ WAKE_BCAST, Config5, BWF },
 		{ WAKE_MCAST, Config5, MWF },
-		{ WAKE_ANY,   Config5, LanWake }
+		{ WAKE_ANY,   Config5, LanWake },
+		{ WAKE_MAGIC, Config3, MagicPacket }
 	};
 	u8 options;
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
 
-	for (i = 0; i < ARRAY_SIZE(cfg); i++) {
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+		tmp = ARRAY_SIZE(cfg) - 1;
+		if (wolopts & WAKE_MAGIC)
+			rtl_w1w0_eri(tp,
+				     0x0dc,
+				     ERIAR_MASK_0100,
+				     MagicPacket_v2,
+				     0x0000,
+				     ERIAR_EXGMAC);
+		else
+			rtl_w1w0_eri(tp,
+				     0x0dc,
+				     ERIAR_MASK_0100,
+				     0x0000,
+				     MagicPacket_v2,
+				     ERIAR_EXGMAC);
+		break;
+	default:
+		tmp = ARRAY_SIZE(cfg);
+		break;
+	}
+
+	for (i = 0; i < tmp; i++) {
 		options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
 		if (wolopts & cfg[i].opt)
 			options |= cfg[i].mask;
@@ -2044,6 +2106,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		u32 val;
 		int mac_version;
 	} mac_info[] = {
+		/* 8168H family. */
+		{ 0x7cf00000, 0x54100000,	RTL_GIGA_MAC_VER_46 },
+		{ 0x7cf00000, 0x54000000,	RTL_GIGA_MAC_VER_45 },
+
 		/* 8168G family. */
 		{ 0x7cf00000, 0x5c800000,	RTL_GIGA_MAC_VER_44 },
 		{ 0x7cf00000, 0x50900000,	RTL_GIGA_MAC_VER_42 },
@@ -2139,6 +2205,14 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		tp->mac_version = tp->mii.supports_gmii ?
 				  RTL_GIGA_MAC_VER_42 :
 				  RTL_GIGA_MAC_VER_43;
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_45) {
+		tp->mac_version = tp->mii.supports_gmii ?
+				  RTL_GIGA_MAC_VER_45 :
+				  RTL_GIGA_MAC_VER_47;
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_46) {
+		tp->mac_version = tp->mii.supports_gmii ?
+				  RTL_GIGA_MAC_VER_46 :
+				  RTL_GIGA_MAC_VER_48;
 	}
 }
 
@@ -3464,6 +3538,189 @@ static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp)
 	rtl_apply_firmware(tp);
 }
 
+static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
+{
+	u16 dout_tapbin;
+	u32 data;
+
+	rtl_apply_firmware(tp);
+
+	/* CHN EST parameters adjust - giga master */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x809b);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0xf800);
+	rtl_writephy(tp, 0x13, 0x80a2);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0xff00);
+	rtl_writephy(tp, 0x13, 0x80a4);
+	rtl_w1w0_phy(tp, 0x14, 0x8500, 0xff00);
+	rtl_writephy(tp, 0x13, 0x809c);
+	rtl_w1w0_phy(tp, 0x14, 0xbd00, 0xff00);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* CHN EST parameters adjust - giga slave */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x80ad);
+	rtl_w1w0_phy(tp, 0x14, 0x7000, 0xf800);
+	rtl_writephy(tp, 0x13, 0x80b4);
+	rtl_w1w0_phy(tp, 0x14, 0x5000, 0xff00);
+	rtl_writephy(tp, 0x13, 0x80ac);
+	rtl_w1w0_phy(tp, 0x14, 0x4000, 0xff00);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* CHN EST parameters adjust - fnet */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x808e);
+	rtl_w1w0_phy(tp, 0x14, 0x1200, 0xff00);
+	rtl_writephy(tp, 0x13, 0x8090);
+	rtl_w1w0_phy(tp, 0x14, 0xe500, 0xff00);
+	rtl_writephy(tp, 0x13, 0x8092);
+	rtl_w1w0_phy(tp, 0x14, 0x9f00, 0xff00);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* enable R-tune & PGA-retune function */
+	dout_tapbin = 0;
+	rtl_writephy(tp, 0x1f, 0x0a46);
+	data = rtl_readphy(tp, 0x13);
+	data &= 3;
+	data <<= 2;
+	dout_tapbin |= data;
+	data = rtl_readphy(tp, 0x12);
+	data &= 0xc000;
+	data >>= 14;
+	dout_tapbin |= data;
+	dout_tapbin = ~(dout_tapbin^0x08);
+	dout_tapbin <<= 12;
+	dout_tapbin &= 0xf000;
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x827a);
+	rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
+	rtl_writephy(tp, 0x13, 0x827b);
+	rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
+	rtl_writephy(tp, 0x13, 0x827c);
+	rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
+	rtl_writephy(tp, 0x13, 0x827d);
+	rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
+
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x0811);
+	rtl_w1w0_phy(tp, 0x14, 0x0800, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0a42);
+	rtl_w1w0_phy(tp, 0x16, 0x0002, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* enable GPHY 10M */
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w1w0_phy(tp, 0x11, 0x0800, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* SAR ADC performance */
+	rtl_writephy(tp, 0x1f, 0x0bca);
+	rtl_w1w0_phy(tp, 0x17, 0x4000, 0x3000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x803f);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x13, 0x8047);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x13, 0x804f);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x13, 0x8057);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x13, 0x805f);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x13, 0x8067);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x13, 0x806f);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* disable phy pfm mode */
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x0080);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Check ALDPS bit, disable it if enabled */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	if (rtl_readphy(tp, 0x10) & 0x0004)
+		rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
+{
+	u16 ioffset_p3, ioffset_p2, ioffset_p1, ioffset_p0;
+	u16 rlen;
+	u32 data;
+
+	rtl_apply_firmware(tp);
+
+	/* CHIN EST parameter update */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x808a);
+	rtl_w1w0_phy(tp, 0x14, 0x000a, 0x003f);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* enable R-tune & PGA-retune function */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x0811);
+	rtl_w1w0_phy(tp, 0x14, 0x0800, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0a42);
+	rtl_w1w0_phy(tp, 0x16, 0x0002, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* enable GPHY 10M */
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w1w0_phy(tp, 0x11, 0x0800, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	r8168_mac_ocp_write(tp, 0xdd02, 0x807d);
+	data = r8168_mac_ocp_read(tp, 0xdd02);
+	ioffset_p3 = ((data & 0x80)>>7);
+	ioffset_p3 <<= 3;
+
+	data = r8168_mac_ocp_read(tp, 0xdd00);
+	ioffset_p3 |= ((data & (0xe000))>>13);
+	ioffset_p2 = ((data & (0x1e00))>>9);
+	ioffset_p1 = ((data & (0x01e0))>>5);
+	ioffset_p0 = ((data & 0x0010)>>4);
+	ioffset_p0 <<= 3;
+	ioffset_p0 |= (data & (0x07));
+	data = (ioffset_p3<<12)|(ioffset_p2<<8)|(ioffset_p1<<4)|(ioffset_p0);
+
+	if ((ioffset_p3 != 0x0F) || (ioffset_p2 != 0x0F) ||
+	    (ioffset_p1 != 0x0F) || (ioffset_p0 == 0x0F)) {
+		rtl_writephy(tp, 0x1f, 0x0bcf);
+		rtl_writephy(tp, 0x16, data);
+		rtl_writephy(tp, 0x1f, 0x0000);
+	}
+
+	/* Modify rlen (TX LPF corner frequency) level */
+	rtl_writephy(tp, 0x1f, 0x0bcd);
+	data = rtl_readphy(tp, 0x16);
+	data &= 0x000f;
+	rlen = 0;
+	if (data > 3)
+		rlen = data - 3;
+	data = rlen | (rlen<<4) | (rlen<<8) | (rlen<<12);
+	rtl_writephy(tp, 0x17, data);
+	rtl_writephy(tp, 0x1f, 0x0bcd);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* disable phy pfm mode */
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w1w0_phy(tp, 0x14, 0x0000, 0x0080);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Check ALDPS bit, disable it if enabled */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	if (rtl_readphy(tp, 0x10) & 0x0004)
+		rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
 static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -3654,6 +3911,14 @@ static void rtl_hw_phy_config(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_44:
 		rtl8168g_2_hw_phy_config(tp);
 		break;
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_47:
+		rtl8168h_1_hw_phy_config(tp);
+		break;
+	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_48:
+		rtl8168h_2_hw_phy_config(tp);
+		break;
 
 	case RTL_GIGA_MAC_VER_41:
 	default:
@@ -3865,6 +4130,10 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_42:
 	case RTL_GIGA_MAC_VER_43:
 	case RTL_GIGA_MAC_VER_44:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
 		ops->write	= r8168g_mdio_write;
 		ops->read	= r8168g_mdio_read;
 		break;
@@ -3919,6 +4188,10 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_42:
 	case RTL_GIGA_MAC_VER_43:
 	case RTL_GIGA_MAC_VER_44:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
 		RTL_W32(RxConfig, RTL_R32(RxConfig) |
 			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
 		break;
@@ -3987,6 +4260,10 @@ static void r810x_pll_power_up(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_13:
 	case RTL_GIGA_MAC_VER_16:
 		break;
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
+		RTL_W8(PMCH, RTL_R8(PMCH) | 0xC0);
+		break;
 	default:
 		RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
 		break;
@@ -4087,6 +4364,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_31:
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
 		RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
 		break;
 	case RTL_GIGA_MAC_VER_40:
@@ -4111,6 +4390,10 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_33:
 		RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
 		break;
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+		RTL_W8(PMCH, RTL_R8(PMCH) | 0xC0);
+		break;
 	case RTL_GIGA_MAC_VER_40:
 	case RTL_GIGA_MAC_VER_41:
 		rtl_w1w0_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000,
@@ -4153,6 +4436,8 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_37:
 	case RTL_GIGA_MAC_VER_39:
 	case RTL_GIGA_MAC_VER_43:
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
 		ops->down	= r810x_pll_power_down;
 		ops->up		= r810x_pll_power_up;
 		break;
@@ -4182,6 +4467,8 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_41:
 	case RTL_GIGA_MAC_VER_42:
 	case RTL_GIGA_MAC_VER_44:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
 		ops->down	= r8168_pll_power_down;
 		ops->up		= r8168_pll_power_up;
 		break;
@@ -4232,6 +4519,10 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_42:
 	case RTL_GIGA_MAC_VER_43:
 	case RTL_GIGA_MAC_VER_44:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
 		RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
 		break;
 	default:
@@ -4393,6 +4684,10 @@ static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_42:
 	case RTL_GIGA_MAC_VER_43:
 	case RTL_GIGA_MAC_VER_44:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
 	default:
 		ops->disable	= NULL;
 		ops->enable	= NULL;
@@ -4495,15 +4790,19 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
 	    tp->mac_version == RTL_GIGA_MAC_VER_31) {
 		rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
 	} else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_35 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_36 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_37 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_40 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_41 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_42 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_43 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_44 ||
-	           tp->mac_version == RTL_GIGA_MAC_VER_38) {
+		   tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_36 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_37 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_38 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_40 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_41 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_42 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_43 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_44 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_45 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_46 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_47 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_48) {
 		RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
 		rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
 	} else {
@@ -5330,6 +5629,105 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
 	rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2));
 }
 
+static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+	u16 rg_saw_cnt;
+	u32 data;
+	static const struct ephy_info e_info_8168h_1[] = {
+		{ 0x1e, 0x0800,	0x0001 },
+		{ 0x1d, 0x0000,	0x0800 },
+		{ 0x05, 0xffff,	0x2089 },
+		{ 0x06, 0xffff,	0x5881 },
+		{ 0x04, 0xffff,	0x154a },
+		{ 0x01, 0xffff,	0x068b }
+	};
+
+	/* disable aspm and clock request before access ephy */
+	RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+	RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+	rtl_ephy_init(tp, e_info_8168h_1, ARRAY_SIZE(e_info_8168h_1));
+
+	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+
+	rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x00080002, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+
+	rtl_csi_access_enable_1(tp);
+
+	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+	rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+	rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+
+	rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_1111, 0x0010, 0x00, ERIAR_EXGMAC);
+
+	rtl_w1w0_eri(tp, 0xd4, ERIAR_MASK_1111, 0x1f00, 0x00, ERIAR_EXGMAC);
+
+	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87, ERIAR_EXGMAC);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+	RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
+	RTL_W8(MaxTxPacketSize, EarlySize);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+	/* Adjust EEE LED frequency */
+	RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
+	RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) & ~TX_10M_PS_EN);
+
+	rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
+
+	rtl_pcie_state_l2l3_enable(tp, false);
+
+	rtl_writephy(tp, 0x1f, 0x0c42);
+	rg_saw_cnt = rtl_readphy(tp, 0x13);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	if (rg_saw_cnt > 0) {
+		u16 sw_cnt_1ms_ini;
+
+		sw_cnt_1ms_ini = 16000000/rg_saw_cnt;
+		sw_cnt_1ms_ini &= 0x0fff;
+		data = r8168_mac_ocp_read(tp, 0xd412);
+		data &= 0x0fff;
+		data |= sw_cnt_1ms_ini;
+		r8168_mac_ocp_write(tp, 0xd412, data);
+	}
+
+	data = r8168_mac_ocp_read(tp, 0xe056);
+	data &= 0xf0;
+	data |= 0x07;
+	r8168_mac_ocp_write(tp, 0xe056, data);
+
+	data = r8168_mac_ocp_read(tp, 0xe052);
+	data &= 0x8008;
+	data |= 0x6000;
+	r8168_mac_ocp_write(tp, 0xe052, data);
+
+	data = r8168_mac_ocp_read(tp, 0xe0d6);
+	data &= 0x01ff;
+	data |= 0x017f;
+	r8168_mac_ocp_write(tp, 0xe0d6, data);
+
+	data = r8168_mac_ocp_read(tp, 0xd420);
+	data &= 0x0fff;
+	data |= 0x047f;
+	r8168_mac_ocp_write(tp, 0xd420, data);
+
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
+}
+
 static void rtl_hw_start_8168(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -5440,6 +5838,11 @@ static void rtl_hw_start_8168(struct net_device *dev)
 		rtl_hw_start_8411_2(tp);
 		break;
 
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+		rtl_hw_start_8168h_1(tp);
+		break;
+
 	default:
 		printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
 			dev->name, tp->mac_version);
@@ -5655,6 +6058,10 @@ static void rtl_hw_start_8101(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_43:
 		rtl_hw_start_8168g_2(tp);
 		break;
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
+		rtl_hw_start_8168h_1(tp);
+		break;
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -5895,7 +6302,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
 {
 	struct skb_shared_info *info = skb_shinfo(skb);
 	unsigned int cur_frag, entry;
-	struct TxDesc * uninitialized_var(txd);
+	struct TxDesc *uninitialized_var(txd);
 	struct device *d = &tp->pci_dev->dev;
 
 	entry = tp->cur_tx;
@@ -7110,6 +7517,10 @@ static void rtl_hw_initialize(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_42:
 	case RTL_GIGA_MAC_VER_43:
 	case RTL_GIGA_MAC_VER_44:
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_47:
+	case RTL_GIGA_MAC_VER_48:
 		rtl_hw_init_8168g(tp);
 		break;
 
@@ -7255,8 +7666,19 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
 	RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
 	RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
-	if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
-		tp->features |= RTL_FEATURE_WOL;
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_45:
+	case RTL_GIGA_MAC_VER_46:
+		if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
+			tp->features |= RTL_FEATURE_WOL;
+		if ((RTL_R8(Config3) & LinkUp) != 0)
+			tp->features |= RTL_FEATURE_WOL;
+		break;
+	default:
+		if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
+			tp->features |= RTL_FEATURE_WOL;
+		break;
+	}
 	if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
 		tp->features |= RTL_FEATURE_WOL;
 	tp->features |= rtl_try_msi(tp, cfg);
@@ -7283,6 +7705,18 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	u64_stats_init(&tp->tx_stats.syncp);
 
 	/* Get MAC address */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_45 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_46 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_47 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_48) {
+		u16 mac_addr[3];
+
+		*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xE0, ERIAR_EXGMAC);
+		*(u16 *)&mac_addr[2] = rtl_eri_read(tp, 0xE4, ERIAR_EXGMAC);
+
+		if (is_valid_ether_addr((u8 *)mac_addr))
+			rtl_rar_set(tp, (u8 *)mac_addr);
+	}
 	for (i = 0; i < ETH_ALEN; i++)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);
 
-- 
1.8.3.2

^ permalink raw reply related

* Re: [PATCH v2] drivers: net: ethernet: intel: e1000: e1000_ethertoo.c coding style fixes
From: Krzysztof Majzerowicz-Jaszcz @ 2014-08-19 17:33 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: Joe Perches, Alexander Duyck, netdev, LKML
In-Reply-To: <CAL3LdT7+5FFbP5Rf1MoY2GJ9cQ0LJnecQb66ZA2ofwD28vy1jw@mail.gmail.com>

On 19/08/14 18:04, Jeff Kirsher wrote:
> On Mon, Aug 18, 2014 at 3:21 PM, Krzysztof Majzerowicz-Jaszcz
> <cristos@vipserv.org> wrote:
>> Fixed many errors/warnings and checks in e1000_ethtool.c reported by checkpatch.pl
>> Suggestions from Joe Perches and Alexander Duyck applied as well
>>
>> Signed-off-by: Krzysztof Majzerowicz-Jaszcz <cristos@vipserv.org>
>> ---
>>  drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 155 ++++++++++++-----------
>>  1 file changed, 79 insertions(+), 76 deletions(-)
>>
> 
> Thanks Krzysztof, I will add your patch to my queue and I can fix up
> the patch title for you. :-)
>

Thank you :). Sorry for that patch title - I guess that 'first pancake is always spoiled'.
Nonetheless, that makes my first successful contribution to the kernel <yay> ;)

^ permalink raw reply

* tulip hangs under load on sparc64
From: Meelis Roos @ 2014-08-19 16:12 UTC (permalink / raw)
  To: Grant Grundler, netdev, sparclinux

This is not a new problem, I have a note about it from a couple of years 
ago. Now while trying to stress test all my sparc64 test computers I 
found and reproduced it again.

Basically, tulip driver driving onboard davicom ethernet in Sun Netra X1 
suffers a hang under load. Load can be generated with scp from 
fast enough machine so that the Sun becomes a bottleneck.

I remember there was a choice of tulip and dmfe drivers when first 
setting up the box, and for some reason the tulip driver was better on 
sparc64.

00:05.0 Ethernet controller: Davicom Semiconductor, Inc. 21x4x DEC-Tulip compatible 10/100 Ethernet (rev 31)
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0 (5000ns min, 10000ns max)
        Interrupt: pin A routed to IRQ 10
        Region 0: I/O ports at 10100 [size=256]
        Region 1: Memory at 00002000 (32-bit, non-prefetchable) [size=8K]
        Region 2: [virtual] Memory at fffffe0100000000 (32-bit, non-prefetchable)
        Region 3: [virtual] Memory at fffffe0100000000 (32-bit, non-prefetchable)
        Region 4: [virtual] Memory at fffffe0100000000 (32-bit, non-prefetchable)
        Region 5: [virtual] Memory at fffffe0100000000 (32-bit, non-prefetchable)
        Expansion ROM at 00080000 [disabled] [size=256K]
        Capabilities: [50] Power Management version 2
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=220mA PME(D0-,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Kernel driver in use: tulip


[   77.953022] Linux Tulip driver version 1.1.15-NAPI (Feb 27, 2007)
[   78.035851] tulip0: Old style EEPROM with no media selection information
[   78.124147] tulip0:  MII transceiver #1 config 1000 status 782d advertising 01e1
[   78.224765] net eth0: Davicom DM9102/DM9102A rev 49 at MMIO 0x1ff00000000, EEPROM not present, 00:03:ba:0c:06:cd, IRQ 9
[   78.369474] tulip1: Old style EEPROM with no media selection information
[   78.457785] tulip1:  MII transceiver #1 config 1000 status 7809 advertising 01e1
[   78.558377] net eth1: Davicom DM9102/DM9102A rev 49 at MMIO 0x1ff00002000, EEPROM not present, 00:03:ba:0c:06:ce, IRQ 10

[...]

[35790.526119] ------------[ cut here ]------------
[35790.586790] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:264 dev_watchdog+0x278/0x2a0()
[35790.697744] NETDEV WATCHDOG: eth0 (tulip): transmit queue 0 timed out
[35790.782400] Modules linked in: ipv6 loop ohci_pci ohci_hcd i2c_ali15x3 i2c_ali1535 sg i2ccore usbcore usb_common
[35790.916222] CPU: 0 PID: 0 Comm: swapper Not tainted 3.17.0-rc1 #131
[35790.998621] Call Trace:
[35791.030744]  [0000000000455dcc] warn_slowpath_fmt+0x2c/0x40
[35791.103989]  [0000000000708f98] dev_watchdog+0x278/0x2a0
[35791.173816]  [000000000048d1e8] call_timer_fn.isra.40+0x8/0x80
[35791.250496]  [000000000048d400] run_timer_softirq+0x1a0/0x260
[35791.326037]  [00000000004588dc] __do_softirq+0xbc/0x1e0
[35791.394724]  [000000000042b980] do_softirq_own_stack+0x20/0x40
[35791.471401]  [0000000000458bac] irq_exit+0x8c/0xa0
[35791.534373]  [000000000042f798] timer_interrupt+0x58/0xa0
[35791.605338]  [00000000004209d4] tl0_irq14+0x14/0x20
[35791.669445]  [000000000042c000] arch_cpu_idle+0x60/0x80
[35791.738137]  [0000000000478994] cpu_startup_entry+0x114/0x180
[35791.813674]  [0000000000930970] start_kernel+0x394/0x3a4
[35791.883503]  [000000000078af6c] tlb_fixup_done+0x80/0x94
[35791.953313]  [0000000000000000]           (null)
[35792.013993] ---[ end trace ab470f2a0234b1ed ]---

-- 
Meelis Roos (mroos@linux.ee)

^ permalink raw reply

* Re: [PATCH v2] drivers: net: ethernet: intel: e1000: e1000_ethertoo.c coding style fixes
From: Jeff Kirsher @ 2014-08-19 16:04 UTC (permalink / raw)
  To: Krzysztof Majzerowicz-Jaszcz; +Cc: Joe Perches, Alexander Duyck, netdev, LKML
In-Reply-To: <1408393263-18027-1-git-send-email-cristos@vipserv.org>

On Mon, Aug 18, 2014 at 3:21 PM, Krzysztof Majzerowicz-Jaszcz
<cristos@vipserv.org> wrote:
> Fixed many errors/warnings and checks in e1000_ethtool.c reported by checkpatch.pl
> Suggestions from Joe Perches and Alexander Duyck applied as well
>
> Signed-off-by: Krzysztof Majzerowicz-Jaszcz <cristos@vipserv.org>
> ---
>  drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 155 ++++++++++++-----------
>  1 file changed, 79 insertions(+), 76 deletions(-)
>

Thanks Krzysztof, I will add your patch to my queue and I can fix up
the patch title for you. :-)

^ permalink raw reply

* Re: 3.17-rc1 oops during network interface configuration
From: Chuck Lever @ 2014-08-19 14:56 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: netdev, linux-rdma
In-Reply-To: <53F1EF18.7010909@acm.org>


On Aug 18, 2014, at 8:18 AM, Bart Van Assche <bvanassche@acm.org> wrote:

> Hello,
> 
> Has anyone else already tried to boot kernel 3.17-rc1 on an IB system ?

After updating to 3.17-rc1 this morning, I hit the same issue.

> The
> following call trace is triggered during boot on a system on which kernel
> 3.16 runs fine:
> 
> BUG: unable to handle kernel paging request at ffff88090000007e
> IP: __dev_queue_xmit+0x519
> Call Trace:
> ? __dev_queue_xmit+0x49
> dev_queue_xmit+0x10
> neigh_connected_output
> ? ip_finish_output
> ip_finish_output
> ? ip_finish_output
> ? netif_rx_ni
> ip_mc_output
> ip_local_out_sk
> ip_send_skb
> udp_send_skb
> udp_sendmsg
> ? ip_reply_glue_bits
> ? __lock_is_held
> inet_sendmsg
> ? inet_sendmsg
> sock_sendmsg
> ? might_fault
> ? might_fault
> ? move_addr_to_kernel.part.38
> SYSC_sendto
> ? sysret_check
> ? trace_hardirqs_on_caller
> ? trace_hardirqs_on_thunk
> SyS_sendto
> system_call_fastpath
> 
> Kernel panic - not syncing: Fatal exception in interrupt
> Kernel Offset: 0x0 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffff9fffffff)
> drm_kms_helper: panic occurred, switching back to text console
> 
> A screenshot of this kernel oops can be found here:
> https://drive.google.com/file/d/0B1YQOreL3_FxVDB5UTNwekF6LVU/
> 
> gdb translates the crash address into the following (not sure this makes sense
> since offset 0x519 is past the end of __dev_queue_xmit()):
> 
> (gdb) list *(__dev_queue_xmit+0x519) 
> 0xffffffff8136bc89 is in netdev_adjacent_rename_links (net/core/dev.c:5167).
> 5162    void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
> 5163    {
> 5164            struct netdev_adjacent *iter;
> 5165
> 5166            list_for_each_entry(iter, &dev->adj_list.upper, list) {
> 5167                    netdev_adjacent_sysfs_del(iter->dev, oldname,
> 5168                                              &iter->dev->adj_list.lower);
> 5169                    netdev_adjacent_sysfs_add(iter->dev, dev,
> 5170                                              &iter->dev->adj_list.lower);
> 5171            }
> 
> And the address __dev_queue_xmit+0x49 is translated by gdb into:
> 
> (gdb) list *(__dev_queue_xmit+0x49)
> 0xffffffff8136b7b9 is in __dev_queue_xmit (./arch/x86/include/asm/preempt.h:75).
> 70       * The various preempt_count add/sub methods
> 71       */
> 72
> 73      static __always_inline void __preempt_count_add(int val)
> 74      {
> 75              raw_cpu_add_4(__preempt_count, val);
> 76      }
> 77
> 78      static __always_inline void __preempt_count_sub(int val)
> 79      {
> 
> Bart.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

^ permalink raw reply

* [PATCH v4 2/2] net: moxa: replace build_skb() with netdev_alloc_skb_ip_align() / memcpy()
From: Jonas Jensen @ 2014-08-19 14:49 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-arm-kernel, linux-kernel, f.fainelli, bhutchings,
	Jonas Jensen
In-Reply-To: <1408459784-9385-1-git-send-email-jonas.jensen@gmail.com>

build_skb() is used to make skbs out of existing RX ring memory
which is bad because the RX ring is allocated only once, on probe.
Memory corruption occur because said memory is reclaimed, i.e.
__kfree_skb() (and eventually put_page()).

Replace build_skb() with netdev_alloc_skb_ip_align() and use memcpy().
Also, synchronize DMA memory before passing skb to napi_gro_receive().

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=69041

Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com>
---

Notes:
    The original motivation was to avoid memcpy(), since the memory is
    already allocated, why make a copy.
    
    Maybe the copy can be avoided updating RX ring descriptor addresses;
    new memory must be allocated just the same, the only difference that
    the controller could write directly to it.
    
    This fixes errors due to memory corruption, such as the following,
    seen on wget download (or ncftp):
    
    "read error: Bad address"
    
    On receiving error, wget exits without resuming (busybox default).
    
    Changes since v3:
    
    1. commit message reworded
    
    Applies to next-20140818

 drivers/net/ethernet/moxa/moxart_ether.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index aa45607..17c9f0e 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -226,14 +226,21 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
 		if (len > RX_BUF_SIZE)
 			len = RX_BUF_SIZE;
 
-		skb = build_skb(priv->rx_buf[rx_head], priv->rx_buf_size);
+		dma_sync_single_for_cpu(&ndev->dev,
+					priv->rx_mapping[rx_head],
+					priv->rx_buf_size, DMA_FROM_DEVICE);
+		skb = netdev_alloc_skb_ip_align(ndev, len);
 		if (unlikely(!skb)) {
-			net_dbg_ratelimited("build_skb failed\n");
+			net_dbg_ratelimited("netdev_alloc_skb_ip_align failed\n");
 			priv->stats.rx_dropped++;
 			priv->stats.rx_errors++;
 		}
-
+		memcpy(skb->data, priv->rx_buf[rx_head], len);
 		skb_put(skb, len);
+		dma_sync_single_for_device(&ndev->dev,
+					   priv->rx_mapping[rx_head],
+					   priv->rx_buf_size, DMA_FROM_DEVICE);
+
 		skb->protocol = eth_type_trans(skb, ndev);
 		napi_gro_receive(&priv->napi, skb);
 		rx++;
-- 
1.8.2.1

^ permalink raw reply related

* [PATCH v4 1/2] net: moxa: clear TX descriptor length bits
From: Jonas Jensen @ 2014-08-19 14:49 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-arm-kernel, linux-kernel, f.fainelli, bhutchings,
	Jonas Jensen

TX buffer length is not cleared on ndo_start_xmit().
Failing to do so can bug/hang the controller and
cause TX interrupts to stop altogether.

Add TX_DESC1_BUF_SIZE_MASK to bits that are cleared,
before the TX buffer length is set.

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=69031

Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com>
---

Notes:
    Changes since v3:
    
    1. commit message reworded
    
    Applies to next-20140818

 drivers/net/ethernet/moxa/moxart_ether.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 5020fd4..aa45607 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -348,7 +348,8 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	txdes1 = readl(desc + TX_REG_OFFSET_DESC1);
 	txdes1 |= TX_DESC1_LTS | TX_DESC1_FTS;
-	txdes1 &= ~(TX_DESC1_FIFO_COMPLETE | TX_DESC1_INTR_COMPLETE);
+	txdes1 &= ~(TX_DESC1_FIFO_COMPLETE | TX_DESC1_INTR_COMPLETE |
+		    TX_DESC1_BUF_SIZE_MASK);
 	txdes1 |= (len & TX_DESC1_BUF_SIZE_MASK);
 	writel(txdes1, desc + TX_REG_OFFSET_DESC1);
 	writel(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0);
-- 
1.8.2.1

^ permalink raw reply related

* For Partnership
From: MADAM SAFIA HASSAN @ 2014-08-19  0:08 UTC (permalink / raw)




I am from syria mother of two kids I have a proposal to present to you for the benefit of both of us kindly reply me back for details. kindly 
reply for more details
hsafia11@outlook.com

^ permalink raw reply

* [patch net-next] bonding: create netlink event when bonding option is changed
From: Jiri Pirko @ 2014-08-19 14:02 UTC (permalink / raw)
  To: netdev; +Cc: davem, j.vosburgh, vfalico, andy, nikolay, dingtianhong, sfeldma

Userspace needs to be notified if one changes some option.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/bonding/bond_options.c | 2 ++
 include/linux/netdevice.h          | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index dc73463..d8dc17f 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -625,6 +625,8 @@ int __bond_opt_set(struct bonding *bond,
 out:
 	if (ret)
 		bond_opt_error_interpret(bond, opt, ret, val);
+	else
+		call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
 
 	return ret;
 }
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 967ddcc..44bc4bd 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2017,6 +2017,7 @@ struct pcpu_sw_netstats {
 #define NETDEV_CHANGEUPPER	0x0015
 #define NETDEV_RESEND_IGMP	0x0016
 #define NETDEV_PRECHANGEMTU	0x0017 /* notify before mtu change happened */
+#define NETDEV_CHANGEINFODATA	0x0018
 
 int register_netdevice_notifier(struct notifier_block *nb);
 int unregister_netdevice_notifier(struct notifier_block *nb);
-- 
1.9.3

^ permalink raw reply related


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