aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/pi433/pi433_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/pi433/pi433_if.c')
-rw-r--r--drivers/staging/pi433/pi433_if.c93
1 files changed, 49 insertions, 44 deletions
diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c
index b061f77dda41..c85a805a1243 100644
--- a/drivers/staging/pi433/pi433_if.c
+++ b/drivers/staging/pi433/pi433_if.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* userspace interface for pi433 radio module
*
@@ -65,10 +66,12 @@ static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */
static struct class *pi433_class; /* mainly for udev to create /dev/pi433 */
-/* tx config is instance specific
+/*
+ * tx config is instance specific
* so with each open a new tx config struct is needed
*/
-/* rx config is device specific
+/*
+ * rx config is device specific
* so we have just one rx config, ebedded in device struct
*/
struct pi433_device {
@@ -78,7 +81,6 @@ struct pi433_device {
struct device *dev;
struct cdev *cdev;
struct spi_device *spi;
- unsigned int users;
/* irq related values */
struct gpio_desc *gpiod[NUM_DIO];
@@ -584,7 +586,8 @@ pi433_tx_thread(void *data)
if (kthread_should_stop())
return 0;
- /* get data from fifo in the following order:
+ /*
+ * get data from fifo in the following order:
* - tx_cfg
* - size of message
* - message
@@ -639,7 +642,8 @@ pi433_tx_thread(void *data)
dev_dbg(device->dev,
"read %d message byte(s) from fifo queue.", retval);
- /* if rx is active, we need to interrupt the waiting for
+ /*
+ * if rx is active, we need to interrupt the waiting for
* incoming telegrams, to be able to send something.
* We are only allowed, if currently no reception takes
* place otherwise we need to wait for the incoming telegram
@@ -649,14 +653,16 @@ pi433_tx_thread(void *data)
!device->rx_active ||
device->interrupt_rx_allowed);
- /* prevent race conditions
+ /*
+ * prevent race conditions
* irq will be reenabled after tx config is set
*/
disable_irq(device->irq_num[DIO0]);
device->tx_active = true;
if (device->rx_active && !rx_interrupted) {
- /* rx is currently waiting for a telegram;
+ /*
+ * rx is currently waiting for a telegram;
* we need to set the radio module to standby
*/
retval = rf69_set_mode(device->spi, standby);
@@ -826,11 +832,15 @@ pi433_write(struct file *filp, const char __user *buf,
instance = filp->private_data;
device = instance->device;
- /* check, whether internal buffer (tx thread) is big enough for requested size */
+ /*
+ * check, whether internal buffer (tx thread) is big enough
+ * for requested size
+ */
if (count > MAX_MSG_SIZE)
return -EMSGSIZE;
- /* write the following sequence into fifo:
+ /*
+ * write the following sequence into fifo:
* - tx_cfg
* - size of message
* - message
@@ -880,15 +890,13 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
int retval = 0;
struct pi433_instance *instance;
struct pi433_device *device;
+ struct pi433_tx_cfg tx_cfg;
void __user *argp = (void __user *)arg;
/* Check type and command number */
if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC)
return -ENOTTY;
- /* TODO? guard against device removal before, or while,
- * we issue this ioctl. --> device_get()
- */
instance = filp->private_data;
device = instance->device;
@@ -902,9 +910,11 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EFAULT;
break;
case PI433_IOC_WR_TX_CFG:
- if (copy_from_user(&instance->tx_cfg, argp,
- sizeof(struct pi433_tx_cfg)))
+ if (copy_from_user(&tx_cfg, argp, sizeof(struct pi433_tx_cfg)))
return -EFAULT;
+ mutex_lock(&device->tx_fifo_lock);
+ memcpy(&instance->tx_cfg, &tx_cfg, sizeof(struct pi433_tx_cfg));
+ mutex_unlock(&device->tx_fifo_lock);
break;
case PI433_IOC_RD_RX_CFG:
if (copy_to_user(argp, &device->rx_cfg,
@@ -960,19 +970,9 @@ static int pi433_open(struct inode *inode, struct file *filp)
return -ENODEV;
}
- if (!device->rx_buffer) {
- device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL);
- if (!device->rx_buffer)
- return -ENOMEM;
- }
-
- device->users++;
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
- if (!instance) {
- kfree(device->rx_buffer);
- device->rx_buffer = NULL;
+ if (!instance)
return -ENOMEM;
- }
/* setup instance data*/
instance->device = device;
@@ -989,23 +989,11 @@ static int pi433_open(struct inode *inode, struct file *filp)
static int pi433_release(struct inode *inode, struct file *filp)
{
struct pi433_instance *instance;
- struct pi433_device *device;
instance = filp->private_data;
- device = instance->device;
kfree(instance);
filp->private_data = NULL;
- /* last close? */
- device->users--;
-
- if (!device->users) {
- kfree(device->rx_buffer);
- device->rx_buffer = NULL;
- if (!device->spi)
- kfree(device);
- }
-
return 0;
}
@@ -1115,7 +1103,8 @@ static void pi433_free_minor(struct pi433_device *dev)
static const struct file_operations pi433_fops = {
.owner = THIS_MODULE,
- /* REVISIT switch to aio primitives, so that userspace
+ /*
+ * REVISIT switch to aio primitives, so that userspace
* gets more complete API coverage. It'll simplify things
* too, except for the locking.
*/
@@ -1138,7 +1127,10 @@ static int pi433_probe(struct spi_device *spi)
/* setup spi parameters */
spi->mode = 0x00;
spi->bits_per_word = 8;
- /* spi->max_speed_hz = 10000000; 1MHz already set by device tree overlay */
+ /*
+ * spi->max_speed_hz = 10000000;
+ * 1MHz already set by device tree overlay
+ */
retval = spi_setup(spi);
if (retval) {
@@ -1175,6 +1167,13 @@ static int pi433_probe(struct spi_device *spi)
device->tx_active = false;
device->interrupt_rx_allowed = false;
+ /* init rx buffer */
+ device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL);
+ if (!device->rx_buffer) {
+ retval = -ENOMEM;
+ goto RX_failed;
+ }
+
/* init wait queues */
init_waitqueue_head(&device->tx_wait_queue);
init_waitqueue_head(&device->rx_wait_queue);
@@ -1250,6 +1249,7 @@ static int pi433_probe(struct spi_device *spi)
device->minor);
if (IS_ERR(device->tx_task_struct)) {
dev_dbg(device->dev, "start of send thread failed");
+ retval = PTR_ERR(device->tx_task_struct);
goto send_thread_failed;
}
@@ -1277,6 +1277,8 @@ device_create_failed:
minor_failed:
free_gpio(device);
GPIO_failed:
+ kfree(device->rx_buffer);
+RX_failed:
kfree(device);
return retval;
@@ -1300,8 +1302,8 @@ static int pi433_remove(struct spi_device *spi)
pi433_free_minor(device);
- if (device->users == 0)
- kfree(device);
+ kfree(device->rx_buffer);
+ kfree(device);
return 0;
}
@@ -1322,7 +1324,8 @@ static struct spi_driver pi433_spi_driver = {
.probe = pi433_probe,
.remove = pi433_remove,
- /* NOTE: suspend/resume methods are not necessary here.
+ /*
+ * NOTE: suspend/resume methods are not necessary here.
* We don't do anything except pass the requests to/from
* the underlying controller. The refrigerator handles
* most issues; the controller driver handles the rest.
@@ -1335,13 +1338,15 @@ static int __init pi433_init(void)
{
int status;
- /* If MAX_MSG_SIZE is smaller then FIFO_SIZE, the driver won't
+ /*
+ * If MAX_MSG_SIZE is smaller then FIFO_SIZE, the driver won't
* work stable - risk of buffer overflow
*/
if (MAX_MSG_SIZE < FIFO_SIZE)
return -EINVAL;
- /* Claim device numbers. Then register a class
+ /*
+ * Claim device numbers. Then register a class
* that will key udev/mdev to add/remove /dev nodes. Last, register
* Last, register the driver which manages those device numbers.
*/