Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 219b3d29 authored by Logan Gunthorpe's avatar Logan Gunthorpe Committed by Greg Kroah-Hartman
Browse files

dmaengine: Store module owner in dma_device struct



[ Upstream commit dae7a589c18a4d979d5f14b09374e871b995ceb1 ]

dma_chan_to_owner() dereferences the driver from the struct device to
obtain the owner and call module_[get|put](). However, if the backing
device is unbound before the dma_device is unregistered, the driver
will be cleared and this will cause a NULL pointer dereference.

Instead, store a pointer to the owner module in the dma_device struct
so the module reference can be properly put when the channel is put, even
if the backing device was destroyed first.

This change helps to support a safer unbind of DMA engines.
If the dma_device is unregistered in the driver's remove function,
there's no guarantee that there are no existing clients and a users
action may trigger the WARN_ONCE in dma_async_device_unregister()
which is unlikely to leave the system in a consistent state.
Instead, a better approach is to allow the backing driver to go away
and fail any subsequent requests to it.

Signed-off-by: default avatarLogan Gunthorpe <logang@deltatee.com>
Link: https://lore.kernel.org/r/20191216190120.21374-2-logang@deltatee.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 7742c3e9
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -190,7 +190,7 @@ __dma_device_satisfies_mask(struct dma_device *device,

static struct module *dma_chan_to_owner(struct dma_chan *chan)
{
	return chan->device->dev->driver->owner;
	return chan->device->owner;
}

/**
@@ -923,6 +923,8 @@ int dma_async_device_register(struct dma_device *device)
		return -EIO;
	}

	device->owner = device->dev->driver->owner;

	if (dma_has_cap(DMA_MEMCPY, device->cap_mask) && !device->device_prep_dma_memcpy) {
		dev_err(device->dev,
			"Device claims capability %s, but op is not defined\n",
+2 −0
Original line number Diff line number Diff line
@@ -686,6 +686,7 @@ struct dma_filter {
 * @fill_align: alignment shift for memset operations
 * @dev_id: unique device ID
 * @dev: struct device reference for dma mapping api
 * @owner: owner module (automatically set based on the provided dev)
 * @src_addr_widths: bit mask of src addr widths the device supports
 *	Width is specified in bytes, e.g. for a device supporting
 *	a width of 4 the mask should have BIT(4) set.
@@ -749,6 +750,7 @@ struct dma_device {

	int dev_id;
	struct device *dev;
	struct module *owner;

	u32 src_addr_widths;
	u32 dst_addr_widths;