linux/drivers/net/ethernet
Arthur Kiyanovski 1e5ae35072 net: ena: avoid unnecessary rearming of interrupt vector when busy-polling
For an overview of the race created by this patch goto synchronization
label.

In napi busy-poll mode, the kernel invokes the napi handler of the
device repeatedly to poll the NIC's receive queues. This process
repeats until a timeout, specific for each connection, is up.
By polling packets in busy-poll mode the user may gain lower latency
and higher throughput (since the kernel no longer waits for interrupts
to poll the queues) in expense of CPU usage.

Upon completing a napi routine, the driver checks whether
the routine was called by an interrupt handler. If so, the driver
re-enables interrupts for the device. This is needed since an
interrupt routine invocation disables future invocations until
explicitly re-enabled.

The driver avoids re-enabling the interrupts if they were not disabled
in the first place (e.g. if driver in busy mode).
Originally, the driver checked whether interrupt re-enabling is needed
by reading the 'ena_napi->unmask_interrupt' variable. This atomic
variable was set upon interrupt and cleared after re-enabling it.

In the 4.10 Linux version, the 'napi_complete_done' call was changed
so that it returns 'false' when device should not re-enable
interrupts, and 'true' otherwise. The change includes reading the
"NAPIF_STATE_IN_BUSY_POLL" flag to check if the napi call is in
busy-poll mode, and if so, return 'false'.
The driver was changed to re-enable interrupts according to this
routine's return value.
The Linux community rejected the use of the
'ena_napi->unmaunmask_interrupt' variable to determine whether
unmasking is needed, and urged to use napi_napi_complete_done()
return value solely.
See https://lore.kernel.org/patchwork/patch/741149/ for more details

As explained, a busy-poll session exists for a specified timeout
value, after which it exits the busy-poll mode and re-enters it later.
This leads to many invocations of the napi handler where
napi_complete_done() false indicates that interrupts should be
re-enabled.
This creates a bug in which the interrupts are re-enabled
unnecessarily.
To reproduce this bug:
    1) echo 50 | sudo tee /proc/sys/net/core/busy_poll
    2) echo 50 | sudo tee /proc/sys/net/core/busy_read
    3) Add counters that check whether
    'ena_unmask_interrupt(tx_ring, rx_ring);'
    is called without disabling the interrupts in the first
    place (i.e. with calling the interrupt routine
    ena_intr_msix_io())

Steps 1+2 enable busy-poll as the default mode for new connections.

The busy poll routine rearms the interrupts after every session by
design, and so we need to add an extra check that the interrupts were
masked in the first place.

synchronization:
This patch introduces a race between the interrupt handler
ena_intr_msix_io() and the napi routine ena_io_poll().
Some macros and instruction were added to prevent this race from leaving
the interrupts masked. The following specifies the different race
scenarios in this patch:

1) interrupt handler and napi routine run sequentially
    i) interrupt handler is called, sets 'interrupts_masked' flag and
	successfully schedules the napi handler via softirq.

    In this scenario the napi routine might not see the flag change
    for several reasons:
	a) The flag is stored in a register by the compiler. For this
	case the WRITE_ONCE macro which prevents this.
	b) The compiler might reorder the instruction. For this the
	smp_wmb() instruction was used which implies a compiler memory
	barrier.
	c) On archs with weak consistency model (like ARM64) the napi
	routine might be scheduled and start running before the flag
	STORE instruction is committed to cache/memory. To ensure this
	doesn't happen, the smp_wmb() instruction was added. It ensures
	that the flag set instruction is committed before scheduling
	napi.

    ii) compiler reorders the flag's value check in the 'if' with
    the flag set in the napi routine.

    This scenario is prevented by smp_rmb() call after the flag check.

2) interrupt handler and napi routine run in parallel (can happen when
busy poll routine invokes the napi handler)

    i) interrupt handler sets the flag in one core, while the napi
    routine reads it in another core.

    This scenario also is divided into two cases:
	a) napi_complete_done() doesn't finish running, in which case
	napi_sched() would just set NAPIF_STATE_MISSED and the napi
	routine would reschedule itself without changing the flag's value.

	b) napi_complete_done() finishes running. In this case the
	napi routine might override the flag's value.
	This doesn't present any rise since it later unmasks the
	interrupt vector.

Signed-off-by: Shay Agroskin <shayagr@amazon.com>
Signed-off-by: Arthur Kiyanovski <akiyano@amazon.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-21 15:59:04 -07:00
..
3com typhoon: use generic power management 2020-07-01 12:58:33 -07:00
8390 ne2k-pci: Use netif_msg_init to initialize msg_enable bits 2020-07-17 19:04:06 -07:00
adaptec starfire: use generic power management 2020-07-01 12:58:33 -07:00
aeroflex Replace HTTP links with HTTPS ones: GRETH 10/100/1G Ethernet MAC device driver 2020-07-07 15:44:27 -07:00
agere net: ethernet: et131x: Remove redundant register read 2020-07-17 18:48:15 -07:00
alacritech treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
allwinner treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
alteon net: alteon: Avoid some useless memset 2020-07-17 12:57:59 -07:00
altera treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
amazon net: ena: avoid unnecessary rearming of interrupt vector when busy-polling 2020-07-21 15:59:04 -07:00
amd xgbe: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
apm
apple treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
aquantia net: atlantic: add hwmon getter for MAC temperature 2020-07-20 18:07:39 -07:00
arc net: arc_emac: fix arc_emac_tx()'s return type 2020-06-28 20:52:53 -07:00
atheros net: alx: fix race condition in alx_remove 2020-06-15 13:20:14 -07:00
aurora net: nb8800: fix nb8800_xmit()'s return type 2020-06-28 20:52:53 -07:00
broadcom net: bnxt: don't complain if TC flower can't be supported 2020-07-17 18:26:20 -07:00
brocade net: bna: Remove unused variable 't' 2020-07-17 18:42:28 -07:00
cadence net: macb: Add WoL interrupt support for MACB type of Ethernet controller 2020-07-20 17:01:45 -07:00
calxeda
cavium liquidio_vf: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
chelsio cxgb4: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
cirrus docs: networking: reorganize driver documentation again 2020-06-26 16:08:44 -07:00
cisco enic: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
cortina net: ethernet: Replace HTTP links with HTTPS ones 2020-07-13 17:42:45 -07:00
davicom treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
dec docs: networking: reorganize driver documentation again 2020-06-26 16:08:44 -07:00
dlink net: sundance: Replace HTTP links with HTTPS ones 2020-07-15 17:41:34 -07:00
emulex be2net: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
ezchip treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
faraday treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
freescale enetc: Add adaptive interrupt coalescing 2020-07-21 15:38:30 -07:00
fujitsu treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
google
hisilicon net: hns: use eth_broadcast_addr() to assign broadcast address 2020-07-20 16:55:34 -07:00
huawei hinic: add firmware update support 2020-07-15 18:06:44 -07:00
i825xx treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
ibm ibmvnic: continue to init in CRQ reset returns H_CLOSED 2020-06-20 17:28:41 -07:00
intel fm10k: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
marvell net: mvneta: move rxq->left_size on the stack 2020-07-19 18:28:34 -07:00
mediatek net: ethernet: mtk-star-emac: use devm_of_mdiobus_register() 2020-06-30 15:57:34 -07:00
mellanox net/mlx5e: CT: Map 128 bits labels to 32 bit map ID 2020-07-16 16:37:00 -07:00
micrel ksz884x: switch from 'pci_' to 'dma_' API 2020-07-14 15:10:29 -07:00
microchip lan743x: switch from 'pci_' to 'dma_' API 2020-07-14 13:47:56 -07:00
moxa treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
mscc net: mscc: ocelot: add support for PTP waveform configuration 2020-07-19 19:22:57 -07:00
myricom ethernet: myri10ge: use generic power management 2020-07-20 18:01:07 -07:00
natsemi natsemi: use generic power management 2020-07-01 12:58:33 -07:00
neterion net: vxge-main: Remove unnecessary cast in kfree() 2020-07-20 16:45:09 -07:00
netronome nfp: convert to new udp_tunnel_nic infra 2020-07-14 17:04:27 -07:00
ni
nvidia treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
nxp
oki-semi net: pch_gbe: fix pch_gbe_xmit_frame()'s return type 2020-06-28 20:52:53 -07:00
packetengines net: packetengines: switch from 'pci_' to 'dma_' API 2020-07-20 17:48:23 -07:00
pasemi treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
pensando Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2020-07-11 00:46:00 -07:00
qlogic qed: Fix ILT and XRCD bitmap memory leaks 2020-07-21 15:50:53 -07:00
qualcomm net: rmnet: do not allow to add multiple bridge interfaces 2020-07-04 18:04:55 -07:00
rdc r6040: switch from 'pci_' to 'dma_' API 2020-07-20 17:49:50 -07:00
realtek r8169: add support for RTL8125B 2020-07-14 15:07:16 -07:00
renesas treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
rocker rocker: fix incorrect error handling in dma_rings_init 2020-06-15 13:37:36 -07:00
samsung treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
seeq treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
sfc sfc_ef100: helper function to set default RSS table of given size 2020-07-02 14:47:40 -07:00
sgi treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
silan treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
sis sis: switch from 'pci_' to 'dma_' API 2020-07-20 17:50:07 -07:00
smsc smsc9420: use generic power management 2020-07-07 15:20:49 -07:00
socionext socionext: account for napi_gro_receive never returning GRO_DROP 2020-06-25 16:16:21 -07:00
stmicro net: stmmac: dwmac-meson8b: use clk_parent_data for clock registration 2020-06-26 12:17:29 -07:00
sun net: sungem: switch from 'pci_' to 'dma_' API 2020-07-17 12:56:40 -07:00
synopsys net: dwc-xlgmac: fix xlgmac_xmit()'s return type 2020-06-28 20:52:53 -07:00
tehuti treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
ti net: ethernet: ti: am65-cpsw-nuss: enable am65x sr2.0 support 2020-06-29 17:06:19 -07:00
toshiba treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
tundra treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
via treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
wiznet treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
xilinx net: axienet: fix spelling mistake in comment "Exteneded" -> "extended" 2020-06-15 13:02:03 -07:00
xircom xirc2ps_cs: remove dev null check from do_reset(). 2020-06-23 20:18:16 -07:00
xscale treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
dnet.c
dnet.h
ec_bhf.c
ethoc.c
fealnx.c net/fealnx: switch from 'pci_' to 'dma_' API 2020-07-20 18:32:49 -07:00
jme.c net: jme: Replace HTTP links with HTTPS ones 2020-07-13 17:45:04 -07:00
jme.h net: jme: Replace HTTP links with HTTPS ones 2020-07-13 17:45:04 -07:00
Kconfig treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
korina.c
lantiq_etop.c
lantiq_xrx200.c
Makefile