linux/Documentation/driver-api
Daniel Vetter 5fbff813a4 dma-fence: basic lockdep annotations
Design is similar to the lockdep annotations for workers, but with
some twists:

- We use a read-lock for the execution/worker/completion side, so that
  this explicit annotation can be more liberally sprinkled around.
  With read locks lockdep isn't going to complain if the read-side
  isn't nested the same way under all circumstances, so ABBA deadlocks
  are ok. Which they are, since this is an annotation only.

- We're using non-recursive lockdep read lock mode, since in recursive
  read lock mode lockdep does not catch read side hazards. And we
  _very_ much want read side hazards to be caught. For full details of
  this limitation see

  commit e914985897
  Author: Peter Zijlstra <peterz@infradead.org>
  Date:   Wed Aug 23 13:13:11 2017 +0200

      locking/lockdep/selftests: Add mixed read-write ABBA tests

- To allow nesting of the read-side explicit annotations we explicitly
  keep track of the nesting. lock_is_held() allows us to do that.

- The wait-side annotation is a write lock, and entirely done within
  dma_fence_wait() for everyone by default.

- To be able to freely annotate helper functions I want to make it ok
  to call dma_fence_begin/end_signalling from soft/hardirq context.
  First attempt was using the hardirq locking context for the write
  side in lockdep, but this forces all normal spinlocks nested within
  dma_fence_begin/end_signalling to be spinlocks. That bollocks.

  The approach now is to simple check in_atomic(), and for these cases
  entirely rely on the might_sleep() check in dma_fence_wait(). That
  will catch any wrong nesting against spinlocks from soft/hardirq
  contexts.

The idea here is that every code path that's critical for eventually
signalling a dma_fence should be annotated with
dma_fence_begin/end_signalling. The annotation ideally starts right
after a dma_fence is published (added to a dma_resv, exposed as a
sync_file fd, attached to a drm_syncobj fd, or anything else that
makes the dma_fence visible to other kernel threads), up to and
including the dma_fence_wait(). Examples are irq handlers, the
scheduler rt threads, the tail of execbuf (after the corresponding
fences are visible), any workers that end up signalling dma_fences and
really anything else. Not annotated should be code paths that only
complete fences opportunistically as the gpu progresses, like e.g.
shrinker/eviction code.

The main class of deadlocks this is supposed to catch are:

Thread A:

	mutex_lock(A);
	mutex_unlock(A);

	dma_fence_signal();

Thread B:

	mutex_lock(A);
	dma_fence_wait();
	mutex_unlock(A);

Thread B is blocked on A signalling the fence, but A never gets around
to that because it cannot acquire the lock A.

Note that dma_fence_wait() is allowed to be nested within
dma_fence_begin/end_signalling sections. To allow this to happen the
read lock needs to be upgraded to a write lock, which means that any
other lock is acquired between the dma_fence_begin_signalling() call and
the call to dma_fence_wait(), and still held, this will result in an
immediate lockdep complaint. The only other option would be to not
annotate such calls, defeating the point. Therefore these annotations
cannot be sprinkled over the code entirely mindless to avoid false
positives.

Originally I hope that the cross-release lockdep extensions would
alleviate the need for explicit annotations:

https://lwn.net/Articles/709849/

But there's a few reasons why that's not an option:

- It's not happening in upstream, since it got reverted due to too
  many false positives:

	commit e966eaeeb6
	Author: Ingo Molnar <mingo@kernel.org>
	Date:   Tue Dec 12 12:31:16 2017 +0100

	    locking/lockdep: Remove the cross-release locking checks

	    This code (CONFIG_LOCKDEP_CROSSRELEASE=y and CONFIG_LOCKDEP_COMPLETIONS=y),
	    while it found a number of old bugs initially, was also causing too many
	    false positives that caused people to disable lockdep - which is arguably
	    a worse overall outcome.

- cross-release uses the complete() call to annotate the end of
  critical sections, for dma_fence that would be dma_fence_signal().
  But we do not want all dma_fence_signal() calls to be treated as
  critical, since many are opportunistic cleanup of gpu requests. If
  these get stuck there's still the main completion interrupt and
  workers who can unblock everyone. Automatically annotating all
  dma_fence_signal() calls would hence cause false positives.

- cross-release had some educated guesses for when a critical section
  starts, like fresh syscall or fresh work callback. This would again
  cause false positives without explicit annotations, since for
  dma_fence the critical sections only starts when we publish a fence.

- Furthermore there can be cases where a thread never does a
  dma_fence_signal, but is still critical for reaching completion of
  fences. One example would be a scheduler kthread which picks up jobs
  and pushes them into hardware, where the interrupt handler or
  another completion thread calls dma_fence_signal(). But if the
  scheduler thread hangs, then all the fences hang, hence we need to
  manually annotate it. cross-release aimed to solve this by chaining
  cross-release dependencies, but the dependency from scheduler thread
  to the completion interrupt handler goes through hw where
  cross-release code can't observe it.

In short, without manual annotations and careful review of the start
and end of critical sections, cross-relese dependency tracking doesn't
work. We need explicit annotations.

v2: handle soft/hardirq ctx better against write side and dont forget
EXPORT_SYMBOL, drivers can't use this otherwise.

v3: Kerneldoc.

v4: Some spelling fixes from Mika

v5: Amend commit message to explain in detail why cross-release isn't
the solution.

v6: Pull out misplaced .rst hunk.

Acked-by: Christian König <christian.koenig@amd.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Cc: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Thomas Hellstrom <thomas.hellstrom@intel.com>
Cc: linux-media@vger.kernel.org
Cc: linaro-mm-sig@lists.linaro.org
Cc: linux-rdma@vger.kernel.org
Cc: amd-gfx@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Christian König <christian.koenig@amd.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200707201229.472834-2-daniel.vetter@ffwll.ch
2020-07-21 09:42:19 +02:00
..
80211 docs: prevent warnings due to autosectionlabel 2020-03-20 17:01:29 -06:00
acpi Replace HTTP links with HTTPS ones: documentation 2020-06-08 09:30:19 -06:00
backlight docs: lp855x-driver.rst: add it to the driver-api book 2019-07-15 11:03:02 -03:00
dmaengine This has been a busy cycle for documentation work. Highlights include: 2020-03-30 12:45:23 -07:00
driver-model A handful of late-arriving docs fixes, along with a patch changing a lot of 2020-06-10 14:12:15 -07:00
early-userspace docs: add SPDX tags to new index files 2019-07-15 11:03:03 -03:00
firmware Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2020-03-30 16:13:08 -07:00
fpga
gpio gpiolib: Add support for GPIO lookup by line name 2020-05-18 10:12:42 +02:00
i3c
iio iio: core: drop devm_iio_trigger_free() API call 2020-04-19 16:56:37 +01:00
md docs: add SPDX tags to new index files 2019-07-15 11:03:03 -03:00
media Documentation: media: convert to use i2c_new_client_device() 2020-06-19 09:20:25 +02:00
mei mei: docs: update mei documentation 2019-06-06 16:51:37 +02:00
memory-devices docs: add SPDX tags to new index files 2019-07-15 11:03:03 -03:00
mmc docs: add SPDX tags to new index files 2019-07-15 11:03:03 -03:00
mtd docs: mtd: Update spi nor reference driver 2019-09-06 08:51:39 -06:00
nfc docs: add SPDX tags to new index files 2019-07-15 11:03:03 -03:00
nvdimm doc: nvdimm: remove reference to non-existent CONFIG_NFIT_TEST 2020-04-28 12:46:07 -06:00
pci
phy docs: phy: Drop duplicate 'be made' 2019-07-26 08:15:26 -06:00
pm Merge branch 'pm-cpuidle' 2020-06-01 15:19:30 +02:00
rapidio docs: add SPDX tags to new index files 2019-07-15 11:03:03 -03:00
serial tty: n_gsm: add ioctl to map serial device to mux'ed tty 2019-09-04 12:43:54 +02:00
soundwire soundwire: bus: rename sdw_bus_master_add/delete, add arguments 2020-05-19 12:44:34 +05:30
thermal doc: thermal: add cpu-idle-cooling to index tree 2020-05-05 09:57:14 -06:00
usb Replace HTTP links with HTTPS ones: documentation 2020-06-08 09:30:19 -06:00
xilinx docs: driver-api: add xilinx driver API documentation 2019-07-15 11:03:02 -03:00
basics.rst docs: Do not seek comments in kernel/rcu/tree_plugin.h 2019-05-24 14:23:40 -06:00
clk.rst docs: clk: fix struct syntax 2019-06-07 11:35:15 -06:00
component.rst
connector.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
console.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
dcdbas.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
devfreq.rst docs: Add initial documentation for devfreq 2019-11-19 13:16:53 -07:00
device_connection.rst
device_link.rst driver core: Add support for linking devices during device addition 2019-10-04 17:29:50 +02:00
device-io.rst
dma-buf.rst dma-fence: basic lockdep annotations 2020-07-21 09:42:19 +02:00
edac.rst
eisa.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
firewire.rst
frame-buffer.rst
generic-counter.rst docs: driver-api: generic-counter: Update Count and Signal data types 2019-10-18 19:47:38 +01:00
hsi.rst
i2c.rst
index.rst media updates for v5.8-rc1 2020-06-03 20:59:38 -07:00
infiniband.rst RDMA/core: Remove FMR pool API 2020-06-02 20:32:53 -03:00
infrastructure.rst docs: No structured comments in kernel/dma/coherent.c 2019-10-01 08:43:21 -06:00
input.rst
interconnect.rst interconnect: Add interconnect_graph file to debugfs 2019-12-16 09:49:54 +02:00
io_ordering.rst Documentation: Add io_ordering.rst to driver-api manual 2020-03-10 11:33:19 -06:00
io-mapping.rst Documentation: Add io-mapping.rst to driver-api manual 2020-03-10 11:33:15 -06:00
ioctl.rst docs: move core-api/ioctl.rst to driver-api/ 2020-03-10 11:21:08 -06:00
ipmb.rst drivers: ipmi: Support raw i2c packet in IPMB 2019-12-11 13:21:36 -06:00
ipmi.rst docs: move IPMI.txt to the driver API book 2020-05-15 11:55:04 -06:00
isa.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
isapnp.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
libata.rst scsi: docs: convert scsi_eh.txt to ReST 2020-03-11 23:08:01 -04:00
lightnvm-pblk.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
men-chameleon-bus.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
message-based.rst
misc_devices.rst
miscellaneous.rst
mtdnand.rst mtd: rawnand: Stop using nand_release() 2020-05-31 10:53:40 +02:00
ntb.rst New feature to add support for NTB virtual MSI interrupts, the ability 2019-07-21 09:46:59 -07:00
nvmem.rst nvmem: core: add nvmem_device_find 2019-10-07 09:47:37 -07:00
parport-lowlevel.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
pinctl.rst docs/pinctrl: fix compile errors in example code 2019-07-29 00:20:09 +02:00
pps.rst docs: driver-api: add remaining converted dirs to it 2019-07-15 11:03:03 -03:00
pti_intel_mid.rst docs: driver-api: pti_intel_mid: Enable syntax highlighting for C code block 2019-10-18 09:40:13 -06:00
ptp.rst docs: driver-api: add remaining converted dirs to it 2019-07-15 11:03:03 -03:00
pwm.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
regulator.rst
rfkill.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
s390-drivers.rst docs: s390: convert docs to ReST and rename to *.rst 2019-06-11 09:48:14 +02:00
scsi.rst
slimbus.rst
sm501.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
smsc_ece1099.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
sound.rst
spi.rst
switchtec.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
sync_file.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
target.rst docs: No structured comments in target_core_device.c 2019-05-24 15:01:30 -06:00
uio-howto.rst uio: Documentation: Add information on using uio_pdrv_genirq with DT 2019-09-04 13:42:43 +02:00
vfio-mediated-device.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
vfio.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
vme.rst
w1.rst docs: driver-api: address duplicate label warning 2020-04-07 13:41:34 -06:00
xillybus.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00
zorro.rst docs: driver-api: add a series of orphaned documents 2019-07-15 11:03:02 -03:00