Commit c31bbc14 authored by Eli Billauer's avatar Eli Billauer Committed by Greg Kroah-Hartman
Browse files

char: xillybus: Eliminate redundant wrappers to DMA related calls



The driver was originally written with the assumption that a different
API must be used for DMA-related functions if the device is PCIe based
or if not. Since Xillybus' driver supports devices on a PCIe bus (with
xillybus_pcie) as well as connected directly to the processor (with
xillybus_of), it originally used wrapper functions that ensure that
a different API is used for each.

This patch eliminates the said wrapper functions, as all use the same
dma_* API now. This is most notable by the code deleted in xillybus_pcie.c
and xillybus_of.c.

It also eliminates the OF driver's check for a "dma-coherent" attribute
in the device's OF entry, since this is taken care of by the kernel's
implementation of dma_sync_single_for_*().

There is however still need for one wrapper function, which is merged
from xillybus_pcie.c and xillybus_of.c into xillybus_core.c: The call to
dma_map_single() is wrapped by a function that uses the Managed Device
(devres) framework, in the absence of a relevant function in the current
kernel's API.

Suggested-by: default avatarChristophe JAILLET <christophe.jaillet@wanadoo.fr>
Suggested-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarEli Billauer <eli.billauer@gmail.com>
Link: https://lore.kernel.org/r/20210929094442.46383-1-eli.billauer@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 847afd7b
Loading
Loading
Loading
Loading
+2 −21
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ struct xilly_channel {

struct xilly_endpoint {
	struct device *dev;
	struct xilly_endpoint_hardware *ephw;
	struct module *owner;

	int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */
	__iomem void *registers;
@@ -108,23 +108,6 @@ struct xilly_endpoint {
	unsigned int msg_buf_size;
};

struct xilly_endpoint_hardware {
	struct module *owner;
	void (*hw_sync_sgl_for_cpu)(struct xilly_endpoint *,
				    dma_addr_t,
				    size_t,
				    int);
	void (*hw_sync_sgl_for_device)(struct xilly_endpoint *,
				       dma_addr_t,
				       size_t,
				       int);
	int (*map_single)(struct xilly_endpoint *,
			  void *,
			  size_t,
			  int,
			  dma_addr_t *);
};

struct xilly_mapping {
	struct device *device;
	dma_addr_t dma_addr;
@@ -134,9 +117,7 @@ struct xilly_mapping {

irqreturn_t xillybus_isr(int irq, void *data);

struct xilly_endpoint *xillybus_init_endpoint(struct device *dev,
					      struct xilly_endpoint_hardware
					      *ephw);
struct xilly_endpoint *xillybus_init_endpoint(struct device *dev);

int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint);

+78 −51
Original line number Diff line number Diff line
@@ -122,10 +122,8 @@ irqreturn_t xillybus_isr(int irq, void *data)
	buf = ep->msgbuf_addr;
	buf_size = ep->msg_buf_size/sizeof(u32);

	ep->ephw->hw_sync_sgl_for_cpu(ep,
				      ep->msgbuf_dma_addr,
				      ep->msg_buf_size,
				      DMA_FROM_DEVICE);
	dma_sync_single_for_cpu(ep->dev, ep->msgbuf_dma_addr,
				ep->msg_buf_size, DMA_FROM_DEVICE);

	for (i = 0; i < buf_size; i += 2) {
		if (((buf[i+1] >> 28) & 0xf) != ep->msg_counter) {
@@ -140,8 +138,7 @@ irqreturn_t xillybus_isr(int irq, void *data)
				dev_err(ep->dev,
					"Lost sync with interrupt messages. Stopping.\n");
			} else {
				ep->ephw->hw_sync_sgl_for_device(
					ep,
				dma_sync_single_for_device(ep->dev,
							   ep->msgbuf_dma_addr,
							   ep->msg_buf_size,
							   DMA_FROM_DEVICE);
@@ -275,10 +272,8 @@ irqreturn_t xillybus_isr(int irq, void *data)
		}
	}

	ep->ephw->hw_sync_sgl_for_device(ep,
					 ep->msgbuf_dma_addr,
					 ep->msg_buf_size,
					 DMA_FROM_DEVICE);
	dma_sync_single_for_device(ep->dev, ep->msgbuf_dma_addr,
				   ep->msg_buf_size, DMA_FROM_DEVICE);

	ep->msg_counter = (ep->msg_counter + 1) & 0xf;
	ep->failed_messages = 0;
@@ -304,6 +299,47 @@ struct xilly_alloc_state {
	u32 regdirection;
};

static void xilly_unmap(void *ptr)
{
	struct xilly_mapping *data = ptr;

	dma_unmap_single(data->device, data->dma_addr,
			 data->size, data->direction);

	kfree(ptr);
}

static int xilly_map_single(struct xilly_endpoint *ep,
			    void *ptr,
			    size_t size,
			    int direction,
			    dma_addr_t *ret_dma_handle
	)
{
	dma_addr_t addr;
	struct xilly_mapping *this;

	this = kzalloc(sizeof(*this), GFP_KERNEL);
	if (!this)
		return -ENOMEM;

	addr = dma_map_single(ep->dev, ptr, size, direction);

	if (dma_mapping_error(ep->dev, addr)) {
		kfree(this);
		return -ENODEV;
	}

	this->device = ep->dev;
	this->dma_addr = addr;
	this->size = size;
	this->direction = direction;

	*ret_dma_handle = addr;

	return devm_add_action_or_reset(ep->dev, xilly_unmap, this);
}

static int xilly_get_dma_buffers(struct xilly_endpoint *ep,
				 struct xilly_alloc_state *s,
				 struct xilly_buffer **buffers,
@@ -355,7 +391,7 @@ static int xilly_get_dma_buffers(struct xilly_endpoint *ep,
			s->left_of_salami = allocsize;
		}

		rc = ep->ephw->map_single(ep, s->salami,
		rc = xilly_map_single(ep, s->salami,
				      bytebufsize, s->direction,
				      &dma_addr);
		if (rc)
@@ -620,8 +656,7 @@ static int xilly_obtain_idt(struct xilly_endpoint *endpoint)
		return -ENODEV;
	}

	endpoint->ephw->hw_sync_sgl_for_cpu(
		channel->endpoint,
	dma_sync_single_for_cpu(channel->endpoint->dev,
				channel->wr_buffers[0]->dma_addr,
				channel->wr_buf_size,
				DMA_FROM_DEVICE);
@@ -735,8 +770,7 @@ static ssize_t xillybus_read(struct file *filp, char __user *userbuf,
		if (!empty) { /* Go on, now without the spinlock */

			if (bufpos == 0) /* Position zero means it's virgin */
				channel->endpoint->ephw->hw_sync_sgl_for_cpu(
					channel->endpoint,
				dma_sync_single_for_cpu(channel->endpoint->dev,
							channel->wr_buffers[bufidx]->dma_addr,
							channel->wr_buf_size,
							DMA_FROM_DEVICE);
@@ -751,8 +785,7 @@ static ssize_t xillybus_read(struct file *filp, char __user *userbuf,
			bytes_done += howmany;

			if (bufferdone) {
				channel->endpoint->ephw->hw_sync_sgl_for_device(
					channel->endpoint,
				dma_sync_single_for_device(channel->endpoint->dev,
							   channel->wr_buffers[bufidx]->dma_addr,
							   channel->wr_buf_size,
							   DMA_FROM_DEVICE);
@@ -1055,8 +1088,7 @@ static int xillybus_myflush(struct xilly_channel *channel, long timeout)
		else
			channel->rd_host_buf_idx++;

		channel->endpoint->ephw->hw_sync_sgl_for_device(
			channel->endpoint,
		dma_sync_single_for_device(channel->endpoint->dev,
					   channel->rd_buffers[bufidx]->dma_addr,
					   channel->rd_buf_size,
					   DMA_TO_DEVICE);
@@ -1275,8 +1307,7 @@ static ssize_t xillybus_write(struct file *filp, const char __user *userbuf,

			if ((bufpos == 0) || /* Zero means it's virgin */
			    (channel->rd_leftovers[3] != 0)) {
				channel->endpoint->ephw->hw_sync_sgl_for_cpu(
					channel->endpoint,
				dma_sync_single_for_cpu(channel->endpoint->dev,
							channel->rd_buffers[bufidx]->dma_addr,
							channel->rd_buf_size,
							DMA_TO_DEVICE);
@@ -1297,8 +1328,7 @@ static ssize_t xillybus_write(struct file *filp, const char __user *userbuf,
			bytes_done += howmany;

			if (bufferdone) {
				channel->endpoint->ephw->hw_sync_sgl_for_device(
					channel->endpoint,
				dma_sync_single_for_device(channel->endpoint->dev,
							   channel->rd_buffers[bufidx]->dma_addr,
							   channel->rd_buf_size,
							   DMA_TO_DEVICE);
@@ -1772,9 +1802,7 @@ static const struct file_operations xillybus_fops = {
	.poll       = xillybus_poll,
};

struct xilly_endpoint *xillybus_init_endpoint(struct device *dev,
					      struct xilly_endpoint_hardware
					      *ephw)
struct xilly_endpoint *xillybus_init_endpoint(struct device *dev)
{
	struct xilly_endpoint *endpoint;

@@ -1783,7 +1811,6 @@ struct xilly_endpoint *xillybus_init_endpoint(struct device *dev,
		return NULL;

	endpoint->dev = dev;
	endpoint->ephw = ephw;
	endpoint->msg_counter = 0x0b;
	endpoint->failed_messages = 0;
	endpoint->fatal_error = 0;
@@ -1910,7 +1937,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
		goto failed_idt;

	rc = xillybus_init_chrdev(dev, &xillybus_fops,
				  endpoint->ephw->owner, endpoint,
				  endpoint->owner, endpoint,
				  idt_handle.names,
				  idt_handle.names_len,
				  endpoint->num_channels,
+3 −83
Original line number Diff line number Diff line
@@ -31,102 +31,22 @@ static const struct of_device_id xillybus_of_match[] = {

MODULE_DEVICE_TABLE(of, xillybus_of_match);

static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint *ep,
					     dma_addr_t dma_handle,
					     size_t size,
					     int direction)
{
	dma_sync_single_for_cpu(ep->dev, dma_handle, size, direction);
}

static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint *ep,
						dma_addr_t dma_handle,
						size_t size,
						int direction)
{
	dma_sync_single_for_device(ep->dev, dma_handle, size, direction);
}

static void xilly_dma_sync_single_nop(struct xilly_endpoint *ep,
				      dma_addr_t dma_handle,
				      size_t size,
				      int direction)
{
}

static void xilly_of_unmap(void *ptr)
{
	struct xilly_mapping *data = ptr;

	dma_unmap_single(data->device, data->dma_addr,
			 data->size, data->direction);

	kfree(ptr);
}

static int xilly_map_single_of(struct xilly_endpoint *ep,
			       void *ptr,
			       size_t size,
			       int direction,
			       dma_addr_t *ret_dma_handle
	)
{
	dma_addr_t addr;
	struct xilly_mapping *this;

	this = kzalloc(sizeof(*this), GFP_KERNEL);
	if (!this)
		return -ENOMEM;

	addr = dma_map_single(ep->dev, ptr, size, direction);

	if (dma_mapping_error(ep->dev, addr)) {
		kfree(this);
		return -ENODEV;
	}

	this->device = ep->dev;
	this->dma_addr = addr;
	this->size = size;
	this->direction = direction;

	*ret_dma_handle = addr;

	return devm_add_action_or_reset(ep->dev, xilly_of_unmap, this);
}

static struct xilly_endpoint_hardware of_hw = {
	.owner = THIS_MODULE,
	.hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of,
	.hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of,
	.map_single = xilly_map_single_of,
};

static struct xilly_endpoint_hardware of_hw_coherent = {
	.owner = THIS_MODULE,
	.hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop,
	.hw_sync_sgl_for_device = xilly_dma_sync_single_nop,
	.map_single = xilly_map_single_of,
};

static int xilly_drv_probe(struct platform_device *op)
{
	struct device *dev = &op->dev;
	struct xilly_endpoint *endpoint;
	int rc;
	int irq;
	struct xilly_endpoint_hardware *ephw = &of_hw;

	if (of_property_read_bool(dev->of_node, "dma-coherent"))
		ephw = &of_hw_coherent;

	endpoint = xillybus_init_endpoint(dev, ephw);
	endpoint = xillybus_init_endpoint(dev);

	if (!endpoint)
		return -ENOMEM;

	dev_set_drvdata(dev, endpoint);

	endpoint->owner = THIS_MODULE;

	endpoint->registers = devm_platform_ioremap_resource(op, 0);
	if (IS_ERR(endpoint->registers))
		return PTR_ERR(endpoint->registers);
+3 −87
Original line number Diff line number Diff line
@@ -32,105 +32,21 @@ static const struct pci_device_id xillyids[] = {
	{ /* End: all zeroes */ }
};

static int xilly_pci_direction(int direction)
{
	switch (direction) {
	case DMA_TO_DEVICE:
	case DMA_FROM_DEVICE:
		return direction;
	default:
		return DMA_BIDIRECTIONAL;
	}
}

static void xilly_dma_sync_single_for_cpu_pci(struct xilly_endpoint *ep,
					      dma_addr_t dma_handle,
					      size_t size,
					      int direction)
{
	dma_sync_single_for_cpu(ep->dev, dma_handle, size,
				xilly_pci_direction(direction));
}

static void xilly_dma_sync_single_for_device_pci(struct xilly_endpoint *ep,
						 dma_addr_t dma_handle,
						 size_t size,
						 int direction)
{
	dma_sync_single_for_device(ep->dev, dma_handle, size,
				   xilly_pci_direction(direction));
}

static void xilly_pci_unmap(void *ptr)
{
	struct xilly_mapping *data = ptr;

	dma_unmap_single(data->device, data->dma_addr, data->size,
			 data->direction);

	kfree(ptr);
}

/*
 * Map either through the PCI DMA mapper or the non_PCI one. Behind the
 * scenes exactly the same functions are called with the same parameters,
 * but that can change.
 */

static int xilly_map_single_pci(struct xilly_endpoint *ep,
				void *ptr,
				size_t size,
				int direction,
				dma_addr_t *ret_dma_handle
	)
{
	int pci_direction;
	dma_addr_t addr;
	struct xilly_mapping *this;

	this = kzalloc(sizeof(*this), GFP_KERNEL);
	if (!this)
		return -ENOMEM;

	pci_direction = xilly_pci_direction(direction);

	addr = dma_map_single(ep->dev, ptr, size, pci_direction);

	if (dma_mapping_error(ep->dev, addr)) {
		kfree(this);
		return -ENODEV;
	}

	this->device = ep->dev;
	this->dma_addr = addr;
	this->size = size;
	this->direction = pci_direction;

	*ret_dma_handle = addr;

	return devm_add_action_or_reset(ep->dev, xilly_pci_unmap, this);
}

static struct xilly_endpoint_hardware pci_hw = {
	.owner = THIS_MODULE,
	.hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_pci,
	.hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_pci,
	.map_single = xilly_map_single_pci,
};

static int xilly_probe(struct pci_dev *pdev,
		       const struct pci_device_id *ent)
{
	struct xilly_endpoint *endpoint;
	int rc;

	endpoint = xillybus_init_endpoint(&pdev->dev, &pci_hw);
	endpoint = xillybus_init_endpoint(&pdev->dev);

	if (!endpoint)
		return -ENOMEM;

	pci_set_drvdata(pdev, endpoint);

	endpoint->owner = THIS_MODULE;

	rc = pcim_enable_device(pdev);
	if (rc) {
		dev_err(endpoint->dev,