From 01573e231f18eb2d99162747186f59511f56b64d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 08 Dec 2023 10:40:48 +0000
Subject: [PATCH] 移去rt
---
kernel/drivers/staging/axis-fifo/axis-fifo.c | 468 +++++++++++++++++++++++-----------------------------------
1 files changed, 185 insertions(+), 283 deletions(-)
diff --git a/kernel/drivers/staging/axis-fifo/axis-fifo.c b/kernel/drivers/staging/axis-fifo/axis-fifo.c
index abeee0e..2bb1c2e 100644
--- a/kernel/drivers/staging/axis-fifo/axis-fifo.c
+++ b/kernel/drivers/staging/axis-fifo/axis-fifo.c
@@ -16,7 +16,7 @@
#include <linux/kernel.h>
#include <linux/wait.h>
-#include <linux/spinlock_types.h>
+#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/init.h>
@@ -27,8 +27,6 @@
#include <linux/interrupt.h>
#include <linux/param.h>
#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/jiffies.h>
@@ -127,7 +125,6 @@
struct axis_fifo {
int irq; /* interrupt */
- struct resource *mem; /* physical memory */
void __iomem *base_addr; /* kernel space memory */
unsigned int rx_fifo_depth; /* max words in the receive fifo */
@@ -136,9 +133,9 @@
int has_tx_fifo; /* whether the IP has the tx fifo enabled */
wait_queue_head_t read_queue; /* wait queue for asynchronos read */
- spinlock_t read_queue_lock; /* lock for reading waitqueue */
+ struct mutex read_lock; /* lock for reading */
wait_queue_head_t write_queue; /* wait queue for asynchronos write */
- spinlock_t write_queue_lock; /* lock for writing waitqueue */
+ struct mutex write_lock; /* lock for writing */
unsigned int write_flags; /* write file flags */
unsigned int read_flags; /* read file flags */
@@ -339,7 +336,21 @@
iowrite32(XLLF_INT_ALL_MASK, fifo->base_addr + XLLF_ISR_OFFSET);
}
-/* reads a single packet from the fifo as dictated by the tlast signal */
+/**
+ * axis_fifo_write() - Read a packet from AXIS-FIFO character device.
+ * @f Open file.
+ * @buf User space buffer to read to.
+ * @len User space buffer length.
+ * @off Buffer offset.
+ *
+ * As defined by the device's documentation, we need to check the device's
+ * occupancy before reading the length register and then the data. All these
+ * operations must be executed atomically, in order and one after the other
+ * without missing any.
+ *
+ * Returns the number of bytes read from the device or negative error code
+ * on failure.
+ */
static ssize_t axis_fifo_read(struct file *f, char __user *buf,
size_t len, loff_t *off)
{
@@ -353,36 +364,38 @@
u32 tmp_buf[READ_BUF_SIZE];
if (fifo->read_flags & O_NONBLOCK) {
- /* opened in non-blocking mode
- * return if there are no packets available
+ /*
+ * Device opened in non-blocking mode. Try to lock it and then
+ * check if any packet is available.
*/
- if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET))
+ if (!mutex_trylock(&fifo->read_lock))
return -EAGAIN;
+
+ if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET)) {
+ ret = -EAGAIN;
+ goto end_unlock;
+ }
} else {
/* opened in blocking mode
* wait for a packet available interrupt (or timeout)
* if nothing is currently available
*/
- spin_lock_irq(&fifo->read_queue_lock);
- ret = wait_event_interruptible_lock_irq_timeout(
- fifo->read_queue,
+ mutex_lock(&fifo->read_lock);
+ ret = wait_event_interruptible_timeout(fifo->read_queue,
ioread32(fifo->base_addr + XLLF_RDFO_OFFSET),
- fifo->read_queue_lock,
- (read_timeout >= 0) ? msecs_to_jiffies(read_timeout) :
- MAX_SCHEDULE_TIMEOUT);
- spin_unlock_irq(&fifo->read_queue_lock);
+ (read_timeout >= 0) ?
+ msecs_to_jiffies(read_timeout) :
+ MAX_SCHEDULE_TIMEOUT);
- if (ret == 0) {
- /* timeout occurred */
- dev_dbg(fifo->dt_device, "read timeout");
- return -EAGAIN;
- } else if (ret == -ERESTARTSYS) {
- /* signal received */
- return -ERESTARTSYS;
- } else if (ret < 0) {
- dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n",
- ret);
- return ret;
+ if (ret <= 0) {
+ if (ret == 0) {
+ ret = -EAGAIN;
+ } else if (ret != -ERESTARTSYS) {
+ dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n",
+ ret);
+ }
+
+ goto end_unlock;
}
}
@@ -390,14 +403,16 @@
if (!bytes_available) {
dev_err(fifo->dt_device, "received a packet of length 0 - fifo core will be reset\n");
reset_ip_core(fifo);
- return -EIO;
+ ret = -EIO;
+ goto end_unlock;
}
if (bytes_available > len) {
dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu) - fifo core will be reset\n",
bytes_available, len);
reset_ip_core(fifo);
- return -EINVAL;
+ ret = -EINVAL;
+ goto end_unlock;
}
if (bytes_available % sizeof(u32)) {
@@ -406,7 +421,8 @@
*/
dev_err(fifo->dt_device, "received a packet that isn't word-aligned - fifo core will be reset\n");
reset_ip_core(fifo);
- return -EIO;
+ ret = -EIO;
+ goto end_unlock;
}
words_available = bytes_available / sizeof(u32);
@@ -426,16 +442,37 @@
if (copy_to_user(buf + copied * sizeof(u32), tmp_buf,
copy * sizeof(u32))) {
reset_ip_core(fifo);
- return -EFAULT;
+ ret = -EFAULT;
+ goto end_unlock;
}
copied += copy;
words_available -= copy;
}
- return bytes_available;
+ ret = bytes_available;
+
+end_unlock:
+ mutex_unlock(&fifo->read_lock);
+
+ return ret;
}
+/**
+ * axis_fifo_write() - Write buffer to AXIS-FIFO character device.
+ * @f Open file.
+ * @buf User space buffer to write to the device.
+ * @len User space buffer length.
+ * @off Buffer offset.
+ *
+ * As defined by the device's documentation, we need to write to the device's
+ * data buffer then to the device's packet length register atomically. Also,
+ * we need to lock before checking if the device has available space to avoid
+ * any concurrency issue.
+ *
+ * Returns the number of bytes written to the device or negative error code
+ * on failure.
+ */
static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
size_t len, loff_t *off)
{
@@ -468,12 +505,17 @@
}
if (fifo->write_flags & O_NONBLOCK) {
- /* opened in non-blocking mode
- * return if there is not enough room available in the fifo
+ /*
+ * Device opened in non-blocking mode. Try to lock it and then
+ * check if there is any room to write the given buffer.
*/
+ if (!mutex_trylock(&fifo->write_lock))
+ return -EAGAIN;
+
if (words_to_write > ioread32(fifo->base_addr +
XLLF_TDFV_OFFSET)) {
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto end_unlock;
}
} else {
/* opened in blocking mode */
@@ -481,29 +523,23 @@
/* wait for an interrupt (or timeout) if there isn't
* currently enough room in the fifo
*/
- spin_lock_irq(&fifo->write_queue_lock);
- ret = wait_event_interruptible_lock_irq_timeout(
- fifo->write_queue,
+ mutex_lock(&fifo->write_lock);
+ ret = wait_event_interruptible_timeout(fifo->write_queue,
ioread32(fifo->base_addr + XLLF_TDFV_OFFSET)
- >= words_to_write,
- fifo->write_queue_lock,
- (write_timeout >= 0) ? msecs_to_jiffies(write_timeout) :
- MAX_SCHEDULE_TIMEOUT);
- spin_unlock_irq(&fifo->write_queue_lock);
+ >= words_to_write,
+ (write_timeout >= 0) ?
+ msecs_to_jiffies(write_timeout) :
+ MAX_SCHEDULE_TIMEOUT);
- if (ret == 0) {
- /* timeout occurred */
- dev_dbg(fifo->dt_device, "write timeout\n");
- return -EAGAIN;
- } else if (ret == -ERESTARTSYS) {
- /* signal received */
- return -ERESTARTSYS;
- } else if (ret < 0) {
- /* unknown error */
- dev_err(fifo->dt_device,
- "wait_event_interruptible_timeout() error in write (ret=%i)\n",
- ret);
- return ret;
+ if (ret <= 0) {
+ if (ret == 0) {
+ ret = -EAGAIN;
+ } else if (ret != -ERESTARTSYS) {
+ dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in write (ret=%i)\n",
+ ret);
+ }
+
+ goto end_unlock;
}
}
@@ -517,7 +553,8 @@
if (copy_from_user(tmp_buf, buf + copied * sizeof(u32),
copy * sizeof(u32))) {
reset_ip_core(fifo);
- return -EFAULT;
+ ret = -EFAULT;
+ goto end_unlock;
}
for (i = 0; i < copy; i++)
@@ -528,10 +565,15 @@
words_to_write -= copy;
}
- /* write packet size to fifo */
- iowrite32(copied * sizeof(u32), fifo->base_addr + XLLF_TLR_OFFSET);
+ ret = copied * sizeof(u32);
- return (ssize_t)copied * sizeof(u32);
+ /* write packet size to fifo */
+ iowrite32(ret, fifo->base_addr + XLLF_TLR_OFFSET);
+
+end_unlock:
+ mutex_unlock(&fifo->write_lock);
+
+ return ret;
}
static irqreturn_t axis_fifo_irq(int irq, void *dw)
@@ -702,6 +744,68 @@
return 0;
}
+static int axis_fifo_parse_dt(struct axis_fifo *fifo)
+{
+ int ret;
+ unsigned int value;
+
+ ret = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width", &value);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,axi-str-rxd-tdata-width property\n");
+ goto end;
+ } else if (value != 32) {
+ dev_err(fifo->dt_device, "xlnx,axi-str-rxd-tdata-width only supports 32 bits\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width", &value);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,axi-str-txd-tdata-width property\n");
+ goto end;
+ } else if (value != 32) {
+ dev_err(fifo->dt_device, "xlnx,axi-str-txd-tdata-width only supports 32 bits\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,rx-fifo-depth",
+ &fifo->rx_fifo_depth);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,rx-fifo-depth property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,tx-fifo-depth",
+ &fifo->tx_fifo_depth);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,tx-fifo-depth property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ /* IP sets TDFV to fifo depth - 4 so we will do the same */
+ fifo->tx_fifo_depth -= 4;
+
+ ret = get_dts_property(fifo, "xlnx,use-rx-data", &fifo->has_rx_fifo);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,use-rx-data property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = get_dts_property(fifo, "xlnx,use-tx-data", &fifo->has_tx_fifo);
+ if (ret) {
+ dev_err(fifo->dt_device, "missing xlnx,use-tx-data property\n");
+ ret = -EIO;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
static int axis_fifo_probe(struct platform_device *pdev)
{
struct resource *r_irq; /* interrupt resources */
@@ -712,34 +816,6 @@
char device_name[32];
int rc = 0; /* error return value */
-
- /* IP properties from device tree */
- unsigned int rxd_tdata_width;
- unsigned int txc_tdata_width;
- unsigned int txd_tdata_width;
- unsigned int tdest_width;
- unsigned int tid_width;
- unsigned int tuser_width;
- unsigned int data_interface_type;
- unsigned int has_tdest;
- unsigned int has_tid;
- unsigned int has_tkeep;
- unsigned int has_tstrb;
- unsigned int has_tuser;
- unsigned int rx_fifo_depth;
- unsigned int rx_programmable_empty_threshold;
- unsigned int rx_programmable_full_threshold;
- unsigned int axi_id_width;
- unsigned int axi4_data_width;
- unsigned int select_xpm;
- unsigned int tx_fifo_depth;
- unsigned int tx_programmable_empty_threshold;
- unsigned int tx_programmable_full_threshold;
- unsigned int use_rx_cut_through;
- unsigned int use_rx_data;
- unsigned int use_tx_control;
- unsigned int use_tx_cut_through;
- unsigned int use_tx_data;
/* ----------------------------
* init wrapper device
@@ -757,8 +833,8 @@
init_waitqueue_head(&fifo->read_queue);
init_waitqueue_head(&fifo->write_queue);
- spin_lock_init(&fifo->read_queue_lock);
- spin_lock_init(&fifo->write_queue_lock);
+ mutex_init(&fifo->read_lock);
+ mutex_init(&fifo->write_lock);
/* ----------------------------
* init device memory space
@@ -773,32 +849,19 @@
goto err_initial;
}
- fifo->mem = r_mem;
-
/* request physical memory */
- if (!request_mem_region(fifo->mem->start, resource_size(fifo->mem),
- DRIVER_NAME)) {
- dev_err(fifo->dt_device,
- "couldn't lock memory region at 0x%pa\n",
- &fifo->mem->start);
- rc = -EBUSY;
+ fifo->base_addr = devm_ioremap_resource(fifo->dt_device, r_mem);
+ if (IS_ERR(fifo->base_addr)) {
+ rc = PTR_ERR(fifo->base_addr);
+ dev_err(fifo->dt_device, "can't remap IO resource (%d)\n", rc);
goto err_initial;
}
- dev_dbg(fifo->dt_device, "got memory location [0x%pa - 0x%pa]\n",
- &fifo->mem->start, &fifo->mem->end);
- /* map physical memory to kernel virtual address space */
- fifo->base_addr = ioremap(fifo->mem->start, resource_size(fifo->mem));
- if (!fifo->base_addr) {
- dev_err(fifo->dt_device, "couldn't map physical memory\n");
- rc = -ENOMEM;
- goto err_mem;
- }
dev_dbg(fifo->dt_device, "remapped memory to 0x%p\n", fifo->base_addr);
/* create unique device name */
snprintf(device_name, sizeof(device_name), "%s_%pa",
- DRIVER_NAME, &fifo->mem->start);
+ DRIVER_NAME, &r_mem->start);
dev_dbg(fifo->dt_device, "device name [%s]\n", device_name);
@@ -807,164 +870,9 @@
* ----------------------------
*/
- /* retrieve device tree properties */
- rc = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width",
- &rxd_tdata_width);
+ rc = axis_fifo_parse_dt(fifo);
if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axi-str-txc-tdata-width",
- &txc_tdata_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width",
- &txd_tdata_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axis-tdest-width", &tdest_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axis-tid-width", &tid_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,axis-tuser-width", &tuser_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,data-interface-type",
- &data_interface_type);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tdest", &has_tdest);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tid", &has_tid);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tkeep", &has_tkeep);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tstrb", &has_tstrb);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,has-axis-tuser", &has_tuser);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,rx-fifo-depth", &rx_fifo_depth);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,rx-fifo-pe-threshold",
- &rx_programmable_empty_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,rx-fifo-pf-threshold",
- &rx_programmable_full_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,s-axi-id-width", &axi_id_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,s-axi4-data-width", &axi4_data_width);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,select-xpm", &select_xpm);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,tx-fifo-depth", &tx_fifo_depth);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,tx-fifo-pe-threshold",
- &tx_programmable_empty_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,tx-fifo-pf-threshold",
- &tx_programmable_full_threshold);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-rx-cut-through",
- &use_rx_cut_through);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-rx-data", &use_rx_data);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-tx-ctrl", &use_tx_control);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-tx-cut-through",
- &use_tx_cut_through);
- if (rc)
- goto err_unmap;
- rc = get_dts_property(fifo, "xlnx,use-tx-data", &use_tx_data);
- if (rc)
- goto err_unmap;
-
- /* check validity of device tree properties */
- if (rxd_tdata_width != 32) {
- dev_err(fifo->dt_device,
- "rxd_tdata_width width [%u] unsupported\n",
- rxd_tdata_width);
- rc = -EIO;
- goto err_unmap;
- }
- if (txd_tdata_width != 32) {
- dev_err(fifo->dt_device,
- "txd_tdata_width width [%u] unsupported\n",
- txd_tdata_width);
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tdest) {
- dev_err(fifo->dt_device, "tdest not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tid) {
- dev_err(fifo->dt_device, "tid not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tkeep) {
- dev_err(fifo->dt_device, "tkeep not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tstrb) {
- dev_err(fifo->dt_device, "tstrb not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (has_tuser) {
- dev_err(fifo->dt_device, "tuser not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (use_rx_cut_through) {
- dev_err(fifo->dt_device, "rx cut-through not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (use_tx_cut_through) {
- dev_err(fifo->dt_device, "tx cut-through not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
- if (use_tx_control) {
- dev_err(fifo->dt_device, "tx control not supported\n");
- rc = -EIO;
- goto err_unmap;
- }
-
- /* TODO
- * these exist in the device tree but it's unclear what they do
- * - select-xpm
- * - data-interface-type
- */
-
- /* set device wrapper properties based on IP config */
- fifo->rx_fifo_depth = rx_fifo_depth;
- /* IP sets TDFV to fifo depth - 4 so we will do the same */
- fifo->tx_fifo_depth = tx_fifo_depth - 4;
- fifo->has_rx_fifo = use_rx_data;
- fifo->has_tx_fifo = use_tx_data;
+ goto err_initial;
reset_ip_core(fifo);
@@ -977,18 +885,19 @@
r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!r_irq) {
dev_err(fifo->dt_device, "no IRQ found for 0x%pa\n",
- &fifo->mem->start);
+ &r_mem->start);
rc = -EIO;
- goto err_unmap;
+ goto err_initial;
}
/* request IRQ */
fifo->irq = r_irq->start;
- rc = request_irq(fifo->irq, &axis_fifo_irq, 0, DRIVER_NAME, fifo);
+ rc = devm_request_irq(fifo->dt_device, fifo->irq, &axis_fifo_irq, 0,
+ DRIVER_NAME, fifo);
if (rc) {
dev_err(fifo->dt_device, "couldn't allocate interrupt %i\n",
fifo->irq);
- goto err_unmap;
+ goto err_initial;
}
/* ----------------------------
@@ -999,7 +908,7 @@
/* allocate device number */
rc = alloc_chrdev_region(&fifo->devt, 0, 1, DRIVER_NAME);
if (rc < 0)
- goto err_irq;
+ goto err_initial;
dev_dbg(fifo->dt_device, "allocated device number major %i minor %i\n",
MAJOR(fifo->devt), MINOR(fifo->devt));
@@ -1023,14 +932,14 @@
}
/* create sysfs entries */
- rc = sysfs_create_group(&fifo->device->kobj, &axis_fifo_attrs_group);
+ rc = devm_device_add_group(fifo->device, &axis_fifo_attrs_group);
if (rc < 0) {
dev_err(fifo->dt_device, "couldn't register sysfs group\n");
goto err_cdev;
}
dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i, major=%i, minor=%i\n",
- &fifo->mem->start, &fifo->base_addr, fifo->irq,
+ &r_mem->start, &fifo->base_addr, fifo->irq,
MAJOR(fifo->devt), MINOR(fifo->devt));
return 0;
@@ -1041,12 +950,6 @@
device_destroy(axis_fifo_driver_class, fifo->devt);
err_chrdev_region:
unregister_chrdev_region(fifo->devt, 1);
-err_irq:
- free_irq(fifo->irq, fifo);
-err_unmap:
- iounmap(fifo->base_addr);
-err_mem:
- release_mem_region(fifo->mem->start, resource_size(fifo->mem));
err_initial:
dev_set_drvdata(dev, NULL);
return rc;
@@ -1057,15 +960,12 @@
struct device *dev = &pdev->dev;
struct axis_fifo *fifo = dev_get_drvdata(dev);
- sysfs_remove_group(&fifo->device->kobj, &axis_fifo_attrs_group);
cdev_del(&fifo->char_device);
dev_set_drvdata(fifo->device, NULL);
device_destroy(axis_fifo_driver_class, fifo->devt);
unregister_chrdev_region(fifo->devt, 1);
- free_irq(fifo->irq, fifo);
- iounmap(fifo->base_addr);
- release_mem_region(fifo->mem->start, resource_size(fifo->mem));
dev_set_drvdata(dev, NULL);
+
return 0;
}
@@ -1089,6 +989,8 @@
pr_info("axis-fifo driver loaded with parameters read_timeout = %i, write_timeout = %i\n",
read_timeout, write_timeout);
axis_fifo_driver_class = class_create(THIS_MODULE, DRIVER_NAME);
+ if (IS_ERR(axis_fifo_driver_class))
+ return PTR_ERR(axis_fifo_driver_class);
return platform_driver_register(&axis_fifo_driver);
}
--
Gitblit v1.6.2