1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/drivers/net/ethernet/cisco/enic
Thomas Gleixner a53b59ece8 net: enic: Cure the enic api locking trainwreck
enic_dev_wait() has a BUG_ON(in_interrupt()).

Chasing the callers of enic_dev_wait() revealed the gems of enic_reset()
and enic_tx_hang_reset() which are both invoked through work queues in
order to be able to call rtnl_lock(). So far so good.

After locking rtnl both functions acquire enic::enic_api_lock which
serializes against the (ab)use from infiniband. This is where the
trainwreck starts.

enic::enic_api_lock is a spin_lock() which implicitly disables preemption,
but both functions invoke a ton of functions under that lock which can
sleep. The BUG_ON(in_interrupt()) does not trigger in that case because it
can't detect the preempt disabled condition.

This clearly has never been tested with any of the mandatory debug options
for 7+ years, which would have caught that for sure.

Cure it by adding a enic_api_busy member to struct enic, which is modified
and evaluated with enic::enic_api_lock held.

If enic_api_devcmd_proxy_by_index() observes enic::enic_api_busy as true,
it drops enic::enic_api_lock and busy waits for enic::enic_api_busy to
become false.

It would be smarter to wait for a completion of that busy period, but
enic_api_devcmd_proxy_by_index() is called with other spin locks held which
obviously can't sleep.

Remove the BUG_ON(in_interrupt()) check as well because it's incomplete and
with proper debugging enabled the problem would have been caught from the
debug checks in schedule_timeout().

Fixes: 0b038566c0 ("drivers/net: enic: Add an interface for USNIC to interact with firmware")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-09-29 14:02:53 -07:00
..
cq_desc.h
cq_enet_desc.h enic: Fix endianness bug. 2012-02-24 17:53:03 -05:00
enic.h net: enic: Cure the enic api locking trainwreck 2020-09-29 14:02:53 -07:00
enic_api.c net: enic: Cure the enic api locking trainwreck 2020-09-29 14:02:53 -07:00
enic_api.h drivers/net: enic: Add an interface for USNIC to interact with firmware 2013-08-20 13:41:01 -07:00
enic_clsf.c drivers: net: Remove unnecessary semicolon 2019-03-01 23:13:49 -08:00
enic_clsf.h treewide: setup_timer() -> timer_setup() (2 field) 2017-11-21 15:57:09 -08:00
enic_dev.c net: ethernet: cisco: enic: enic_dev: Remove some unused functions 2015-01-02 16:36:08 -05:00
enic_dev.h net: ethernet: cisco: enic: enic_dev: Remove some unused functions 2015-01-02 16:36:08 -05:00
enic_ethtool.c drivers/net/ethernet: clean up mis-targeted comments 2020-09-25 16:29:00 -07:00
enic_main.c net: enic: Cure the enic api locking trainwreck 2020-09-29 14:02:53 -07:00
enic_pp.c net: enic: slight optimization of addr compare 2013-12-31 16:48:31 -05:00
enic_pp.h enic: Add support for port profile association on a enic SRIOV VF 2011-09-27 01:10:24 -04:00
enic_res.c enic: fix UDP rss bits 2018-06-06 09:09:09 -04:00
enic_res.h ethernet: use core min/max MTU checking 2016-10-18 11:34:22 -04:00
Kconfig treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
Makefile treewide: Add SPDX license identifier - Makefile/Kconfig 2019-05-21 10:50:46 +02:00
rq_enet_desc.h
vnic_cq.c cisco: enic: Update logging macros and uses 2016-03-11 15:07:48 -05:00
vnic_cq.h enic: Add support for adaptive interrupt coalescing 2014-05-21 17:04:13 -04:00
vnic_dev.c enic: switch from 'pci_' to 'dma_' API 2020-09-06 12:52:19 -07:00
vnic_dev.h enic: fix UDP rss bits 2018-06-06 09:09:09 -04:00
vnic_devcmd.h net: cisco: Replace zero-length array with flexible-array member 2020-02-26 16:43:09 -08:00
vnic_enet.h enic: add devcmds for vxlan offload 2017-02-09 17:24:29 -05:00
vnic_intr.c cisco: enic: Update logging macros and uses 2016-03-11 15:07:48 -05:00
vnic_intr.h
vnic_nic.h enic: fix UDP rss bits 2018-06-06 09:09:09 -04:00
vnic_resource.h enic: add devcmd2 resources 2015-08-17 15:25:29 -07:00
vnic_rq.c net: cisco: enic: Replace GFP_ATOMIC with GFP_KERNEL 2018-08-04 13:08:06 -07:00
vnic_rq.h enic: Remove local ndo_busy_poll() implementation. 2017-02-03 17:28:21 -05:00
vnic_rss.h enic: use netdev_rss_key_fill() helper 2014-11-23 21:01:42 -05:00
vnic_stats.h enic: add stats for dma mapping error 2014-12-31 13:08:45 -05:00
vnic_vic.c
vnic_vic.h net: cisco: Replace zero-length array with flexible-array member 2020-02-26 16:43:09 -08:00
vnic_wq.c net: cisco: enic: Replace GFP_ATOMIC with GFP_KERNEL 2018-08-04 13:08:06 -07:00
vnic_wq.h enic: reduce ioread in devcmd2 2015-08-25 16:05:48 -07:00
wq_enet_desc.h