* Re: [PATCH v2] net-tcp: TCP/IP stack bypass for loopback connections
From: Jan Engelhardt @ 2012-09-09 17:54 UTC (permalink / raw)
To: Eric Dumazet
Cc: Pádraig Brady, Bruce "Brutus" Curtis,
David S. Miller, Eric Dumazet, netdev
In-Reply-To: <1345722015.5904.675.camel@edumazet-glaptop>
On Thursday 2012-08-23 13:40, Eric Dumazet wrote:
>On Thu, 2012-08-23 at 11:57 +0100, Pádraig Brady wrote:
>
>> Just to quantify the loopback testing compat issue.
>> I often do stuff like the following to test latency.
>> Will that be impacted?
>>
>> tc qdisc add dev lo root handle 1:0 netem delay 20msec
>>
>
>Yes this will. At least for tcp traffic this wont "work".
>
>TCP friends bypass layers, by directly queuing skbs to sockets.
>
>-> no iptables,
If it amounts to that, you will have upset users rather soon.
^ permalink raw reply
* Re: [PATCH] configure: Add search path for 64bit library.
From: Jan Engelhardt @ 2012-09-09 19:42 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Ben Hutchings, Li Wei, netdev
In-Reply-To: <20120813093323.1506aa83@nehalam.linuxnetplumber.net>
On Monday 2012-08-13 18:33, Stephen Hemminger wrote:
>> > > > IPT_LIB_DIR=""
>> > > > - for dir in /lib /usr/lib /usr/local/lib
>> > > > + for dir in /lib /usr/lib /usr/local/lib /lib64 /usr/lib64 /usr/local/lib64
>> > > > do
>> > > > for file in $dir/{xtables,iptables}/lib*t_*so ; do
>> > > > if [ -f $file ]; then
>> > >
>> > > I think this should be done with pkg-config:
>> > >
>> > > pkg-config --variable=xtlibdir xtables
>> >
>> > Does every distro have pkg-config or does more logic need to be done here?
>>
>> Every distro has pkg-config; the question is whether you want to support
>> library versions that don't include a pkg-config file (xtables.pc), if
>> they exist.
>
>Let's do pkg-config first, and as a fallback keep the old code and only
>look in the same old places.
Every distro that has libxtables.so also has the .pc file.
The obvious reason to have the .pc file is to render such error
prone static path searching redundant.
^ permalink raw reply
* Re: [PATCH v2] net-tcp: TCP/IP stack bypass for loopback connections
From: David Miller @ 2012-09-09 21:39 UTC (permalink / raw)
To: jengelh; +Cc: eric.dumazet, P, brutus, edumazet, netdev
In-Reply-To: <alpine.LNX.2.01.1209091954120.15847@frira.zrqbmnf.qr>
From: Jan Engelhardt <jengelh@inai.de>
Date: Sun, 9 Sep 2012 19:54:42 +0200 (CEST)
>
> On Thursday 2012-08-23 13:40, Eric Dumazet wrote:
>>On Thu, 2012-08-23 at 11:57 +0100, Pádraig Brady wrote:
>>
>>> Just to quantify the loopback testing compat issue.
>>> I often do stuff like the following to test latency.
>>> Will that be impacted?
>>>
>>> tc qdisc add dev lo root handle 1:0 netem delay 20msec
>>>
>>
>>Yes this will. At least for tcp traffic this wont "work".
>>
>>TCP friends bypass layers, by directly queuing skbs to sockets.
>>
>>-> no iptables,
>
> If it amounts to that, you will have upset users rather soon.
This is over "loopback", you're just being rediculous. %99.9999 of
people simply do not care.
^ permalink raw reply
* Re: netlink: hide struct module parameter in netlink_kernel_create
From: Stephen Rothwell @ 2012-09-09 23:37 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: David S. Miller, netdev
[-- Attachment #1: Type: text/plain, Size: 322 bytes --]
Hi all,
I didn't see the original patch until it reached linux-enxt this morning,
but just a comment:
THIS_MODULE is defined in linux/export.h, so that should be included in
linux/netlink.h instead of linux/module.h as it is much smaller.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH net-next] r8169: use unlimited DMA burst for TX
From: Michal Schmidt @ 2012-09-09 23:55 UTC (permalink / raw)
To: netdev
Cc: Francois Romieu, Hayes Wang, Realtek linux nic maintainers,
Ivan Vecera
The r8169 driver currently limits the DMA burst for TX to 1024 bytes. I have
a box where this prevents the interface from using the gigabit line to its full
potential. This patch solves the problem by setting TX_DMA_BURST to unlimited.
The box has an ASRock B75M motherboard with on-board RTL8168evl/8111evl
(XID 0c900880). TSO is enabled.
I used netperf (TCP_STREAM test) to measure the dependency of TX throughput
on MTU. I did it for three different values of TX_DMA_BURST ('5'=512, '6'=1024,
'7'=unlimited). This chart shows the results:
http://michich.fedorapeople.org/r8169/r8169-effects-of-TX_DMA_BURST.png
Interesting points:
- With the current DMA burst limit (1024):
- at the default MTU=1500 I get only 842 Mbit/s.
- when going from small MTU, the performance rises monotonically with
increasing MTU only up to a peak at MTU=1076 (908 MBit/s). Then there's
a sudden drop to 762 MBit/s from which the throughput rises monotonically
again with further MTU increases.
- With a smaller DMA burst limit (512):
- there's a similar peak at MTU=1076 and another one at MTU=564.
- With unlimited DMA burst:
- at the default MTU=1500 I get nice 940 Mbit/s.
- the throughput rises monotonically with increasing MTU with no strange
peaks.
Notice that the peaks occur at MTU sizes that are multiples of the DMA burst
limit plus 52. Why 52? Because:
20 (IP header) + 20 (TCP header) + 12 (TCP options) = 52
The Realtek-provided r8168 driver (v8.032.00) uses unlimited TX DMA burst too,
except for CFG_METHOD_1 where the TX DMA burst is set to 512 bytes.
CFG_METHOD_1 appears to be the oldest MAC version of "RTL8168B/8111B",
i.e. RTL_GIGA_MAC_VER_11 in r8169. Not sure if this MAC version really needs
the smaller burst limit, or if any other versions have similar requirements.
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
drivers/net/ethernet/realtek/r8169.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index b47d5b3..549314f 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -77,7 +77,7 @@
static const int multicast_filter_limit = 32;
#define MAX_READ_REQUEST_SHIFT 12
-#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
+#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
--
1.7.1
^ permalink raw reply related
* RFC: mac802154 Packet Queueing and Slave Devices
From: Alan Ott @ 2012-09-10 0:43 UTC (permalink / raw)
To: Alexander Smirnov, Dmitry Eremin-Solenikov, slapin, Tony Cheneau
Cc: linux-zigbee-devel, netdev
Hi,
Tony and I were recently talking about packet queueing on 802.15.4. What
currently happens (in net/mac802154/tx.c) is that each tx packet (skb)
is stuck on a work queue, and the worker function then sends each packet
to the hardware driver in order.
The problem with this is that it defeats the netif flow control. The
networking layer thinks the packet is sent as soon as it's put on the
workqueue (because the function that queues it returns NETDEV_TX_OK to
the networking layer), and the workqueue can then get arbitrarily large
if an application tries to send a lot of data. (Tony has shown this with
iperf)
The way the 802.15.4 drivers are currently written, their xmit function
blocks until the hardware confirms the packet has been sent. Any
hardware queueing is either not done (at86rf230 and mrf24j40 (and other
non-mainline (yet) drivers)[1]), or is done completely in the firmware
side (as in serial.c (for Econotag), not in mainline yet).
Solution 1:
If we want to keep the driver interface this way (no queueing on the
driver side and each driver's .xmit() function blocks), then we should
call netif_stop_queue()/netif_wake_queue() on the mac802154-subsystem
side[2].
Solution 2:
If we instead want to move to a non-blocking .xmit() function, like
ethernet and wifi currently have, we should then push the
netif_*_queue() functions to the drivers. This has the added benefit of
increased efficiency for devices which have a hardware queue (like the
Econotag, which is managed by the serial.c driver), as netif_*_queue()
functions won't have to be turned on and off repeatedly.
Solution 2 is more invasive. Note that right now we can't add
netif_*_queue() functions to the drivers, because the drivers have no
way to get to the net_device pointer. That is a different, but related
problem, which we might as well get to now. Right now there is the idea
of hardware devices each having multiple virtual slave devices
(represented by mac802154_sub_if_data, net/mac802154/mac802154.h). These
slave devices each have a net_device pointer. The drivers only get a
pointer to the ieee802154_dev, which represents the physical hardware.
They get no net_device (and there's no way for them to get to a
net_device pointer because there are multiple net_devices (one for each
slave interface) which could be sending them data). One of the problems
here is that each of these slave interfaces can potentially (and by
design) be on a different channel, which seems to cause a major problem
since the hardware radio can only receive on a single channel at a time.
I propose implementation of solution #1 in the short term, in parallel
with discussion about the intent of slave devices what their intended
design goals were and how they can be made to work as designed (if
possible).
Alan.
[1] While I can't speak for all devices, the mrf24j40 has no hardware
queue (or, it has a single packet queue).
[2] netif_stop_queue() would go in mac802154_tx() and netif_wake_queue()
would go in mac802154_xmit_worker() once xmit() returns.
^ permalink raw reply
* Re: [PATCH v2] iproute2: tc.8: update UNITS section.
From: Li Wei @ 2012-09-10 1:28 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20120829111956.77d504ce@s6510.linuxnetplumber.net>
On 08/30/2012 02:19 AM, Stephen Hemminger wrote:
> On Wed, 29 Aug 2012 14:41:56 +0800
> Li Wei <lw@cn.fujitsu.com> wrote:
>
>> - rename section UNITS to PARAMETERS.
>> - break section PARAMETERS down to four subsections to cover the
>> common used parameter types(RATES, TIMES, SIZES, VALUES).
>> - add some explaination for IEC units in RATES.
>> - point out the max value we can set for RATES, TIMES and SIZES.
>>
>> Signed-off-by: Li Wei <lw@cn.fujitsu.com>
>
> Plan to merge this when I get back next week.
ping ...
>
>
^ permalink raw reply
* Re: RFC - document network device carrier management
From: Jan Engelhardt @ 2012-09-10 2:00 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20120815085827.2b252094@nehalam.linuxnetplumber.net>
On Wednesday 2012-08-15 17:58, Stephen Hemminger wrote:
>--- a/Documentation/networking/netdevices.txt 2012-06-22 08:27:46.729168196 -0700
>+++ b/Documentation/networking/netdevices.txt 2012-08-15 08:56:31.120429994 -0700
>@@ -45,6 +45,36 @@ drop, truncate, or pass up oversize pack
> packets is preferred.
>
>
>+CARRIER
>+=======
>+Most network devices have an operational state that the device
>+monitors. The Linux kernel uses the name "carrier" for this flag which
>+is a historical reference to old modems. Carrier is reported to
>+userspace via the IFF_RUNNING flag from SIOCGIFFLAGS ioctl.
I think Netlink should be mentioned instead:
Carrier is reported to userspace via the IFF_RUNNING flag in
struct ifinfomsg.ifi_flags returned by RTM_GETLINK (see rtnetlink(7)).
^ permalink raw reply
* Re: [PATCHv4] virtio-spec: virtio network device multiqueue support
From: Rusty Russell @ 2012-09-10 2:12 UTC (permalink / raw)
To: Michael S. Tsirkin, kvm, virtualization, netdev
Cc: pbonzini, rick.jones2, levinsasha928, Tom Herbert
In-Reply-To: <20120909130308.GA3471@redhat.com>
OK, I read the spec (pasted below for easy of reading), but I'm still
confused over how this will work.
I thought normal net drivers have the hardware provide an rxhash for
each packet, and we map that to CPU to queue the packet on[1]. We hope
that the receiving process migrates to that CPU, so xmit queue
matches.
For virtio this would mean a new per-packet rxhash value, right?
Why are we doing something different? What am I missing?
Thanks,
Rusty.
[1] Everything I Know About Networking I Learned From LWN:
https://lwn.net/Articles/362339/
---
Transmit Packet Steering
When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, guest can use any of multiple configured transmit queues to transmit a given packet. To avoid packet reordering by device (which generally leads to performance degradation) driver should attempt to utilize the same transmit virtqueue for all packets of a given transmit flow. For bi-directional protocols (in practice, TCP), a given network connection can utilize both transmit and receive queues. For best performance, packets from a single connection should utilize the paired transmit and receive queues from the same virtqueue pair; for example both transmitqN and receiveqN. This rule makes it possible to optimize processing on the device side, but this is not a hard requirement: devices should function correctly even when this rule is
not followed.
Driver selects an active steering rule using VIRTIO_NET_CTRL_STEERING command (this controls both which virtqueue is selected for a given packet for receive and notifies the device which virtqueues are about to be used for transmit).
This command accepts a single out argument in the following format:
#define VIRTIO_NET_CTRL_STEERING 4
The field rule specifies the function used to select transmit virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE (this is the default) all packets are steered to the default virtqueue transmitq (1); param is unused; this is the default. With any other rule, When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by driver to the first N=(param+1) multiqueue virtqueues transmitq1...transmitqN; the default transmitq is unused. Driver must have configured all these (param+1) virtqueues beforehand.
Supported steering rules can be added and removed in the future. Driver should check that the request to change the steering rule was successful by checking ack values of the command. As selecting a specific steering is an optimization feature, drivers should avoid hard failure and fall back on using a supported steering rule if this command fails. The default steering rule is VIRTIO_NET_CTRL_STEERING_SINGLE. It will not be removed.
When the steering rule is modified, some packets can still be outstanding in one or more of the transmit virtqueues. Since drivers might choose to modify the current steering rule at a high rate (e.g. adaptively in response to changes in the workload) to avoid reordering packets, device is recommended to complete processing of the transmit queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
For debugging, the current steering rule can also be read from the configuration space.
Receive Packet Steering
When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, device can use any of multiple configured receive queues to pass a given packet to driver. Driver controls which virtqueue is selected in practice by configuring packet steering rule using VIRTIO_NET_CTRL_STEERING command, as described above[sub:Transmit-Packet-Steering].
The field rule specifies the function used to select receive virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE all packets are steered to the default virtqueue receiveq (0); param is unused; this is the default. When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by host to the first N=(param+1) multiqueue virtqueues receiveq1...receiveqN; the default receiveq is unused. Driver must have configured all these (param+1) virtqueues beforehand. For best performance for bi-directional flows (such as TCP) device should detect the flow to virtqueue pair mapping on transmit and select the receive virtqueue from the same virtqueue pair. For uni-directional flows, o
r when this mapping information is missing, a device-specific steering function is used.
Supported steering rules can be added and removed in the future. Driver should probe for supported rules by checking ack values of the command.
When the steering rule is modified, some packets can still be outstanding in one or more of the virtqueues. Device is not required to wait for these packets to be consumed before delivering packets using the new streering rule. Drivers modifying the steering rule at a high rate (e.g. adaptively in response to changes in the workload) are recommended to complete processing of the receive queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
^ permalink raw reply
* [PATCH] caif: move the dereference below the NULL test
From: Wei Yongjun @ 2012-09-10 4:38 UTC (permalink / raw)
To: sjur.brandeland, davem; +Cc: yongjun_wei, netdev
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
The dereference should be moved below the NULL test.
spatch with a semantic match is used to found this.
(http://coccinelle.lip6.fr/)
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
net/caif/cfsrvl.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
index dd485f6..ba217e9 100644
--- a/net/caif/cfsrvl.c
+++ b/net/caif/cfsrvl.c
@@ -211,9 +211,10 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,
void (*put)(struct cflayer *lyr))
{
struct cfsrvl *service;
- service = container_of(adapt_layer->dn, struct cfsrvl, layer);
- WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL);
+ if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL))
+ return;
+ service = container_of(adapt_layer->dn, struct cfsrvl, layer);
service->hold = hold;
service->put = put;
}
^ permalink raw reply related
* [PATCH] rndis_wlan: move the dereference below the NULL test
From: Wei Yongjun @ 2012-09-10 4:46 UTC (permalink / raw)
To: jussi.kivilinna, linville; +Cc: yongjun_wei, linux-wireless, netdev
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
The dereference should be moved below the NULL test.
spatch with a semantic match is used to found this.
(http://coccinelle.lip6.fr/)
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
drivers/net/wireless/rndis_wlan.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 7a4ae9e..de2a673 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1946,12 +1946,19 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
static int rndis_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
- struct net_device *dev = request->wdev->netdev;
- struct usbnet *usbdev = netdev_priv(dev);
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ struct net_device *dev;
+ struct usbnet *usbdev;
+ struct rndis_wlan_private *priv;
int ret;
int delay = SCAN_DELAY_JIFFIES;
+ if (!request)
+ return -EINVAL;
+
+ dev = request->wdev->netdev;
+ usbdev = netdev_priv(dev);
+ priv = get_rndis_wlan_priv(usbdev);
+
netdev_dbg(usbdev->net, "cfg80211.scan\n");
/* Get current bssid list from device before new scan, as new scan
@@ -1959,9 +1966,6 @@ static int rndis_scan(struct wiphy *wiphy,
*/
rndis_check_bssid_list(usbdev, NULL, NULL);
- if (!request)
- return -EINVAL;
-
if (priv->scan_request && priv->scan_request != request)
return -EBUSY;
^ permalink raw reply related
* Re: (ipt_log_packet, sb_add) 3.6.0-rc2 kernel panic - not syncing; Fatal exception in interrupt
From: Jan Engelhardt @ 2012-09-10 5:02 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Florian Westphal, Sami Farin, netdev, e1000-devel
In-Reply-To: <1346626385.2563.44.camel@edumazet-glaptop>
On Monday 2012-09-03 00:53, Eric Dumazet wrote:
>[PATCH] xt_LOG: take care of timewait sockets
>
>Sami Farin reported crashes in xt_LOG because it assumes skb->sk is a
>full blown socket.
>
>But with TCP early demux, we can have skb->sk pointing to a timewait
>socket.
>
>+static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk)
>+{
>+ if (!sk || sk->sk_state == TCP_TIME_WAIT)
>+ return;
>+
>+ read_lock_bh(&sk->sk_callback_lock);
>+ if (sk->sk_socket && sk->sk_socket->file)
>+ sb_add(m, "UID=%u GID=%u ",
>+ sk->sk_socket->file->f_cred->fsuid,
>+ sk->sk_socket->file->f_cred->fsgid);
xt_owner.c is also using f_cred, so it might need the same,
does it not?
^ permalink raw reply
* Re: (ipt_log_packet, sb_add) 3.6.0-rc2 kernel panic - not syncing; Fatal exception in interrupt
From: Eric Dumazet @ 2012-09-10 6:00 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Sami Farin, netdev, Florian Westphal, e1000-devel
In-Reply-To: <alpine.LNX.2.01.1209100659220.22738@frira.zrqbmnf.qr>
On Mon, 2012-09-10 at 07:02 +0200, Jan Engelhardt wrote:
> On Monday 2012-09-03 00:53, Eric Dumazet wrote:
> >[PATCH] xt_LOG: take care of timewait sockets
> >
> >Sami Farin reported crashes in xt_LOG because it assumes skb->sk is a
> >full blown socket.
> >
> >But with TCP early demux, we can have skb->sk pointing to a timewait
> >socket.
> >
> >+static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk)
> >+{
> >+ if (!sk || sk->sk_state == TCP_TIME_WAIT)
> >+ return;
> >+
> >+ read_lock_bh(&sk->sk_callback_lock);
> >+ if (sk->sk_socket && sk->sk_socket->file)
> >+ sb_add(m, "UID=%u GID=%u ",
> >+ sk->sk_socket->file->f_cred->fsuid,
> >+ sk->sk_socket->file->f_cred->fsgid);
>
> xt_owner.c is also using f_cred, so it might need the same,
> does it not?
Right.
AFAIK, xt_owner would make little sense in input path, no ?
static struct xt_match owner_mt_reg __read_mostly = {
.name = "owner",
.revision = 1,
.family = NFPROTO_UNSPEC,
.checkentry = owner_check,
.match = owner_mt,
.matchsize = sizeof(struct xt_owner_match_info),
.hooks = (1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING),
.me = THIS_MODULE,
};
So it seems we have nothing to do at this moment.
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: RFC: mac802154 Packet Queueing and Slave Devices
From: Eric Dumazet @ 2012-09-10 6:12 UTC (permalink / raw)
To: Alan Ott
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <504D37A7.60109-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
On Sun, 2012-09-09 at 20:43 -0400, Alan Ott wrote:
> Hi,
>
> Tony and I were recently talking about packet queueing on 802.15.4. What
> currently happens (in net/mac802154/tx.c) is that each tx packet (skb)
> is stuck on a work queue, and the worker function then sends each packet
> to the hardware driver in order.
>
> The problem with this is that it defeats the netif flow control.
And qdisc ability to better control bufferbloat...
By the way, mac802154_tx() looks buggy :
if (!(priv->phy->channels_supported[page] & (1 << chan))) {
WARN_ON(1);
// Here, a kfree_skb(skb) is missing.
return NETDEV_TX_OK;
}
if (skb_cow_head(skb, priv->hw.extra_tx_headroom)) {
dev_kfree_skb(skb); // should be kfree_skb(skb)
return NETDEV_TX_OK;
}
work = kzalloc(sizeof(struct xmit_work), GFP_ATOMIC);
if (!work)
return NETDEV_TX_BUSY;
NETDEV_TX_BUSY is going to loop. So if there is really no more memory,
its a deadlock. You should instead kfree_skb(skb) and return
NETDEV_TX_OK.
Also mac802154_wpan_xmit() returns NETDEV_TX_OK without kfree_skb(skb)
here :
if (chan == MAC802154_CHAN_NONE ||
page >= WPAN_NUM_PAGES ||
chan >= WPAN_NUM_CHANNELS)
return NETDEV_TX_OK;
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply
* Re: [PATCHv4] virtio-spec: virtio network device multiqueue support
From: Michael S. Tsirkin @ 2012-09-10 6:16 UTC (permalink / raw)
To: Rusty Russell
Cc: kvm, netdev, rick.jones2, virtualization, levinsasha928, pbonzini,
Tom Herbert
In-Reply-To: <878vcifwxi.fsf@rustcorp.com.au>
On Mon, Sep 10, 2012 at 11:42:25AM +0930, Rusty Russell wrote:
> OK, I read the spec (pasted below for easy of reading), but I'm still
> confused over how this will work.
>
> I thought normal net drivers have the hardware provide an rxhash for
> each packet, and we map that to CPU to queue the packet on[1]. We hope
> that the receiving process migrates to that CPU, so xmit queue
> matches.
This ony works sometimes. For example it's common to pin netperf to a
cpu to get consistent performance. Proper hardware must obey what
applications want it to do, not the other way around.
> For virtio this would mean a new per-packet rxhash value, right?
>
> Why are we doing something different? What am I missing?
>
> Thanks,
> Rusty.
> [1] Everything I Know About Networking I Learned From LWN:
> https://lwn.net/Articles/362339/
I think you missed this:
Some network interfaces can help with the distribution of incoming
packets; they have multiple receive queues and multiple interrupt lines.
Others, though, are equipped with a single queue, meaning that the
driver for that hardware must deal with all incoming packets in a
single, serialized stream. Parallelizing such a stream requires some
intelligence on the part of the host operating system.
In other words RPS is a hack to speed up networking on cheapo
hardware, this is one of the reasons it is off by default.
Good hardware has multiple receive queues.
We can implement a good one so we do not need RPS.
Also not all guest OS-es support RPS.
Does this clarify?
> ---
> Transmit Packet Steering
>
> When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, guest can use any of multiple configured transmit queues to transmit a given packet. To avoid packet reordering by device (which generally leads to performance degradation) driver should attempt to utilize the same transmit virtqueue for all packets of a given transmit flow. For bi-directional protocols (in practice, TCP), a given network connection can utilize both transmit and receive queues. For best performance, packets from a single connection should utilize the paired transmit and receive queues from the same virtqueue pair; for example both transmitqN and receiveqN. This rule makes it possible to optimize processing on the device side, but this is not a hard requirement: devices should function correctly even when this rule i
s not followed.
>
> Driver selects an active steering rule using VIRTIO_NET_CTRL_STEERING command (this controls both which virtqueue is selected for a given packet for receive and notifies the device which virtqueues are about to be used for transmit).
>
> This command accepts a single out argument in the following format:
>
> #define VIRTIO_NET_CTRL_STEERING 4
>
> The field rule specifies the function used to select transmit virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE (this is the default) all packets are steered to the default virtqueue transmitq (1); param is unused; this is the default. With any other rule, When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by driver to the first N=(param+1) multiqueue virtqueues transmitq1...transmitqN; the default transmitq is unused. Driver must have configured all these (param+1) virtqueues beforehand.
>
> Supported steering rules can be added and removed in the future. Driver should check that the request to change the steering rule was successful by checking ack values of the command. As selecting a specific steering is an optimization feature, drivers should avoid hard failure and fall back on using a supported steering rule if this command fails. The default steering rule is VIRTIO_NET_CTRL_STEERING_SINGLE. It will not be removed.
>
> When the steering rule is modified, some packets can still be outstanding in one or more of the transmit virtqueues. Since drivers might choose to modify the current steering rule at a high rate (e.g. adaptively in response to changes in the workload) to avoid reordering packets, device is recommended to complete processing of the transmit queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
>
> For debugging, the current steering rule can also be read from the configuration space.
>
> Receive Packet Steering
>
> When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, device can use any of multiple configured receive queues to pass a given packet to driver. Driver controls which virtqueue is selected in practice by configuring packet steering rule using VIRTIO_NET_CTRL_STEERING command, as described above[sub:Transmit-Packet-Steering].
>
> The field rule specifies the function used to select receive virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE all packets are steered to the default virtqueue receiveq (0); param is unused; this is the default. When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by host to the first N=(param+1) multiqueue virtqueues receiveq1...receiveqN; the default receiveq is unused. Driver must have configured all these (param+1) virtqueues beforehand. For best performance for bi-directional flows (such as TCP) device should detect the flow to virtqueue pair mapping on transmit and select the receive virtqueue from the same virtqueue pair. For uni-directional flows,
or when this mapping information is missing, a device-specific steering function is used.
>
> Supported steering rules can be added and removed in the future. Driver should probe for supported rules by checking ack values of the command.
>
> When the steering rule is modified, some packets can still be outstanding in one or more of the virtqueues. Device is not required to wait for these packets to be consumed before delivering packets using the new streering rule. Drivers modifying the steering rule at a high rate (e.g. adaptively in response to changes in the workload) are recommended to complete processing of the receive queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
^ permalink raw reply
* Re: [PATCHv4] virtio-spec: virtio network device multiqueue support
From: Michael S. Tsirkin @ 2012-09-10 6:27 UTC (permalink / raw)
To: Rusty Russell
Cc: kvm, netdev, rick.jones2, virtualization, levinsasha928, pbonzini,
Tom Herbert
In-Reply-To: <20120910061629.GC16819@redhat.com>
On Mon, Sep 10, 2012 at 09:16:29AM +0300, Michael S. Tsirkin wrote:
> On Mon, Sep 10, 2012 at 11:42:25AM +0930, Rusty Russell wrote:
> > OK, I read the spec (pasted below for easy of reading), but I'm still
> > confused over how this will work.
> >
> > I thought normal net drivers have the hardware provide an rxhash for
> > each packet, and we map that to CPU to queue the packet on[1]. We hope
> > that the receiving process migrates to that CPU, so xmit queue
> > matches.
>
> This ony works sometimes. For example it's common to pin netperf to a
> cpu to get consistent performance. Proper hardware must obey what
> applications want it to do, not the other way around.
>
> > For virtio this would mean a new per-packet rxhash value, right?
> >
> > Why are we doing something different? What am I missing?
> >
> > Thanks,
> > Rusty.
> > [1] Everything I Know About Networking I Learned From LWN:
> > https://lwn.net/Articles/362339/
>
> I think you missed this:
>
> Some network interfaces can help with the distribution of incoming
> packets; they have multiple receive queues and multiple interrupt lines.
> Others, though, are equipped with a single queue, meaning that the
> driver for that hardware must deal with all incoming packets in a
> single, serialized stream. Parallelizing such a stream requires some
> intelligence on the part of the host operating system.
>
> In other words RPS is a hack to speed up networking on cheapo
> hardware, this is one of the reasons it is off by default.
> Good hardware has multiple receive queues.
> We can implement a good one so we do not need RPS.
>
> Also not all guest OS-es support RPS.
>
> Does this clarify?
I would like to add that on many processors, sending
IPCs between guest CPUs requires exits on sending *and*
receiving path, making it very expensive.
> > ---
> > Transmit Packet Steering
> >
> > When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, guest can use any of multiple configured transmit queues to transmit a given packet. To avoid packet reordering by device (which generally leads to performance degradation) driver should attempt to utilize the same transmit virtqueue for all packets of a given transmit flow. For bi-directional protocols (in practice, TCP), a given network connection can utilize both transmit and receive queues. For best performance, packets from a single connection should utilize the paired transmit and receive queues from the same virtqueue pair; for example both transmitqN and receiveqN. This rule makes it possible to optimize processing on the device side, but this is not a hard requirement: devices should function correctly even when this rule
is not followed.
> >
> > Driver selects an active steering rule using VIRTIO_NET_CTRL_STEERING command (this controls both which virtqueue is selected for a given packet for receive and notifies the device which virtqueues are about to be used for transmit).
> >
> > This command accepts a single out argument in the following format:
> >
> > #define VIRTIO_NET_CTRL_STEERING 4
> >
> > The field rule specifies the function used to select transmit virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE (this is the default) all packets are steered to the default virtqueue transmitq (1); param is unused; this is the default. With any other rule, When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by driver to the first N=(param+1) multiqueue virtqueues transmitq1...transmitqN; the default transmitq is unused. Driver must have configured all these (param+1) virtqueues beforehand.
> >
> > Supported steering rules can be added and removed in the future. Driver should check that the request to change the steering rule was successful by checking ack values of the command. As selecting a specific steering is an optimization feature, drivers should avoid hard failure and fall back on using a supported steering rule if this command fails. The default steering rule is VIRTIO_NET_CTRL_STEERING_SINGLE. It will not be removed.
> >
> > When the steering rule is modified, some packets can still be outstanding in one or more of the transmit virtqueues. Since drivers might choose to modify the current steering rule at a high rate (e.g. adaptively in response to changes in the workload) to avoid reordering packets, device is recommended to complete processing of the transmit queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
> >
> > For debugging, the current steering rule can also be read from the configuration space.
> >
> > Receive Packet Steering
> >
> > When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, device can use any of multiple configured receive queues to pass a given packet to driver. Driver controls which virtqueue is selected in practice by configuring packet steering rule using VIRTIO_NET_CTRL_STEERING command, as described above[sub:Transmit-Packet-Steering].
> >
> > The field rule specifies the function used to select receive virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE all packets are steered to the default virtqueue receiveq (0); param is unused; this is the default. When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by host to the first N=(param+1) multiqueue virtqueues receiveq1...receiveqN; the default receiveq is unused. Driver must have configured all these (param+1) virtqueues beforehand. For best performance for bi-directional flows (such as TCP) device should detect the flow to virtqueue pair mapping on transmit and select the receive virtqueue from the same virtqueue pair. For uni-directional flow
s, or when this mapping information is missing, a device-specific steering function is used.
> >
> > Supported steering rules can be added and removed in the future. Driver should probe for supported rules by checking ack values of the command.
> >
> > When the steering rule is modified, some packets can still be outstanding in one or more of the virtqueues. Device is not required to wait for these packets to be consumed before delivering packets using the new streering rule. Drivers modifying the steering rule at a high rate (e.g. adaptively in response to changes in the workload) are recommended to complete processing of the receive queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
^ permalink raw reply
* Re: [PATCH] rndis_wlan: move the dereference below the NULL test
From: Jussi Kivilinna @ 2012-09-10 6:29 UTC (permalink / raw)
To: Wei Yongjun; +Cc: linville, yongjun_wei, linux-wireless, netdev
In-Reply-To: <CAPgLHd97uPhcX-dTkur_Ceb=8YOwWQtbRk7MqirNvsYBbDoZ1A@mail.gmail.com>
Quoting Wei Yongjun <weiyj.lk@gmail.com>:
> From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
>
> The dereference should be moved below the NULL test.
>
> spatch with a semantic match is used to found this.
> (http://coccinelle.lip6.fr/)
>
> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
> ---
> drivers/net/wireless/rndis_wlan.c | 16 ++++++++++------
> 1 file changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/rndis_wlan.c
> b/drivers/net/wireless/rndis_wlan.c
> index 7a4ae9e..de2a673 100644
> --- a/drivers/net/wireless/rndis_wlan.c
> +++ b/drivers/net/wireless/rndis_wlan.c
> @@ -1946,12 +1946,19 @@ static int rndis_get_tx_power(struct wiphy
> *wiphy, int *dbm)
> static int rndis_scan(struct wiphy *wiphy,
> struct cfg80211_scan_request *request)
> {
> - struct net_device *dev = request->wdev->netdev;
> - struct usbnet *usbdev = netdev_priv(dev);
> - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
> + struct net_device *dev;
> + struct usbnet *usbdev;
> + struct rndis_wlan_private *priv;
> int ret;
> int delay = SCAN_DELAY_JIFFIES;
>
> + if (!request)
> + return -EINVAL;
> +
> + dev = request->wdev->netdev;
> + usbdev = netdev_priv(dev);
> + priv = get_rndis_wlan_priv(usbdev);
> +
'request' is actually always valid pointer and the !request check is
unneeded. Correct fix is to remove the check.
> netdev_dbg(usbdev->net, "cfg80211.scan\n");
>
> /* Get current bssid list from device before new scan, as new scan
> @@ -1959,9 +1966,6 @@ static int rndis_scan(struct wiphy *wiphy,
> */
> rndis_check_bssid_list(usbdev, NULL, NULL);
>
> - if (!request)
> - return -EINVAL;
> -
Only this part is needed.
-Jussi
> if (priv->scan_request && priv->scan_request != request)
> return -EBUSY;
>
^ permalink raw reply
* Re: [PATCHv4] virtio-spec: virtio network device multiqueue support
From: Michael S. Tsirkin @ 2012-09-10 6:33 UTC (permalink / raw)
To: Rusty Russell
Cc: kvm, netdev, rick.jones2, virtualization, levinsasha928, pbonzini,
Tom Herbert
In-Reply-To: <20120910062738.GA17331@redhat.com>
On Mon, Sep 10, 2012 at 09:27:38AM +0300, Michael S. Tsirkin wrote:
> On Mon, Sep 10, 2012 at 09:16:29AM +0300, Michael S. Tsirkin wrote:
> > On Mon, Sep 10, 2012 at 11:42:25AM +0930, Rusty Russell wrote:
> > > OK, I read the spec (pasted below for easy of reading), but I'm still
> > > confused over how this will work.
> > >
> > > I thought normal net drivers have the hardware provide an rxhash for
> > > each packet, and we map that to CPU to queue the packet on[1]. We hope
> > > that the receiving process migrates to that CPU, so xmit queue
> > > matches.
> >
> > This ony works sometimes. For example it's common to pin netperf to a
> > cpu to get consistent performance. Proper hardware must obey what
> > applications want it to do, not the other way around.
> >
> > > For virtio this would mean a new per-packet rxhash value, right?
> > >
> > > Why are we doing something different? What am I missing?
> > >
> > > Thanks,
> > > Rusty.
> > > [1] Everything I Know About Networking I Learned From LWN:
> > > https://lwn.net/Articles/362339/
> >
> > I think you missed this:
> >
> > Some network interfaces can help with the distribution of incoming
> > packets; they have multiple receive queues and multiple interrupt lines.
> > Others, though, are equipped with a single queue, meaning that the
> > driver for that hardware must deal with all incoming packets in a
> > single, serialized stream. Parallelizing such a stream requires some
> > intelligence on the part of the host operating system.
> >
> > In other words RPS is a hack to speed up networking on cheapo
> > hardware, this is one of the reasons it is off by default.
> > Good hardware has multiple receive queues.
> > We can implement a good one so we do not need RPS.
> >
> > Also not all guest OS-es support RPS.
> >
> > Does this clarify?
>
> I would like to add that on many processors, sending
> IPCs between guest CPUs requires exits on sending *and*
> receiving path, making it very expensive.
A final addition: what you suggest above would be
"TX follows RX", right?
It is in anticipation of something like that, that I made
steering programming so generic.
I think TX follows RX is more immediately useful for reasons above
but we can add both to spec and let drivers and devices
decide what they want to support.
Pls let me know.
> > > ---
> > > Transmit Packet Steering
> > >
> > > When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, guest can use any of multiple configured transmit queues to transmit a given packet. To avoid packet reordering by device (which generally leads to performance degradation) driver should attempt to utilize the same transmit virtqueue for all packets of a given transmit flow. For bi-directional protocols (in practice, TCP), a given network connection can utilize both transmit and receive queues. For best performance, packets from a single connection should utilize the paired transmit and receive queues from the same virtqueue pair; for example both transmitqN and receiveqN. This rule makes it possible to optimize processing on the device side, but this is not a hard requirement: devices should function correctly even when this ru
le is not followed.
> > >
> > > Driver selects an active steering rule using VIRTIO_NET_CTRL_STEERING command (this controls both which virtqueue is selected for a given packet for receive and notifies the device which virtqueues are about to be used for transmit).
> > >
> > > This command accepts a single out argument in the following format:
> > >
> > > #define VIRTIO_NET_CTRL_STEERING 4
> > >
> > > The field rule specifies the function used to select transmit virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE (this is the default) all packets are steered to the default virtqueue transmitq (1); param is unused; this is the default. With any other rule, When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by driver to the first N=(param+1) multiqueue virtqueues transmitq1...transmitqN; the default transmitq is unused. Driver must have configured all these (param+1) virtqueues beforehand.
> > >
> > > Supported steering rules can be added and removed in the future. Driver should check that the request to change the steering rule was successful by checking ack values of the command. As selecting a specific steering is an optimization feature, drivers should avoid hard failure and fall back on using a supported steering rule if this command fails. The default steering rule is VIRTIO_NET_CTRL_STEERING_SINGLE. It will not be removed.
> > >
> > > When the steering rule is modified, some packets can still be outstanding in one or more of the transmit virtqueues. Since drivers might choose to modify the current steering rule at a high rate (e.g. adaptively in response to changes in the workload) to avoid reordering packets, device is recommended to complete processing of the transmit queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
> > >
> > > For debugging, the current steering rule can also be read from the configuration space.
> > >
> > > Receive Packet Steering
> > >
> > > When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, device can use any of multiple configured receive queues to pass a given packet to driver. Driver controls which virtqueue is selected in practice by configuring packet steering rule using VIRTIO_NET_CTRL_STEERING command, as described above[sub:Transmit-Packet-Steering].
> > >
> > > The field rule specifies the function used to select receive virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE all packets are steered to the default virtqueue receiveq (0); param is unused; this is the default. When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by host to the first N=(param+1) multiqueue virtqueues receiveq1...receiveqN; the default receiveq is unused. Driver must have configured all these (param+1) virtqueues beforehand. For best performance for bi-directional flows (such as TCP) device should detect the flow to virtqueue pair mapping on transmit and select the receive virtqueue from the same virtqueue pair. For uni-directional fl
ows, or when this mapping information is missing, a device-specific steering function is used.
> > >
> > > Supported steering rules can be added and removed in the future. Driver should probe for supported rules by checking ack values of the command.
> > >
> > > When the steering rule is modified, some packets can still be outstanding in one or more of the virtqueues. Device is not required to wait for these packets to be consumed before delivering packets using the new streering rule. Drivers modifying the steering rule at a high rate (e.g. adaptively in response to changes in the workload) are recommended to complete processing of the receive queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
^ permalink raw reply
* Re: [PATCH net-next] ipv6: fix handling of throw routes
From: Nicolas Dichtel @ 2012-09-10 7:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, markus.stenberg, eric.dumazet
In-Reply-To: <20120907.141808.933339383624986735.davem@davemloft.net>
Le 07/09/2012 20:18, David Miller a écrit :
> From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Date: Thu, 6 Sep 2012 11:53:35 -0400
>
>> It's the same problem that previous fix about blackhole and prohibit routes.
>>
>> When adding a throw route, it was handled like a classic route.
>> Moreover, it was only possible to add this kind of routes by specifying
>> an interface.
>>
>> Before the patch:
>> $ ip route add throw 2001::2/128
>> RTNETLINK answers: No such device
>> $ ip route add throw 2001::2/128 dev eth0
>> $ ip -6 route | grep 2001::2
>> 2001::2 dev eth0 metric 1024
>>
>> After:
>> $ ip route add throw 2001::2/128
>> $ ip -6 route | grep 2001::2
>> throw 2001::2 dev lo metric 1024 error -11
>>
>> Reported-by: Markus Stenberg <markus.stenberg@iki.fi>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>
> Applied, thanks.
>
> See how easy this was to implement via ->rtm_type? :-)
>
Definitely!
^ permalink raw reply
* Who maintains and handles patches for drivers/net/phy/ ?
From: leroy christophe @ 2012-09-10 7:20 UTC (permalink / raw)
To: netdev
The MAINTAINER file doesn't include any maintainer for drivers/net/phy/
Section NETWORKING DRIVERS doesn't refer to anyone.
I have a patch for the Intel LXT phy driver. I submitted it to the list
a few weeks ago but didn't get any feedback at all.
Who shall I contact to get my patch taken into account ?
Regards
Christophe
^ permalink raw reply
* [PATCH v2] rndis_wlan: remove pointless check from rndis_scan()
From: Wei Yongjun @ 2012-09-10 7:21 UTC (permalink / raw)
To: jussi.kivilinna, linville; +Cc: yongjun_wei, linux-wireless, netdev
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
In rndis_scan(), 'request' is actually always valid pointer and
the !request check is unneeded, so remove it.
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
drivers/net/wireless/rndis_wlan.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 7a4ae9e..bd1f0cb 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1959,9 +1959,6 @@ static int rndis_scan(struct wiphy *wiphy,
*/
rndis_check_bssid_list(usbdev, NULL, NULL);
- if (!request)
- return -EINVAL;
-
if (priv->scan_request && priv->scan_request != request)
return -EBUSY;
^ permalink raw reply related
* [net-next.git 6/8] stmmac: fix and review the rx irq path after adding new mitigation
From: Giuseppe CAVALLARO @ 2012-09-10 7:38 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, davem, Giuseppe Cavallaro
In-Reply-To: <1347262689-21251-1-git-send-email-peppe.cavallaro@st.com>
After adopting the new mitigation approach I have
found a couple of problems in the rx irq path.
The enable/disable_dma_irq functions now are used for
handling the DMA_INTR_ENA_RIE bit in the DMA register 7.
So this patch masks the specific bit in this register.
Also these function names have been changed (to make clear
their meaning).
A new extra statistic field has been added to show the early
receive status in the interrupt handler as well. This has been
useful on debugging stage, indeed.
In the end, this patch also adds an extra check to avoid to call
napi_schedule when the DMA_INTR_ENA_RIE bit is disabled in the
Interrupt Mask register.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 12 +++++---
.../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 27 ++++++++++++++-----
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 9 ++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 17 ++++--------
7 files changed, 45 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 3ab3684..b563645 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -85,7 +85,7 @@ struct stmmac_extra_stats {
unsigned long rx_missed_cntr;
unsigned long rx_overflow_cntr;
unsigned long rx_vlan;
- /* Tx/Rx IRQ errors */
+ /* Tx/Rx IRQ error info */
unsigned long tx_undeflow_irq;
unsigned long tx_process_stopped_irq;
unsigned long tx_jabber_irq;
@@ -95,7 +95,8 @@ struct stmmac_extra_stats {
unsigned long rx_watchdog_irq;
unsigned long tx_early_irq;
unsigned long fatal_bus_error_irq;
- /* Extra info */
+ /* Tx/Rx IRQ Events */
+ unsigned long rx_early_irq;
unsigned long threshold;
unsigned long tx_pkt_n;
unsigned long rx_pkt_n;
@@ -106,11 +107,12 @@ struct stmmac_extra_stats {
unsigned long txtimer;
unsigned long tx_clean;
unsigned long tx_reset_ic_bit;
+ unsigned long irq_receive_pmt_irq_n;
+ /* MMC info */
unsigned long mmc_tx_irq_n;
unsigned long mmc_rx_irq_n;
unsigned long mmc_rx_csum_offload_irq_n;
/* EEE */
- unsigned long irq_receive_pmt_irq_n;
unsigned long irq_tx_path_in_lpi_mode_n;
unsigned long irq_tx_path_exit_lpi_mode_n;
unsigned long irq_rx_path_in_lpi_mode_n;
@@ -302,8 +304,8 @@ struct stmmac_dma_ops {
void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
void __iomem *ioaddr);
void (*enable_dma_transmission) (void __iomem *ioaddr);
- void (*enable_dma_irq) (void __iomem *ioaddr);
- void (*disable_dma_irq) (void __iomem *ioaddr);
+ void (*enable_rx_dma_irq) (void __iomem *ioaddr);
+ void (*disable_rx_dma_irq) (void __iomem *ioaddr);
void (*start_tx) (void __iomem *ioaddr);
void (*stop_tx) (void __iomem *ioaddr);
void (*start_rx) (void __iomem *ioaddr);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index e2c9431..69c8906 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -184,8 +184,8 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
.dump_regs = dwmac1000_dump_dma_regs,
.dma_mode = dwmac1000_dma_operation_mode,
.enable_dma_transmission = dwmac_enable_dma_transmission,
- .enable_dma_irq = dwmac_enable_dma_irq,
- .disable_dma_irq = dwmac_disable_dma_irq,
+ .enable_rx_dma_irq = dwmac_enable_rx_dma_irq,
+ .disable_rx_dma_irq = dwmac_disable_rx_dma_irq,
.start_tx = dwmac_dma_start_tx,
.stop_tx = dwmac_dma_stop_tx,
.start_rx = dwmac_dma_start_rx,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index c2b4d55..81630c3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -134,8 +134,8 @@ const struct stmmac_dma_ops dwmac100_dma_ops = {
.dma_mode = dwmac100_dma_operation_mode,
.dma_diagnostic_fr = dwmac100_dma_diagnostic_fr,
.enable_dma_transmission = dwmac_enable_dma_transmission,
- .enable_dma_irq = dwmac_enable_dma_irq,
- .disable_dma_irq = dwmac_disable_dma_irq,
+ .enable_rx_dma_irq = dwmac_enable_rx_dma_irq,
+ .disable_rx_dma_irq = dwmac_disable_rx_dma_irq,
.start_tx = dwmac_dma_start_tx,
.stop_tx = dwmac_dma_stop_tx,
.start_rx = dwmac_dma_start_rx,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 4eeff5d..b91c8cf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -105,8 +105,8 @@
#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */
extern void dwmac_enable_dma_transmission(void __iomem *ioaddr);
-extern void dwmac_enable_dma_irq(void __iomem *ioaddr);
-extern void dwmac_disable_dma_irq(void __iomem *ioaddr);
+extern void dwmac_enable_rx_dma_irq(void __iomem *ioaddr);
+extern void dwmac_disable_rx_dma_irq(void __iomem *ioaddr);
extern void dwmac_dma_start_tx(void __iomem *ioaddr);
extern void dwmac_dma_stop_tx(void __iomem *ioaddr);
extern void dwmac_dma_start_rx(void __iomem *ioaddr);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 73766e6..a650019 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -39,14 +39,20 @@ void dwmac_enable_dma_transmission(void __iomem *ioaddr)
writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
}
-void dwmac_enable_dma_irq(void __iomem *ioaddr)
+void dwmac_enable_rx_dma_irq(void __iomem *ioaddr)
{
- writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+ u32 value = readl(ioaddr + DMA_INTR_ENA);
+
+ value |= DMA_INTR_ENA_RIE;
+ writel(value, ioaddr + DMA_INTR_ENA);
}
-void dwmac_disable_dma_irq(void __iomem *ioaddr)
+void dwmac_disable_rx_dma_irq(void __iomem *ioaddr)
{
- writel(0, ioaddr + DMA_INTR_ENA);
+ u32 value = readl(ioaddr + DMA_INTR_ENA);
+
+ value &= ~DMA_INTR_ENA_RIE;
+ writel(value, ioaddr + DMA_INTR_ENA);
}
void dwmac_dma_start_tx(void __iomem *ioaddr)
@@ -206,15 +212,22 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
/* TX/RX NORMAL interrupts */
if (intr_status & DMA_STATUS_NIS) {
x->normal_irq_n++;
- if (likely(intr_status & DMA_STATUS_RI))
- ret |= handle_rx;
- if (intr_status & (DMA_STATUS_TI))
+ if (likely(intr_status & DMA_STATUS_RI)) {
+ u32 value = readl(ioaddr + DMA_INTR_ENA);
+ /* to schedule NAPI on real RIE event. */
+ if (likely(value & DMA_INTR_ENA_RIE))
+ ret |= handle_rx;
+ }
+ if (intr_status & DMA_STATUS_TI)
ret |= handle_tx;
+ if (intr_status & DMA_STATUS_ERI)
+ x->rx_early_irq++;
}
/* Optional hardware blocks, interrupts should be disabled */
if (unlikely(intr_status &
(DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
pr_info("%s: unexpected status %08x\n", __func__, intr_status);
+
/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 145b97d..bc4a462 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -76,7 +76,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(rx_missed_cntr),
STMMAC_STAT(rx_overflow_cntr),
STMMAC_STAT(rx_vlan),
- /* Tx/Rx IRQ errors */
+ /* Tx/Rx IRQ error info */
STMMAC_STAT(tx_undeflow_irq),
STMMAC_STAT(tx_process_stopped_irq),
STMMAC_STAT(tx_jabber_irq),
@@ -86,7 +86,8 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(rx_watchdog_irq),
STMMAC_STAT(tx_early_irq),
STMMAC_STAT(fatal_bus_error_irq),
- /* Extra info */
+ /* Tx/Rx IRQ Events */
+ STMMAC_STAT(rx_early_irq),
STMMAC_STAT(threshold),
STMMAC_STAT(tx_pkt_n),
STMMAC_STAT(rx_pkt_n),
@@ -97,10 +98,12 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(txtimer),
STMMAC_STAT(tx_clean),
STMMAC_STAT(tx_reset_ic_bit),
+ STMMAC_STAT(irq_receive_pmt_irq_n),
+ /* MMC info */
STMMAC_STAT(mmc_tx_irq_n),
STMMAC_STAT(mmc_rx_irq_n),
STMMAC_STAT(mmc_rx_csum_offload_irq_n),
- STMMAC_STAT(irq_receive_pmt_irq_n),
+ /* EEE */
STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b0731e6..0b37c6d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -778,12 +778,12 @@ static void stmmac_tx(struct stmmac_priv *priv)
static inline void stmmac_enable_irq(struct stmmac_priv *priv)
{
- priv->hw->dma->enable_dma_irq(priv->ioaddr);
+ priv->hw->dma->enable_rx_dma_irq(priv->ioaddr);
}
static inline void stmmac_disable_irq(struct stmmac_priv *priv)
{
- priv->hw->dma->disable_dma_irq(priv->ioaddr);
+ priv->hw->dma->disable_rx_dma_irq(priv->ioaddr);
}
static void stmmac_txtimer(unsigned long data)
@@ -815,14 +815,6 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
netif_wake_queue(priv->dev);
}
-static void stmmac_rx_work(struct stmmac_priv *priv)
-{
- if (likely(napi_schedule_prep(&priv->napi))) {
- stmmac_disable_irq(priv);
- __napi_schedule(&priv->napi);
- }
-}
-
static void stmmac_dma_interrupt(struct stmmac_priv *priv)
{
int status;
@@ -830,7 +822,10 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
if (likely(status & handle_rx)) {
priv->xstats.rx_normal_irq_n++;
- stmmac_rx_work(priv);
+ if (likely(napi_schedule_prep(&priv->napi))) {
+ stmmac_disable_irq(priv);
+ __napi_schedule(&priv->napi);
+ }
}
if (likely(status & handle_tx)) {
priv->xstats.tx_normal_irq_n++;
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 2/8 (V2)] stmmac: manage tx clean out of rx_poll
From: Giuseppe CAVALLARO @ 2012-09-10 7:38 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, davem, Giuseppe Cavallaro
In-Reply-To: <1347262689-21251-1-git-send-email-peppe.cavallaro@st.com>
This patch is to invoke the stmmac_tx (tx handler)
out of the NAPI poll method.
This will make easier the next step to add the new
mitigation schema.
Also the patch enhances the ethtool to report some
stats for normal TX and RX IRQs.
V2: use status & handle_rx/tx
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 13 +++++++----
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 7 +++--
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 4 ++-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 22 ++++++++++++++-----
4 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 719be39..bd32fe6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -95,7 +95,9 @@ struct stmmac_extra_stats {
unsigned long threshold;
unsigned long tx_pkt_n;
unsigned long rx_pkt_n;
- unsigned long poll_n;
+ unsigned long rx_napi_poll;
+ unsigned long rx_normal_irq_n;
+ unsigned long tx_normal_irq_n;
unsigned long sched_timer_n;
unsigned long normal_irq_n;
unsigned long mmc_tx_irq_n;
@@ -169,10 +171,11 @@ enum rx_frame_status { /* IPC status */
llc_snap = 4,
};
-enum tx_dma_irq_status {
- tx_hard_error = 1,
- tx_hard_error_bump_tc = 2,
- handle_tx_rx = 3,
+enum dma_irq_status {
+ tx_hard_error = 0x1,
+ tx_hard_error_bump_tc = 0x2,
+ handle_rx = 0x4,
+ handle_tx = 0x8,
};
enum core_specific_irq_mask {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 4e0e18a..73766e6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -206,9 +206,10 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
/* TX/RX NORMAL interrupts */
if (intr_status & DMA_STATUS_NIS) {
x->normal_irq_n++;
- if (likely((intr_status & DMA_STATUS_RI) ||
- (intr_status & (DMA_STATUS_TI))))
- ret = handle_tx_rx;
+ if (likely(intr_status & DMA_STATUS_RI))
+ ret |= handle_rx;
+ if (intr_status & (DMA_STATUS_TI))
+ ret |= handle_tx;
}
/* Optional hardware blocks, interrupts should be disabled */
if (unlikely(intr_status &
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 76fd61a..505fe71 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -90,7 +90,9 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(threshold),
STMMAC_STAT(tx_pkt_n),
STMMAC_STAT(rx_pkt_n),
- STMMAC_STAT(poll_n),
+ STMMAC_STAT(rx_napi_poll),
+ STMMAC_STAT(rx_normal_irq_n),
+ STMMAC_STAT(tx_normal_irq_n),
STMMAC_STAT(sched_timer_n),
STMMAC_STAT(normal_irq_n),
STMMAC_STAT(normal_irq_n),
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c8985f3..8e1e53e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -824,16 +824,27 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
netif_wake_queue(priv->dev);
}
+static inline void stmmac_rx_schedule(struct stmmac_priv *priv)
+{
+ if (likely(napi_schedule_prep(&priv->napi))) {
+ stmmac_disable_irq(priv);
+ __napi_schedule(&priv->napi);
+ }
+}
static void stmmac_dma_interrupt(struct stmmac_priv *priv)
{
int status;
status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
- if (likely(status == handle_tx_rx))
- _stmmac_schedule(priv);
-
- else if (unlikely(status == tx_hard_error_bump_tc)) {
+ if (likely(status & handle_rx)) {
+ priv->xstats.rx_normal_irq_n++;
+ stmmac_rx_schedule(priv);
+ }
+ if (likely(status & handle_tx)) {
+ priv->xstats.tx_normal_irq_n++;
+ stmmac_tx(priv);
+ } else if (unlikely(status & tx_hard_error_bump_tc)) {
/* Try to bump up the dma threshold on this failure */
if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
tc += 64;
@@ -1443,8 +1454,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget)
struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
int work_done = 0;
- priv->xstats.poll_n++;
- stmmac_tx(priv);
+ priv->xstats.rx_napi_poll++;
work_done = stmmac_rx(priv, budget);
if (work_done < budget) {
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 4/8 (V3)] stmmac: add Rx watchdog support to mitigate the DMA irqs
From: Giuseppe CAVALLARO @ 2012-09-10 7:38 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, davem, Giuseppe Cavallaro
In-Reply-To: <1347262689-21251-1-git-send-email-peppe.cavallaro@st.com>
GMAC devices newer than databook 3.40 has an embedded timer
that can be used for mitigating the number of interrupts.
So this patch adds this optimizations.
At any rate, the Rx watchdog can be disable (on bugged HW) by
passing from the platform the riwt_off field.
In this implementation the rx timer stored in the Reg9 is fixed
to the max value. Next step will be to tune it via ethtool.
V2: added a platform parameter to force to disable the rx-watchdog
for example on new core where it is bugged.
V3: do not disable NAPI when Rx watchdog is used.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 7 ++++
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 3 --
.../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 6 +++
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 36 +++++++++++++++----
include/linux/stmmac.h | 1 +
7 files changed, 45 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 1d6bd3e..63d4bad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -48,6 +48,10 @@
#define CHIP_DBG(fmt, args...) do { } while (0)
#endif
+/* Synopsys Core versions */
+#define DWMAC_CORE_3_40 0x34
+#define DWMAC_CORE_3_50 0x35
+
#undef FRAME_FILTER_DEBUG
/* #define FRAME_FILTER_DEBUG */
@@ -165,6 +169,7 @@ struct stmmac_extra_stats {
#define DMA_HW_FEAT_SAVLANINS 0x08000000 /* Source Addr or VLAN Insertion */
#define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY interface */
#define DEFAULT_DMA_PBL 8
+#define DEFAULT_DMA_RIWT 0xff /* Max RI Watchdog Timer count */
enum rx_frame_status { /* IPC status */
good_frame = 0,
@@ -301,6 +306,8 @@ struct stmmac_dma_ops {
struct stmmac_extra_stats *x);
/* If supported then get the optional core features */
unsigned int (*get_hw_feature) (void __iomem *ioaddr);
+ /* Program the HW RX Watchdog */
+ void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
};
struct stmmac_ops {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 0e4cace..7ad56af 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -230,8 +230,5 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
-/* Synopsys Core versions */
-#define DWMAC_CORE_3_40 0x34
-
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 0335000..e2c9431 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -174,6 +174,11 @@ static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
return readl(ioaddr + DMA_HW_FEATURE);
}
+static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt)
+{
+ writel(riwt, ioaddr + DMA_RX_WATCHDOG);
+}
+
const struct stmmac_dma_ops dwmac1000_dma_ops = {
.init = dwmac1000_dma_init,
.dump_regs = dwmac1000_dump_dma_regs,
@@ -187,4 +192,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
.stop_rx = dwmac_dma_stop_rx,
.dma_interrupt = dwmac_dma_interrupt,
.get_hw_feature = dwmac1000_get_hw_feature,
+ .rx_watchdog = dwmac1000_rx_watchdog,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index e49c9a0..4eeff5d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -35,7 +35,8 @@
#define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */
#define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */
#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */
-#define DMA_AXI_BUS_MODE 0x00001028 /* AXI Bus Mode */
+#define DMA_RX_WATCHDOG 0x00001024 /* Receive Int Watchdog Timer */
+#define DMA_AXI_BUS_MODE 0x00001028 /* AXI Bus Mode */
#define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */
#define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */
#define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 0f5ab28..6901e3c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -89,6 +89,7 @@ struct stmmac_priv {
int eee_active;
int tx_lpi_timer;
struct timer_list txtimer;
+ int use_riwt;
u32 tx_count_frames;
u32 tx_coal_frames;
u32 tx_coal_timer;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3df3c3b..8e610a1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -133,6 +133,7 @@ MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
#define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
+static int stmmac_rx(struct stmmac_priv *priv, int limit);
#ifdef CONFIG_STMMAC_DEBUG_FS
static int stmmac_init_fs(struct net_device *dev);
@@ -603,6 +604,8 @@ static void init_dma_desc_rings(struct net_device *dev)
priv->dirty_tx = 0;
priv->cur_tx = 0;
+ if (priv->use_riwt)
+ dis_ic = 1;
/* Clear the Rx/Tx descriptors */
priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic);
priv->hw->desc->init_tx_desc(priv->dma_tx, txsize);
@@ -812,7 +815,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
netif_wake_queue(priv->dev);
}
-static void stmmac_rx_schedule(struct stmmac_priv *priv)
+static void stmmac_rx_work(struct stmmac_priv *priv)
{
if (likely(napi_schedule_prep(&priv->napi))) {
stmmac_disable_irq(priv);
@@ -827,7 +830,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
if (likely(status & handle_rx)) {
priv->xstats.rx_normal_irq_n++;
- stmmac_rx_schedule(priv);
+ stmmac_rx_work(priv);
}
if (likely(status & handle_tx)) {
priv->xstats.tx_normal_irq_n++;
@@ -1115,7 +1118,14 @@ static int stmmac_open(struct net_device *dev)
stmmac_init_tx_coalesce(priv);
+ if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog))
+ /* Program RX Watchdog register to the default values
+ * FIXME: provide user value for RIWT
+ */
+ priv->hw->dma->rx_watchdog(priv->ioaddr, DEFAULT_DMA_RIWT);
+
napi_enable(&priv->napi);
+
skb_queue_head_init(&priv->rx_recycle);
netif_start_queue(dev);
@@ -1436,14 +1446,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
#endif
skb->protocol = eth_type_trans(skb, priv->dev);
- if (unlikely(!priv->plat->rx_coe)) {
- /* No RX COE for old mac10/100 devices */
+ if (unlikely(!priv->plat->rx_coe))
skb_checksum_none_assert(skb);
- netif_receive_skb(skb);
- } else {
+ else
skb->ip_summed = CHECKSUM_UNNECESSARY;
- napi_gro_receive(&priv->napi, skb);
- }
+
+ napi_gro_receive(&priv->napi, skb);
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
@@ -2013,6 +2021,15 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
+ /* Rx Watchdog is available in the COREs newer than the 3.40.
+ * In some case, for example on bugged HW this feature
+ * has to be disable and this can be done by passing the
+ * riwt_off field from the platform. */
+ if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
+ priv->use_riwt = 1;
+ pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
+ }
+
netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
spin_lock_init(&priv->lock);
@@ -2104,6 +2121,9 @@ int stmmac_suspend(struct net_device *ndev)
netif_device_detach(ndev);
netif_stop_queue(ndev);
+ if (priv->use_riwt)
+ dis_ic = 1;
+
napi_disable(&priv->napi);
/* Stop TX/RX DMA */
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index a1547ea..de5b2f8 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -104,6 +104,7 @@ struct plat_stmmacenet_data {
int bugged_jumbo;
int pmt;
int force_sf_dma_mode;
+ int riwt_off;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev);
--
1.7.4.4
^ permalink raw reply related
* [net-next.git 3/8 (V2)] stmmac: add the initial tx coalesce schema
From: Giuseppe CAVALLARO @ 2012-09-10 7:38 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, davem, Giuseppe Cavallaro
In-Reply-To: <1347262689-21251-1-git-send-email-peppe.cavallaro@st.com>
This patch adds a new schema used for mitigating the
number of transmit interrupts.
It is based on a sw timer and a threshold value.
The timer is used to periodically call the stmmac_tx
function that can be invoked by the ISR but only for
the descriptors where the interrupt on completion
field has been set. This is tuned by a threshold.
Next step is to add the ability to tune these coalesce
values by ethtool.
Till now I have put a default that showed a real gain
on all the platforms ARM/SH4 where I performed benchmarks.
V2: review the logic to manage the IC bit in the TDESC
that was bugged because it didn't take care about the
fragments. Also fix the tx_count_frames that has not to be
limited to TX DMA ring. Thanks to Ben Hutchings.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 8 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 4 +
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++++++--------
4 files changed, 69 insertions(+), 44 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index bd32fe6..1d6bd3e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -95,11 +95,13 @@ struct stmmac_extra_stats {
unsigned long threshold;
unsigned long tx_pkt_n;
unsigned long rx_pkt_n;
- unsigned long rx_napi_poll;
+ unsigned long normal_irq_n;
unsigned long rx_normal_irq_n;
+ unsigned long rx_napi_poll;
unsigned long tx_normal_irq_n;
- unsigned long sched_timer_n;
- unsigned long normal_irq_n;
+ unsigned long txtimer;
+ unsigned long tx_clean;
+ unsigned long tx_reset_ic_bit;
unsigned long mmc_tx_irq_n;
unsigned long mmc_rx_irq_n;
unsigned long mmc_rx_csum_offload_irq_n;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 9f35769..0f5ab28 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -88,6 +88,10 @@ struct stmmac_priv {
int eee_enabled;
int eee_active;
int tx_lpi_timer;
+ struct timer_list txtimer;
+ u32 tx_count_frames;
+ u32 tx_coal_frames;
+ u32 tx_coal_timer;
};
extern int phyaddr;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 505fe71..48ad0bc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -90,12 +90,13 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(threshold),
STMMAC_STAT(tx_pkt_n),
STMMAC_STAT(rx_pkt_n),
- STMMAC_STAT(rx_napi_poll),
+ STMMAC_STAT(normal_irq_n),
STMMAC_STAT(rx_normal_irq_n),
+ STMMAC_STAT(rx_napi_poll),
STMMAC_STAT(tx_normal_irq_n),
- STMMAC_STAT(sched_timer_n),
- STMMAC_STAT(normal_irq_n),
- STMMAC_STAT(normal_irq_n),
+ STMMAC_STAT(txtimer),
+ STMMAC_STAT(tx_clean),
+ STMMAC_STAT(tx_reset_ic_bit),
STMMAC_STAT(mmc_tx_irq_n),
STMMAC_STAT(mmc_rx_irq_n),
STMMAC_STAT(mmc_rx_csum_offload_irq_n),
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8e1e53e..3df3c3b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -77,6 +77,8 @@
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
#define JUMBO_LEN 9000
+#define STMMAC_TX_TM 40000
+#define STMMAC_TX_MAX_FRAMES 32 /* Max coalesced frame */
/* Module parameters */
#define TX_TIMEO 5000 /* default 5 seconds */
@@ -695,8 +697,11 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
static void stmmac_tx(struct stmmac_priv *priv)
{
unsigned int txsize = priv->dma_tx_size;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
- spin_lock(&priv->tx_lock);
+ priv->xstats.tx_clean++;
while (priv->dirty_tx != priv->cur_tx) {
int last;
@@ -741,7 +746,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
skb_recycle_check(skb, priv->dma_buf_sz))
__skb_queue_head(&priv->rx_recycle, skb);
else
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
priv->tx_skbuff[entry] = NULL;
}
@@ -765,7 +770,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
stmmac_enable_eee_mode(priv);
mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
}
- spin_unlock(&priv->tx_lock);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
}
static inline void stmmac_enable_irq(struct stmmac_priv *priv)
@@ -778,29 +783,12 @@ static inline void stmmac_disable_irq(struct stmmac_priv *priv)
priv->hw->dma->disable_dma_irq(priv->ioaddr);
}
-static int stmmac_has_work(struct stmmac_priv *priv)
+static void stmmac_txtimer(unsigned long data)
{
- unsigned int has_work = 0;
- int rxret, tx_work = 0;
-
- rxret = priv->hw->desc->get_rx_owner(priv->dma_rx +
- (priv->cur_rx % priv->dma_rx_size));
-
- if (priv->dirty_tx != priv->cur_tx)
- tx_work = 1;
-
- if (likely(!rxret || tx_work))
- has_work = 1;
+ struct stmmac_priv *priv = (struct stmmac_priv *)data;
- return has_work;
-}
-
-static inline void _stmmac_schedule(struct stmmac_priv *priv)
-{
- if (likely(stmmac_has_work(priv))) {
- stmmac_disable_irq(priv);
- napi_schedule(&priv->napi);
- }
+ priv->xstats.txtimer++;
+ stmmac_tx(priv);
}
/**
@@ -824,7 +812,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
netif_wake_queue(priv->dev);
}
-static inline void stmmac_rx_schedule(struct stmmac_priv *priv)
+static void stmmac_rx_schedule(struct stmmac_priv *priv)
{
if (likely(napi_schedule_prep(&priv->napi))) {
stmmac_disable_irq(priv);
@@ -1001,6 +989,18 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
priv->dma_rx_phy);
}
+static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
+{
+ /* Set Tx coalesce parameters and timers */
+ priv->tx_coal_frames = STMMAC_TX_MAX_FRAMES;
+ priv->tx_coal_timer = jiffies + usecs_to_jiffies(STMMAC_TX_TM);
+ init_timer(&priv->txtimer);
+ priv->txtimer.expires = priv->tx_coal_timer;
+ priv->txtimer.data = (unsigned long)priv;
+ priv->txtimer.function = stmmac_txtimer;
+ add_timer(&priv->txtimer);
+}
+
/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
@@ -1113,6 +1113,8 @@ static int stmmac_open(struct net_device *dev)
priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
priv->eee_enabled = stmmac_eee_init(priv);
+ stmmac_init_tx_coalesce(priv);
+
napi_enable(&priv->napi);
skb_queue_head_init(&priv->rx_recycle);
netif_start_queue(dev);
@@ -1160,6 +1162,8 @@ static int stmmac_release(struct net_device *dev)
napi_disable(&priv->napi);
skb_queue_purge(&priv->rx_recycle);
+ del_timer_sync(&priv->txtimer);
+
/* Free the IRQ lines */
free_irq(dev->irq, dev);
if (priv->wol_irq != dev->irq)
@@ -1202,6 +1206,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
int nfrags = skb_shinfo(skb)->nr_frags;
struct dma_desc *desc, *first;
unsigned int nopaged_len = skb_headlen(skb);
+ unsigned long flags;
if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
if (!netif_queue_stopped(dev)) {
@@ -1213,7 +1218,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- spin_lock(&priv->tx_lock);
+ spin_lock_irqsave(&priv->tx_lock, flags);
if (priv->tx_path_in_lpi_mode)
stmmac_disable_eee_mode(priv);
@@ -1222,11 +1227,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef STMMAC_XMIT_DEBUG
if ((skb->len > ETH_FRAME_LEN) || nfrags)
- pr_info("stmmac xmit:\n"
- "\tskb addr %p - len: %d - nopaged_len: %d\n"
- "\tn_frags: %d - ip_summed: %d - %s gso\n",
- skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
- !skb_is_gso(skb) ? "isn't" : "is");
+ pr_debug("stmmac xmit: [entry %d]\n"
+ "\tskb addr %p - len: %d - nopaged_len: %d\n"
+ "\tn_frags: %d - ip_summed: %d - %s gso\n"
+ "\ttx_count_frames %d\n", entry,
+ skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
+ !skb_is_gso(skb) ? "isn't" : "is",
+ priv->tx_count_frames);
#endif
csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
@@ -1236,9 +1243,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef STMMAC_XMIT_DEBUG
if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
- pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
- "\t\tn_frags: %d, ip_summed: %d\n",
- skb->len, nopaged_len, nfrags, skb->ip_summed);
+ pr_debug("\tskb len: %d, nopaged_len: %d,\n"
+ "\t\tn_frags: %d, ip_summed: %d\n",
+ skb->len, nopaged_len, nfrags, skb->ip_summed);
#endif
priv->tx_skbuff[entry] = skb;
@@ -1269,10 +1276,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
wmb();
}
- /* Interrupt on completition only for the latest segment */
+ /* Finalize the latest segment. */
priv->hw->desc->close_tx_desc(desc);
wmb();
+ /* According to the coalesce parameter the IC bit for the latest
+ * segment could be reset and the timer re-started to invoke the
+ * stmmac_tx function. This approach takes care about the fragments. */
+ priv->tx_count_frames += nfrags + 1;
+ if (priv->tx_coal_frames > priv->tx_count_frames) {
+ priv->hw->desc->clear_tx_ic(desc);
+ priv->xstats.tx_reset_ic_bit++;
+ TX_DBG("\t[entry %d]: tx_count_frames %d\n", entry,
+ priv->tx_count_frames);
+ mod_timer(&priv->txtimer, priv->tx_coal_timer);
+ } else
+ priv->tx_count_frames = 0;
/* To avoid raise condition */
priv->hw->desc->set_tx_owner(first);
@@ -1302,7 +1321,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
priv->hw->dma->enable_dma_transmission(priv->ioaddr);
- spin_unlock(&priv->tx_lock);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
return NETDEV_TX_OK;
}
@@ -1447,7 +1466,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
* all interfaces.
* Description :
* This function implements the the reception process.
- * Also it runs the TX completion thread
*/
static int stmmac_poll(struct napi_struct *napi, int budget)
{
--
1.7.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox