Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] stmmac ethernet: remove cut & paste code
From: Pavel Machek @ 2016-11-24 21:44 UTC (permalink / raw)
  To: Joe Perches
  Cc: peppe.cavallaro, netdev, kernel list, ezequiel, sonic.zhang,
	fabrice.gasnier
In-Reply-To: <1480017925.19726.13.camel@perches.com>

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

On Thu 2016-11-24 12:05:25, Joe Perches wrote:
> On Thu, 2016-11-24 at 12:05 +0100, Pavel Machek wrote:
> > Remove duplicate code from _tx routines.
> 
> trivia:
> 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> []
> > @@ -1960,6 +1960,38 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
> >  	}
> >  }
> >  
> > +static void stmmac_xmit_common(struct sk_buff *skb, struct net_device *dev, int nfrags, struct dma_desc *desc)
> > +{
> > +	struct stmmac_priv *priv = netdev_priv(dev);
> > +
> > +	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
> > +		if (netif_msg_hw(priv))
> > +			pr_debug("%s: stop transmitted packets\n", __func__);
> 
> 		netif_dbg(priv, hw, dev, "%s: stop transmitted packets\n",
> 			  __func__);

Not now. Modifying the code while de-duplicating would be bad idea.

(And it looks like the driver has rather more serious problems than
printk style...)

Thanks,									
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply

* Re: [PATCH net-next] tcp: enhance tcp_collapse_retrans() with skb_shift()
From: Eric Dumazet @ 2016-11-24 21:42 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, ncardwell, ycheng
In-Reply-To: <20161124.154208.1594403474025352610.davem@davemloft.net>

On Thu, 2016-11-24 at 15:42 -0500, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Tue, 22 Nov 2016 10:57:33 -0800
> 
> > David, patch is marked 'Superseded' in
> > https://patchwork.ozlabs.org/patch/695264/
> > 
> > Not sure what this means exactly ?
> > Did I miss a mail/feedback/something ?
> 
> I must have mistakenly marked it that way, sorry.
> 
> Applied to net-next, thanks Eric.

Thanks David !

^ permalink raw reply

* Re: stmmac ethernet in kernel 4.9-rc6: coalescing related pauses.
From: Pavel Machek @ 2016-11-24 21:25 UTC (permalink / raw)
  To: David Miller; +Cc: peppe.cavallaro, netdev, linux-kernel
In-Reply-To: <20161124.110416.198867271899443489.davem@davemloft.net>

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

Hi!

> >> I'm debugging strange delays during transmit in stmmac driver. They
> >> seem to be present in 4.4 kernel (and older kernels, too). Workload is
> >> burst of udp packets being sent, pause, burst of udp packets, ...
...
> > 4.9-rc6 still has the delays. With the
> > 
> > #define STMMAC_COAL_TX_TIMER 1000
> > #define STMMAC_TX_MAX_FRAMES 2
> > 
> > settings, delays go away, and driver still works. (It fails fairly
> > fast in 4.4). Good news. But the question still is: what is going on
> > there?
> 
> 256 packets looks way too large for being a trigger for aborting the
> TX coalescing timer.
> 
> Looking more deeply into this, the driver is using non-highres timers
> to implement the TX coalescing.  This simply cannot work.
> 
> 1 HZ, which is the lowest granularity of non-highres timers in the
> kernel, is variable as well as already too large of a delay for
> effective TX coalescing.
> 
> I seriously think that the TX coalescing support should be ripped out
> or disabled entirely until it is implemented properly in this
> driver.

Ok, I'd disable coalescing, but could not figure it out till. What is
generic way to do that?

It seems only thing stmmac_tx_timer() does is calling
stmmac_tx_clean(), which reclaims tx_skbuff[] entries. It should be
possible to do that explicitely, without delay, but it stops working
completely if I attempt to do that.

On a side note, stmmac_poll() does stmmac_enable_dma_irq() while
stmmac_dma_interrupt() disables interrupts. But I don't see any
protection between the two, so IMO it could race and we'd end up
without polling or interrupts...

Thanks and best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply

* Re: pull request: bluetooth 2016-11-23
From: David Miller @ 2016-11-24 21:24 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, netdev
In-Reply-To: <20161123072912.GA3538@x1c>

From: Johan Hedberg <johan.hedberg@gmail.com>
Date: Wed, 23 Nov 2016 09:29:12 +0200

> Sorry about the late pull request for 4.9, but we have one more
> important Bluetooth patch that should make it to the release. It fixes
> connection creation for Bluetooth LE controllers that do not have a
> public address (only a random one).
> 
> Please let me know if there are any issues pulling. Thanks.

Pulled, thanks.

^ permalink raw reply

* Re: [PATCH v2] net: dsa: mv88e6xxx: add MV88E6097 switch
From: Stefan Eichenberger @ 2016-11-24 21:14 UTC (permalink / raw)
  To: David Miller
  Cc: andrew, vivien.didelot, f.fainelli, netdev, stefan.eichenberger
In-Reply-To: <20161124.152921.1374820040756654804.davem@davemloft.net>

Hi David

On Thu, Nov 24, 2016 at 03:29:21PM -0500, David Miller wrote:
> From: Stefan Eichenberger <eichest@gmail.com>
> Date: Tue, 22 Nov 2016 17:47:21 +0100
> 
> > Add support for the MV88E6097 switch. The change was tested on an Armada
> > based platform with a MV88E6097 switch.
> > 
> > Signed-off-by: Stefan Eichenberger <stefan.eichenberger@netmodule.com>
> 
> Applied to net-next, thanks.

I'm afraid this is the wrong patch version, Andrew and Vivien had some
findings, this would be the correct patch series that include all
necessary changes:
http://marc.info/?l=linux-netdev&m=147993563215981&w=2
http://marc.info/?l=linux-netdev&m=147993580216027&w=2
http://marc.info/?l=linux-netdev&m=147993607616121&w=2

Sorry for the confusion, I did a mess
Stefan

^ permalink raw reply

* Re: [PATCH net-next] tuntap: remove unnecessary sk_receive_queue length check during xmit
From: David Miller @ 2016-11-24 21:07 UTC (permalink / raw)
  To: jasowang; +Cc: netdev, linux-kernel, mst
In-Reply-To: <1479868009-14157-1-git-send-email-jasowang@redhat.com>

From: Jason Wang <jasowang@redhat.com>
Date: Wed, 23 Nov 2016 10:26:49 +0800

> After commit 1576d9860599 ("tun: switch to use skb array for tx"),
> sk_receive_queue was not used any more. So remove the uncessary
> sk_receive_queue length check during xmit.
> 
> Signed-off-by: Jason Wang <jasowang@redhat.com>

Good catch, applied, thanks Jason.

^ permalink raw reply

* Re: [PATCH net 1/1] net sched filters: fix filter handle ID in tfilter_notify_chain()
From: David Miller @ 2016-11-24 21:06 UTC (permalink / raw)
  To: mrv; +Cc: netdev, jhs, xiyou.wangcong, daniel
In-Reply-To: <1479866224-12285-1-git-send-email-mrv@mojatatu.com>

From: Roman Mashak <mrv@mojatatu.com>
Date: Tue, 22 Nov 2016 20:57:04 -0500

> Should pass valid filter handle, not the netlink flags.
> 
> Fixes: 30a391a13ab92 ("net sched filters: pass netlink message flags in event notification")
> Signed-off-by: Roman Mashak <mrv@mojatatu.com>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next 2/2] samples/bpf: fix bpf loader
From: David Miller @ 2016-11-24 21:05 UTC (permalink / raw)
  To: ast; +Cc: daniel, netdev
In-Reply-To: <1479862329-2361912-2-git-send-email-ast@fb.com>

From: Alexei Starovoitov <ast@fb.com>
Date: Tue, 22 Nov 2016 16:52:09 -0800

> llvm can emit relocations into sections other than program code
> (like debug info sections). Ignore them during parsing of elf file
> 
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>

Applied.

^ permalink raw reply

* Re: [PATCH net-next 1/2] samples/bpf: fix sockex2 example
From: David Miller @ 2016-11-24 21:05 UTC (permalink / raw)
  To: ast; +Cc: daniel, netdev
In-Reply-To: <1479862329-2361912-1-git-send-email-ast@fb.com>

From: Alexei Starovoitov <ast@fb.com>
Date: Tue, 22 Nov 2016 16:52:08 -0800

> since llvm commit "Do not expand UNDEF SDNode during insn selection lowering"
> llvm will generate code that uses uninitialized registers for cases
> where C code is actually uses uninitialized data.
> So this sockex2 example is technically broken.
> Fix it by initializing on the stack variable fully.
> Also increase verifier buffer limit, since verifier output
> may not fit in 64k for this sockex2 code depending on llvm version.
> 
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] mlx4: reorganize struct mlx4_en_tx_ring
From: David Miller @ 2016-11-24 21:04 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, tariqt
In-Reply-To: <1479858970.8455.461.camel@edumazet-glaptop3.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 22 Nov 2016 15:56:10 -0800

> From: Eric Dumazet <edumazet@google.com>
> 
> Goal is to reorganize this critical structure to increase performance.
> 
> ndo_start_xmit() should only dirty one cache line, and access as few
> cache lines as possible.
> 
> Add sp_ (Slow Path) prefix to fields that are not used in fast path,
> to make clear what is going on.
> 
> After this patch pahole reports something much better, as all
> ndo_start_xmit() needed fields are packed into two cache lines instead
> of seven or eight
 ...
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH net-next v2] ethtool: Protect {get,set}_phy_tunable with PHY device mutex
From: David Miller @ 2016-11-24 21:02 UTC (permalink / raw)
  To: f.fainelli
  Cc: netdev, bcm-kernel-feedback-list, andrew, allan.nielsen,
	raju.lakkaraju, vivien.didelot
In-Reply-To: <20161122215531.18212-1-f.fainelli@gmail.com>

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Tue, 22 Nov 2016 13:55:31 -0800

> PHY drivers should be able to rely on the caller of {get,set}_tunable to
> have acquired the PHY device mutex, in order to both serialize against
> concurrent calls of these functions, but also against PHY state machine
> changes. All ethtool PHY-level functions do this, except
> {get,set}_tunable, so we make them consistent here as well.
> 
> We need to update the Microsemi PHY driver in the same commit to avoid
> introducing either deadlocks, or lack of proper locking.
> 
> Fixes: 968ad9da7e0e ("ethtool: Implements ETHTOOL_PHY_GTUNABLE/ETHTOOL_PHY_STUNABLE")
> Fixes: 310d9ad57ae0 ("net: phy: Add downshift get/set support in Microsemi PHYs driver")
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> Changes in v2:
> 
> - also patch drivers/net/phy/mscc.c in the same commit

Applied, thanks Florian.

^ permalink raw reply

* Re: [PATCH net-next V2 0/7] Mellanox 100G mlx5 SRIOV switchdev update
From: David Miller @ 2016-11-24 21:01 UTC (permalink / raw)
  To: saeedm; +Cc: netdev, ogerlitz, roid
In-Reply-To: <1479849000-14902-1-git-send-email-saeedm@mellanox.com>

From: Saeed Mahameed <saeedm@mellanox.com>
Date: Tue, 22 Nov 2016 23:09:53 +0200

> This series from Roi and Or further enhances the new SRIOV switchdev
> mode.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next 0/5] net: phy: broadcom: Wirespeed/downshift support
From: David Miller @ 2016-11-24 20:54 UTC (permalink / raw)
  To: f.fainelli
  Cc: netdev, bcm-kernel-feedback-list, andrew, allan.nielsen,
	raju.lakkaraju, vivien.didelot
In-Reply-To: <20161122194058.29820-1-f.fainelli@gmail.com>

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Tue, 22 Nov 2016 11:40:53 -0800

> This patch series adds support for the Broadcom Wirespeed, aka downsfhit feature
> utilizing the recently added ethtool PHY tunables.
> 
> Tested with two Gigabit link partners with a 4-wire cable having only 2 pairs
> connected.
> 
> Last patch in the series is a fix that was required for testing, which should
> make it to -stable, which I can submit separate against net if you prefer David.

Series applied to net-next, patch #5 applied also to 'net' and queued up for
-stable.

Thanks.

^ permalink raw reply

* Re: [PATCH net-next] tcp: enhance tcp_collapse_retrans() with skb_shift()
From: David Miller @ 2016-11-24 20:42 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, ncardwell, ycheng
In-Reply-To: <1479841053.8455.441.camel@edumazet-glaptop3.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 22 Nov 2016 10:57:33 -0800

> David, patch is marked 'Superseded' in
> https://patchwork.ozlabs.org/patch/695264/
> 
> Not sure what this means exactly ?
> Did I miss a mail/feedback/something ?

I must have mistakenly marked it that way, sorry.

Applied to net-next, thanks Eric.

^ permalink raw reply

* Re: [PATCH net] bnxt: do not busy-poll when link is down
From: David Miller @ 2016-11-24 20:40 UTC (permalink / raw)
  To: gospo; +Cc: netdev, michael.chan
In-Reply-To: <1479838448-44877-1-git-send-email-gospo@broadcom.com>

From: Andy Gospodarek <gospo@broadcom.com>
Date: Tue, 22 Nov 2016 13:14:08 -0500

> When busy polling while a link is down (during a link-flap test), TX
> timeouts were observed as well as the following messages in the ring
> buffer:
> 
> bnxt_en 0008:01:00.2 enP8p1s0f2d2: Resp cmpl intr err msg: 0x51
> bnxt_en 0008:01:00.2 enP8p1s0f2d2: hwrm_ring_free tx failed. rc:-1
> bnxt_en 0008:01:00.2 enP8p1s0f2d2: Resp cmpl intr err msg: 0x51
> bnxt_en 0008:01:00.2 enP8p1s0f2d2: hwrm_ring_free rx failed. rc:-1
> 
> These were resolved by checking for link status and returning if link
> was not up.
> 
> Signed-off-by: Andy Gospodarek <gospo@broadcom.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>
> Tested-by: Rob Miller <rob.miller@broadcom.com>

Applied.

^ permalink raw reply

* Re: [PATCH 0/3] virtio/vringh: kill off ACCESS_ONCE()
From: Michael S. Tsirkin @ 2016-11-24 20:36 UTC (permalink / raw)
  To: Mark Rutland
  Cc: dave, kvm, dbueso, netdev, linux-kernel, virtualization, paulmck,
	dvyukov
In-Reply-To: <1479983114-17190-1-git-send-email-mark.rutland@arm.com>

On Thu, Nov 24, 2016 at 10:25:11AM +0000, Mark Rutland wrote:
> For several reasons, it would be beneficial to kill off ACCESS_ONCE()
> tree-wide, in favour of {READ,WRITE}_ONCE(). These work with aggregate types,
> more obviously document their intended behaviour, and are necessary for tools
> like KTSAN to work correctly (as otherwise reads and writes cannot be
> instrumented separately).
> 
> While it's possible to script the bulk of this tree-wide conversion, some cases
> such as the virtio code, require some manual intervention. This series moves
> the virtio and vringh code over to {READ,WRITE}_ONCE(), in the process fixing a
> bug in the virtio headers.
> 
> Thanks,
> Mark.

I don't have a problem with this specific patchset.

Though I really question the whole _ONCE APIs esp with
aggregate types - these seem to generate a memcpy and
an 8-byte read/writes sometimes, and I'm pretty sure this simply
can't be read/written at once on all architectures.

So I worry it's kind of like volatile in this respect,
too easy to overuse.


> Mark Rutland (3):
>   tools/virtio: fix READ_ONCE()
>   vringh: kill off ACCESS_ONCE()
>   tools/virtio: use {READ,WRITE}_ONCE() in uaccess.h
> 
>  drivers/vhost/vringh.c        | 5 +++--
>  tools/virtio/linux/compiler.h | 2 +-
>  tools/virtio/linux/uaccess.h  | 9 +++++----
>  3 files changed, 9 insertions(+), 7 deletions(-)
> 
> -- 
> 2.7.4

^ permalink raw reply

* RE: [PATCH v9 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
From: Levy, Amir (Jer) @ 2016-11-24 20:35 UTC (permalink / raw)
  To: Simon Guinot
  Cc: gregkh@linuxfoundation.org, andreas.noever@gmail.com,
	bhelgaas@google.com, corbet@lwn.net, linux-kernel@vger.kernel.org,
	linux-pci@vger.kernel.org, netdev@vger.kernel.org,
	linux-doc@vger.kernel.org, mario_limonciello@dell.com,
	thunderbolt-linux, Westerberg, Mika, Winkler, Tomas,
	Zhang, Xiong Y, remi.rerolle@seagate.com
In-Reply-To: <20161122172828.GB31492@kw.sim.vm.gnt>

On Tue, Nov 22 2016, 07:28 PM, Simon Guinot wrote:
> Hi Amir,
> 
> I tested the thunderbolt-icm driver (v9 series) on an Gigabyte 
> motherboard
> (Z170X-UD5 TH-CF) with a Thunderbolt 3 controller (Alpine Ridge 4C).
> 
> I can see that the network interface is well created when the 
> motherboard is connected to a MacBook Pro (Thunderbolt 2 or 3).
> 
> And here are the TCP bandwidths measured using the iperf3 benchmark:

AFAIK, in UD5, Thunderbolt 3 is installed on 4 lanes of PCI Express Gen 3,
which is good for performance.

> 
> - MacBook Pro Thunderbolt 2: 8.46Gbits/sec
> - MacBook Pro Thunderbolt 3: 11.8Gbits/sec
> 
> Are this results consistent with your expectations ?

Thunderbolt 2 - yes,
Thunderbolt 3 - we didn't check the bandwidth with MacBook Pro Thunderbolt 3 yet.
The bandwidth in Linux<->Linux and Linux<->Windows setups with Thunderbolt 3
is around 15G (one direction).

> 
> From the MacOS system interface on the MacBook Pro Thunderbolt 3, I 
> noticed that the interface appears as dual lane (2x 20Gb/sec). But 
> when two MacBook Pro are connected together, the interface appears as 
> single lane (1x 40Gb/sec). Is some lane bonding support missing in the 
> Linux implementation ?

At the moment the iCM doesn't lane bond the inter domain link.
This will be added in a future drop of the iCM once the networking BW will be such that requires the bonding.

> 
> Here are a couple of additional questions:
> 
> - When the network interface is created, there is no IP address
>   assigned (or negotiated ?) on the Linux side. But it is done on the
>   MacOS side. And in the Linux kernel logs I can also read the message:
>   "ready for ThunderboltIP negotiation". Is there something missing or
>   not working on the Linux side ? What is the correct way to configure
>   or negotiate the IP address. For my tests I did it manually...

This is not related to Thunderbolt, but to OS administration.
I usually use ZeroConf in any OS that support Thunderbolt Networking, but static IP also works.
"ready for ThunderboltIP negotiation" is an important part of the path establishment, but isn't related to IP address.

Thanks,
Amir

^ permalink raw reply

* Re: [PATCH net] udplite: call proper backlog handlers
From: David Miller @ 2016-11-24 20:32 UTC (permalink / raw)
  To: eric.dumazet
  Cc: edumazet, herbert, bcrl, willemb, andreyknvl, samanthakumar,
	netdev, linux-kernel
In-Reply-To: <1479834405.8455.437.camel@edumazet-glaptop3.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 22 Nov 2016 09:06:45 -0800

> From: Eric Dumazet <edumazet@google.com>
> 
> In commits 93821778def10 ("udp: Fix rcv socket locking") and
> f7ad74fef3af ("net/ipv6/udp: UDP encapsulation: break backlog_rcv into
> __udpv6_queue_rcv_skb") UDP backlog handlers were renamed, but UDPlite
> was forgotten.
> 
> This leads to crashes if UDPlite header is pulled twice, which happens
> starting from commit e6afc8ace6dd ("udp: remove headers from UDP packets
> before queueing")
> 
> Bug found by syzkaller team, thanks a lot guys !
> 
> Note that backlog use in UDP/UDPlite is scheduled to be removed starting
> from linux-4.10, so this patch is only needed up to linux-4.9
> 
> Fixes: 93821778def1 ("udp: Fix rcv socket locking")
> Fixes: f7ad74fef3af ("net/ipv6/udp: UDP encapsulation: break backlog_rcv into __udpv6_queue_rcv_skb")
> Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing")
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reported-by: Andrey Konovalov <andreyknvl@google.com>

Applied and queued up for -stable, thanks Eric.

^ permalink raw reply

* Re: [PATCH v2] net: dsa: mv88e6xxx: add MV88E6097 switch
From: David Miller @ 2016-11-24 20:29 UTC (permalink / raw)
  To: eichest; +Cc: andrew, vivien.didelot, f.fainelli, netdev, stefan.eichenberger
In-Reply-To: <20161122164721.4103-1-stefan.eichenberger@netmodule.com>

From: Stefan Eichenberger <eichest@gmail.com>
Date: Tue, 22 Nov 2016 17:47:21 +0100

> Add support for the MV88E6097 switch. The change was tested on an Armada
> based platform with a MV88E6097 switch.
> 
> Signed-off-by: Stefan Eichenberger <stefan.eichenberger@netmodule.com>

Applied to net-next, thanks.

^ permalink raw reply

* Re: [PATCH net-next] net/sched: cls_flower: verify root pointer before dereferncing it
From: David Miller @ 2016-11-24 20:25 UTC (permalink / raw)
  To: xiyou.wangcong
  Cc: jiri, daniel, roid, netdev, jiri, ogerlitz, cwang, john.fastabend
In-Reply-To: <CAM_iQpVTtqQRg7KgQbMQSxxVJRB8a46DGgfU52m=SxF1uYDFWQ@mail.gmail.com>

From: Cong Wang <xiyou.wangcong@gmail.com>
Date: Tue, 22 Nov 2016 11:28:37 -0800

> On Tue, Nov 22, 2016 at 8:11 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> Tue, Nov 22, 2016 at 05:04:11PM CET, daniel@iogearbox.net wrote:
>>>Hmm, I don't think we want to have such an additional test in fast
>>>path for each and every classifier. Can we think of ways to avoid that?
>>>
>>>My question is, since we unlink individual instances from such tp-internal
>>>lists through RCU and release the instance through call_rcu() as well as
>>>the head (tp->root) via kfree_rcu() eventually, against what are we protecting
>>>setting RCU_INIT_POINTER(tp->root, NULL) in ->destroy() callback? Something
>>>not respecting grace period?
>>
>> If you call tp->ops->destroy in call_rcu, you don't have to set tp->root
>> to null.
> 
> We do need to respect the grace period if we touch the globally visible
> data structure tp in tcf_destroy(). Therefore Roi's patch is not fixing the
> right place.

Another idea is to assign tp->root to a dummy static cls_fl_head object,
instead of NULL, which we just make sure has an ht.elems value of zero.

This avoids having to touch the fast path and also avoids all of these
complicated changes being discussed wrt. doing things in call_rcu_bh()
or whatever.

^ permalink raw reply

* [RFC PATCH net-next] ipv6: implement consistent hashing for equal-cost multipath routing
From: David Lebrun @ 2016-11-24 19:59 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun

When multiple nexthops are available for a given route, the routing engine
chooses a nexthop by computing the flow hash through get_hash_from_flowi6
and by taking that value modulo the number of nexthops. The resulting value
indexes the nexthop to select. This method causes issues when a new nexthop
is added or one is removed (e.g. link failure). In that case, the number
of nexthops changes and potentially all the flows get re-routed to another
nexthop.

This patch implements a consistent hash method to select the nexthop in
case of ECMP. The idea is to generate N random numbers (__u32) for each
nexthop, where N is configurable. In order to select a nexthop, we find the
number that is directly higher than the flow hash (which is also __u32).
The nexthop associated to the number is then selected. The lookup method
performs a binary search over the sorted array of numbers, which yields a
time complexity of O(log n), where n is the number of nexthops times the
number of random values generated for each number.

This feature can be enabled through the CONFIG_IPV6_MULTIPATH_CONSISTENT
option and the number of random values generated for each nexthop is
defined through CONFIG_IPV6_MPCONSIST_BUCKETSIZE.

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
 include/net/ip6_fib.h |  20 ++++
 net/ipv6/Kconfig      |  26 +++++
 net/ipv6/Makefile     |   1 +
 net/ipv6/ip6_ecmp.c   | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++
 net/ipv6/ip6_fib.c    |  18 ++++
 net/ipv6/route.c      |  56 +++++++++++
 6 files changed, 384 insertions(+)
 create mode 100644 net/ipv6/ip6_ecmp.c

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index a74e2aa..e22417d 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -93,6 +93,16 @@ struct rt6key {
 
 struct fib6_table;
 
+struct rt6_multi_nh {
+	__u32		key;
+	struct rt6_info *nh;
+};
+
+struct rt6_multi_map {
+	struct rt6_multi_nh	*nhs;
+	unsigned int		size;
+};
+
 struct rt6_info {
 	struct dst_entry		dst;
 
@@ -113,6 +123,9 @@ struct rt6_info {
 	 */
 	struct list_head		rt6i_siblings;
 	unsigned int			rt6i_nsiblings;
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+	struct rt6_multi_map		*rt6i_nh_map;
+#endif
 
 	atomic_t			rt6i_ref;
 
@@ -302,4 +315,11 @@ static inline void              fib6_rules_cleanup(void)
 	return ;
 }
 #endif
+
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+int fib6_mp_shrink(struct rt6_info *sref, struct rt6_info *rt);
+int fib6_mp_extend(struct rt6_info *rt, struct rt6_multi_map *nh_map);
+void fib6_mp_free(struct rt6_info *rt);
+#endif
+
 #endif
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index ec1267e..ebfae0d 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -324,4 +324,30 @@ config IPV6_SEG6_HMAC
 
 	  If unsure, say N.
 
+config IPV6_MULTIPATH_CONSISTENT
+	bool "IPv6: enable consistent hashing for ECMP"
+	depends on IPV6
+	---help---
+	  Enable consistent hashing for Equal-Cost Multi-Path (ECMP)
+	  route selection. By default, the nexthop is selected by taking
+	  the flow hash modulo the number of nexthops. When a nexthop is
+	  added or removed (e.g. link failure), all flows might change to
+	  a different nexthop as the modulo changes. Enabling this option
+	  allows to ensure that when a nexthop is removed, only the affected
+	  flows are assigned to another nexthop, and they are balanced equally
+	  across the remaining nexthops. When a nexthop is added, only a subset
+	  of the flows are assigned to it. The lookup performance is O(log n)
+	  where n is the number of nexthops times CONFIG_IPV6_MPCONSIST_BUCKETSIZE.
+
+	  If unsure, say N.
+
+config IPV6_MPCONSIST_BUCKETSIZE
+	int "IPv6: bucket size for ECMP consistent hashing"
+	default 10
+	depends on IPV6_MULTIPATH_CONSISTENT
+	---help---
+	  Define the number of hash entries generated for each ECMP nexthop.
+	  A higher value increases the uniform distribution of flows across
+	  nexthops, but also increases lookup performances logarithmically.
+
 endif # IPV6
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index a9e9fec..6481c5d 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -25,6 +25,7 @@ ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
 ipv6-$(CONFIG_NETLABEL) += calipso.o
 ipv6-$(CONFIG_IPV6_SEG6_LWTUNNEL) += seg6_iptunnel.o
 ipv6-$(CONFIG_IPV6_SEG6_HMAC) += seg6_hmac.o
+ipv6-$(CONFIG_IPV6_MULTIPATH_CONSISTENT) += ip6_ecmp.o
 
 ipv6-objs += $(ipv6-y)
 
diff --git a/net/ipv6/ip6_ecmp.c b/net/ipv6/ip6_ecmp.c
new file mode 100644
index 0000000..799a328
--- /dev/null
+++ b/net/ipv6/ip6_ecmp.c
@@ -0,0 +1,263 @@
+/*
+ * IPv6 Equal-Cost Multi-Path
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+
+ *  This program is free software; you can redistribute it and/or
+ *	  modify it under the terms of the GNU General Public License
+ *	  as published by the Free Software Foundation; either version
+ *	  2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/net.h>
+#include <linux/route.h>
+#include <linux/netdevice.h>
+#include <linux/in6.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include <net/ipv6.h>
+#include <net/ndisc.h>
+#include <net/addrconf.h>
+#include <net/lwtunnel.h>
+
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+
+static int mphash_bucket_size = CONFIG_IPV6_MPCONSIST_BUCKETSIZE;
+
+void fib6_mp_free(struct rt6_info *rt)
+{
+	struct rt6_multi_map *nh_map = rt->rt6i_nh_map;
+	struct rt6_info *sibling;
+
+	if (nh_map) {
+		list_for_each_entry(sibling, &rt->rt6i_siblings,
+				    rt6i_siblings) {
+			sibling->rt6i_nh_map = NULL;
+		}
+
+		rt->rt6i_nh_map = NULL;
+
+		kfree(nh_map->nhs);
+		kfree(nh_map);
+	}
+}
+
+static bool fib6_mp_key_exists(struct rt6_multi_nh *nhs, unsigned int size,
+			       __u32 key)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; i++) {
+		if (nhs[i].key == key)
+			return true;
+	}
+
+	return false;
+}
+
+static void fib6_mp_populate(struct rt6_multi_nh *nhs, unsigned int offset,
+			     unsigned int size, unsigned int fullsize,
+			     struct rt6_info *rt)
+{
+	unsigned int i;
+
+	for (i = offset; i < offset + size; i++) {
+		__u32 key;
+
+		do {
+			get_random_bytes(&key, sizeof(key));
+		} while (fib6_mp_key_exists(nhs, fullsize, key));
+
+		nhs[i].key = key;
+		nhs[i].nh = rt;
+	}
+}
+
+static int fib6_mp_update(struct rt6_info *rt, struct rt6_multi_nh *nhs,
+			  unsigned int size, bool check)
+{
+	struct rt6_multi_map *new_map;
+	struct rt6_info *sibling;
+
+	new_map = kmalloc(sizeof(*new_map), GFP_ATOMIC);
+	if (!new_map)
+		return -ENOMEM;
+
+	new_map->nhs = nhs;
+	new_map->size = size;
+
+	list_for_each_entry(sibling, &rt->rt6i_siblings, rt6i_siblings) {
+		if (check)
+			WARN_ON(sibling->rt6i_nh_map);
+		sibling->rt6i_nh_map = new_map;
+	}
+
+	rt->rt6i_nh_map = new_map;
+
+	return 0;
+}
+
+static void ___merge(struct rt6_multi_nh *nhs, struct rt6_multi_nh *helper,
+		     unsigned int low, unsigned int middle, unsigned int high)
+{
+	unsigned int i, j, k;
+
+	i = low;
+	j = middle + 1;
+	k = 0;
+
+	while (i <= middle || j <= high) {
+		if (i <= middle && j <= high) {
+			if (nhs[i].key < nhs[j].key)
+				helper[k++] = nhs[i++];
+			else
+				helper[k++] = nhs[j++];
+		} else if (i <= middle) {
+			helper[k++] = nhs[i++];
+		} else {
+			helper[k++] = nhs[j++];
+		}
+	}
+
+	for (i = 0; i < (high - low + 1); i++)
+		nhs[low + i] = helper[i];
+}
+
+static void ___mergesort(struct rt6_multi_nh *nhs, struct rt6_multi_nh *helper,
+			 unsigned int low, unsigned int high)
+{
+	unsigned int middle;
+
+	if (low > high)
+		return;
+
+	middle = ((low + high) / 2);
+
+	if (low < high) {
+		___mergesort(nhs, helper, low, middle);
+		___mergesort(nhs, helper, middle + 1, high);
+	}
+
+	___merge(nhs, helper, low, middle, high);
+}
+
+static int fib6_mp_sort(struct rt6_multi_nh *nhs, unsigned int size)
+{
+	struct rt6_multi_nh *helper;
+
+	helper = kmalloc_array(size, sizeof(*helper), GFP_ATOMIC);
+	if (!helper)
+		return -ENOMEM;
+
+	___mergesort(nhs, helper, 0, size - 1);
+	kfree(helper);
+
+	return 0;
+}
+
+int fib6_mp_extend(struct rt6_info *rt, struct rt6_multi_map *nh_map)
+{
+	struct rt6_multi_nh *tmp_nhs;
+	unsigned int size;
+	int err;
+
+	if (!nh_map) {
+		struct rt6_info *sibling;
+
+		size = mphash_bucket_size * 2;
+		tmp_nhs = kcalloc(size, sizeof(struct rt6_multi_nh),
+				  GFP_ATOMIC);
+		if (!tmp_nhs)
+			return -ENOMEM;
+
+		sibling = list_first_entry(&rt->rt6i_siblings, struct rt6_info,
+					   rt6i_siblings);
+
+		fib6_mp_populate(tmp_nhs, 0, mphash_bucket_size, size, sibling);
+
+		fib6_mp_populate(tmp_nhs, mphash_bucket_size,
+				 mphash_bucket_size, size, rt);
+
+		err = fib6_mp_sort(tmp_nhs, size);
+		if (err) {
+			kfree(tmp_nhs);
+			return err;
+		}
+
+		err = fib6_mp_update(rt, tmp_nhs, size, true);
+		if (err) {
+			kfree(tmp_nhs);
+			return err;
+		}
+
+		return 0;
+	}
+
+	size = nh_map->size + mphash_bucket_size;
+	tmp_nhs = __krealloc(nh_map->nhs, size * sizeof(*tmp_nhs), GFP_ATOMIC);
+	if (!tmp_nhs)
+		return -ENOMEM;
+
+	memset(tmp_nhs + nh_map->size, 0,
+	       mphash_bucket_size * sizeof(*tmp_nhs));
+
+	fib6_mp_populate(tmp_nhs, nh_map->size, mphash_bucket_size, size, rt);
+
+	err = fib6_mp_sort(tmp_nhs, size);
+	if (err) {
+		kfree(tmp_nhs);
+		return err;
+	}
+
+	err = fib6_mp_update(rt, tmp_nhs, size, false);
+	if (err) {
+		kfree(tmp_nhs);
+		return err;
+	}
+
+	if (tmp_nhs != nh_map->nhs)
+		kfree(nh_map->nhs);
+	kfree(nh_map);
+
+	return 0;
+}
+
+int fib6_mp_shrink(struct rt6_info *sref, struct rt6_info *rt)
+{
+	struct rt6_multi_map *nh_map = sref->rt6i_nh_map;
+	struct rt6_multi_nh *tmp_nhs;
+	unsigned int size, i, j;
+	int err;
+
+	WARN_ON(!nh_map);
+	if (!nh_map)
+		return -ENOENT;
+
+	size = nh_map->size - mphash_bucket_size;
+	tmp_nhs = kcalloc(size, sizeof(*tmp_nhs), GFP_ATOMIC);
+	if (!tmp_nhs)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < nh_map->size; i++) {
+		if (nh_map->nhs[i].nh != rt)
+			tmp_nhs[j++] = nh_map->nhs[i];
+	}
+
+	err = fib6_mp_update(sref, tmp_nhs, size, false);
+	if (err) {
+		kfree(tmp_nhs);
+		return err;
+	}
+
+	rt->rt6i_nh_map = NULL;
+	kfree(nh_map->nhs);
+	kfree(nh_map);
+
+	return 0;
+}
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index ef54852..ad5f645 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -837,6 +837,9 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 			}
 			sibling = sibling->dst.rt6_next;
 		}
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+		fib6_mp_extend(rt, sibling->rt6i_nh_map);
+#endif
 		/* For each sibling in the list, increment the counter of
 		 * siblings. BUG() if counters does not match, list of siblings
 		 * is broken!
@@ -900,6 +903,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 			fn->fn_flags |= RTN_RTINFO;
 		}
 		nsiblings = iter->rt6i_nsiblings;
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+		if (nsiblings)
+			fib6_mp_free(iter);
+#endif
 		fib6_purge_rt(iter, fn, info->nl_net);
 		rt6_release(iter);
 
@@ -1407,6 +1414,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
 
 	/* Remove this entry from other siblings */
 	if (rt->rt6i_nsiblings) {
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+		struct rt6_info *sref = list_first_entry(&rt->rt6i_siblings,
+							 struct rt6_info,
+							 rt6i_siblings);
+#endif
 		struct rt6_info *sibling, *next_sibling;
 
 		list_for_each_entry_safe(sibling, next_sibling,
@@ -1414,6 +1426,12 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
 			sibling->rt6i_nsiblings--;
 		rt->rt6i_nsiblings = 0;
 		list_del_init(&rt->rt6i_siblings);
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+		if (!sref->rt6i_nsiblings)
+			fib6_mp_free(sref);
+		else
+			fib6_mp_shrink(sref, rt);
+#endif
 	}
 
 	/* Adjust walkers */
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b317bb1..109f371 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -427,6 +427,60 @@ static bool rt6_check_expired(const struct rt6_info *rt)
 	return false;
 }
 
+#ifdef CONFIG_IPV6_MULTIPATH_CONSISTENT
+
+static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
+					     struct flowi6 *fl6, int oif,
+					     int strict)
+{
+	struct rt6_multi_map *nh_map = match->rt6i_nh_map;
+	__u32 hash = get_hash_from_flowi6(fl6);
+	unsigned int left, right, idx;
+	struct rt6_info *res = NULL;
+
+	WARN_ON(!nh_map);
+	if (!nh_map)
+		return match;
+
+	if (hash <= nh_map->nhs[0].key ||
+	    hash > nh_map->nhs[nh_map->size - 1].key) {
+		res = nh_map->nhs[0].nh;
+		goto skip_lookup;
+	}
+
+	left = 0;
+	right = nh_map->size - 1;
+
+	do {
+		struct rt6_multi_nh *nh1, *nh2;
+
+		idx = (left + right) / 2;
+		nh1 = &nh_map->nhs[idx];
+		nh2 = &nh_map->nhs[idx + 1];
+
+		if (hash < nh1->key && hash < nh2->key)
+			right = idx;
+		else if (hash > nh1->key && hash > nh2->key)
+			left = idx + 1;
+		else if (hash == nh1->key)
+			res = nh1->nh;
+		else
+			res = nh2->nh;
+	} while (left != right && !res);
+
+	WARN_ON(!res);
+	if (!res)
+		return match;
+
+skip_lookup:
+	if (rt6_score_route(res, oif, strict) < 0)
+		res = match;
+
+	return res;
+}
+
+#else
+
 /* Multipath route selection:
  *   Hash based function using packet header and flowlabel.
  * Adapted from fib_info_hashfn()
@@ -462,6 +516,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
 	return match;
 }
 
+#endif
+
 /*
  *	Route lookup. Any table->tb6_lock is implied.
  */
-- 
2.7.3

^ permalink raw reply related

* Re: [PATCH] stmmac ethernet: remove cut & paste code
From: Joe Perches @ 2016-11-24 20:05 UTC (permalink / raw)
  To: Pavel Machek, peppe.cavallaro, netdev, kernel list, ezequiel,
	sonic.zhang, fabrice.gasnier
In-Reply-To: <20161124110548.GB30723@amd>

On Thu, 2016-11-24 at 12:05 +0100, Pavel Machek wrote:
> Remove duplicate code from _tx routines.

trivia:

> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
[]
> @@ -1960,6 +1960,38 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
>  	}
>  }
>  
> +static void stmmac_xmit_common(struct sk_buff *skb, struct net_device *dev, int nfrags, struct dma_desc *desc)
> +{
> +	struct stmmac_priv *priv = netdev_priv(dev);
> +
> +	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
> +		if (netif_msg_hw(priv))
> +			pr_debug("%s: stop transmitted packets\n", __func__);

		netif_dbg(priv, hw, dev, "%s: stop transmitted packets\n",
			  __func__);

^ permalink raw reply

* Re: [PATCH net 1/2] r8152: fix the sw rx checksum is unavailable
From: Greg KH @ 2016-11-24 19:17 UTC (permalink / raw)
  To: Mark Lord
  Cc: David Miller, hayeswang, netdev, nic_swsd, linux-kernel,
	linux-usb
In-Reply-To: <9e8ff5b4-1c72-3106-7821-73484de133c2@pobox.com>

On Thu, Nov 24, 2016 at 02:10:36PM -0500, Mark Lord wrote:
> On 16-11-24 02:00 PM, Greg KH wrote:
> > On Thu, Nov 24, 2016 at 01:34:08PM -0500, Mark Lord wrote:
> >> One thought:  bulk data streams are byte streams, not packets.
> >> Scheduling on the USB bus can break up larger transfers across
> >> multiple in-kernel buffers.  A "real" URB buffer on USB2 is max 512 bytes.
> >> The driver is providing 16384-byte buffers, and assumes that data will
> >> never spill over from one such buffer to the next.
> >> Yet the observations here consistently show otherwise.
> > 
> > Wait, how do you know that data will not spill over?  What is making
> > that guarantee?  Will the USB device send a "zero packet" in order to
> > show that all of the "logical" data is now sent for this specific
> > endpoint?  Is there some sort of "framing" that the device does with the
> > USB data so that the driver "knows" where the end of packet is?
> 
> Exactly my point.
> 
> > Check the zero-packet stuff for this device, that's tripped up many a
> > USB driver writer over the years, myself included.
> 
> I haven't tripped over it myself, but only because we were careful
> to allow for such in the USB drivers I have worked on.
> 
> The r8152 driver just assumes it never happens.

Assumes what?  That the host will always consume data faster than the
device can create it?  If so, that sounds like your real problem
there...

good luck!

greg k-h

^ permalink raw reply

* Re: [PATCH net 1/2] r8152: fix the sw rx checksum is unavailable
From: Mark Lord @ 2016-11-24 19:10 UTC (permalink / raw)
  To: Greg KH; +Cc: David Miller, hayeswang, netdev, nic_swsd, linux-kernel,
	linux-usb
In-Reply-To: <20161124190055.GA3642@kroah.com>

On 16-11-24 02:00 PM, Greg KH wrote:
> On Thu, Nov 24, 2016 at 01:34:08PM -0500, Mark Lord wrote:
>> One thought:  bulk data streams are byte streams, not packets.
>> Scheduling on the USB bus can break up larger transfers across
>> multiple in-kernel buffers.  A "real" URB buffer on USB2 is max 512 bytes.
>> The driver is providing 16384-byte buffers, and assumes that data will
>> never spill over from one such buffer to the next.
>> Yet the observations here consistently show otherwise.
> 
> Wait, how do you know that data will not spill over?  What is making
> that guarantee?  Will the USB device send a "zero packet" in order to
> show that all of the "logical" data is now sent for this specific
> endpoint?  Is there some sort of "framing" that the device does with the
> USB data so that the driver "knows" where the end of packet is?

Exactly my point.

> Check the zero-packet stuff for this device, that's tripped up many a
> USB driver writer over the years, myself included.

I haven't tripped over it myself, but only because we were careful
to allow for such in the USB drivers I have worked on.

The r8152 driver just assumes it never happens.

^ permalink raw reply

* [PATCH 8/8] irda: w83977af_ir: Fix misindented block
From: Joe Perches @ 2016-11-24 19:10 UTC (permalink / raw)
  To: Samuel Ortiz; +Cc: Arnd Bergmann, netdev, linux-kernel
In-Reply-To: <cover.1480014088.git.joe@perches.com>

One indent level too many is too many.

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/net/irda/w83977af_ir.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 19b171af0e81..b865e93f01a0 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -517,15 +517,15 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
 
 		mtt = irda_get_mtt(skb);
 		pr_debug("%s: %ld, mtt=%d\n", __func__, jiffies, mtt);
-			if (mtt > 1000)
-				mdelay(mtt / 1000);
-			else if (mtt)
-				udelay(mtt);
+		if (mtt > 1000)
+			mdelay(mtt / 1000);
+		else if (mtt)
+			udelay(mtt);
 
-			/* Enable DMA interrupt */
-			switch_bank(iobase, SET0);
-			outb(ICR_EDMAI, iobase + ICR);
-			w83977af_dma_write(self, iobase);
+		/* Enable DMA interrupt */
+		switch_bank(iobase, SET0);
+		outb(ICR_EDMAI, iobase + ICR);
+		w83977af_dma_write(self, iobase);
 	} else {
 		self->tx_buff.data = self->tx_buff.head;
 		self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
-- 
2.10.0.rc2.1.g053435c

^ 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