LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Johan Hovold <johan@kernel.org>
Cc: Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Andreas Kemnade <andreas@kemnade.info>,
	Arnd Bergmann <arnd@arndb.de>,
	"H . Nikolaus Schaller" <hns@goldelico.com>,
	Pavel Machek <pavel@ucw.cz>,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH 1/7] gnss: add GNSS receiver subsystem
Date: Wed, 25 Apr 2018 10:56:49 +0200	[thread overview]
Message-ID: <20180425085649.GB13295@kroah.com> (raw)
In-Reply-To: <20180424163458.11947-2-johan@kernel.org>

On Tue, Apr 24, 2018 at 06:34:52PM +0200, Johan Hovold wrote:
> +#define GNSS_MINORS	16

Why only 16?  Just have to start somewhere?

> +static DEFINE_IDA(gnss_minors);
> +static dev_t gnss_first;
> +
> +/* FIFO size must be a power of two */
> +#define GNSS_READ_FIFO_SIZE	4096
> +#define GNSS_WRITE_BUF_SIZE	1024
> +
> +#define to_gnss_device(d) container_of((d), struct gnss_device, dev)
> +
> +static int gnss_open(struct inode *inode, struct file *file)
> +{
> +	struct gnss_device *gdev;
> +	int ret = 0;
> +
> +	gdev = container_of(inode->i_cdev, struct gnss_device, cdev);
> +
> +	get_device(&gdev->dev);
> +
> +	nonseekable_open(inode, file);
> +	file->private_data = gdev;
> +
> +	down_write(&gdev->rwsem);

Just curious, why a rwsem?  They can be slower than a normal semaphore,
is this really a contentious lock?

> +	if (gdev->disconnected) {
> +		ret = -ENODEV;
> +		goto unlock;
> +	}
> +
> +	if (gdev->count++ == 0) {
> +		ret = gdev->ops->open(gdev);
> +		if (ret)
> +			gdev->count--;

Why do we care about the opens here?  Do you only want the "child
driver" to have open called once, like a tty driver?  Does it matter?

Again, just curious.


> +	}
> +unlock:
> +	up_write(&gdev->rwsem);
> +
> +	if (ret)
> +		goto err_put_device;
> +
> +	return 0;
> +
> +err_put_device:
> +	put_device(&gdev->dev);
> +
> +	return ret;

Those last 9 lines can be rewritten as just:

	if (!ret)
		put_device(&gdev->dev);

	return ret;

> +}
> +
> +static int gnss_release(struct inode *inode, struct file *file)
> +{
> +	struct gnss_device *gdev = file->private_data;
> +
> +	down_write(&gdev->rwsem);
> +	if (gdev->disconnected)
> +		goto unlock;
> +
> +	if (--gdev->count == 0) {
> +		gdev->ops->close(gdev);
> +		kfifo_reset(&gdev->read_fifo);
> +	}
> +unlock:
> +	up_write(&gdev->rwsem);
> +
> +	put_device(&gdev->dev);
> +
> +	return 0;
> +}
> +
> +static ssize_t gnss_read(struct file *file, char __user *buf,
> +		size_t count, loff_t *pos)
> +{
> +	struct gnss_device *gdev = file->private_data;
> +	unsigned int copied;
> +	int ret;
> +
> +	mutex_lock(&gdev->read_mutex);
> +	while (kfifo_is_empty(&gdev->read_fifo)) {
> +		mutex_unlock(&gdev->read_mutex);
> +
> +		if (gdev->disconnected)
> +			return 0;
> +
> +		if (file->f_flags & O_NONBLOCK)
> +			return -EAGAIN;
> +
> +		ret = wait_event_interruptible(gdev->read_queue,
> +				gdev->disconnected ||
> +				!kfifo_is_empty(&gdev->read_fifo));
> +		if (ret)
> +			return -ERESTARTSYS;
> +
> +		mutex_lock(&gdev->read_mutex);
> +	}
> +
> +	ret = kfifo_to_user(&gdev->read_fifo, buf, count, &copied);
> +	if (ret)
> +		goto out_unlock;
> +
> +	ret = copied;
> +
> +	dev_dbg(&gdev->dev, "%s - count = %zu\n", __func__, copied);
> +
> +out_unlock:
> +	mutex_unlock(&gdev->read_mutex);
> +
> +	return ret;
> +}
> +
> +static ssize_t gnss_write(struct file *file, const char __user *buf,
> +		size_t count, loff_t *pos)
> +{
> +	struct gnss_device *gdev = file->private_data;
> +	size_t written = 0;
> +	int ret;
> +
> +	dev_dbg(&gdev->dev, "%s - count = %zu\n", __func__, count);

Nit, some of these initial dev_dbg() calls might be able to be removed,
as ftrace should handle the tracing code now, right?

> +
> +	if (gdev->disconnected) {
> +		dev_dbg(&gdev->dev, "%s - disconnected\n", __func__);
> +		return -EIO;
> +	}
> +
> +	if (!count)
> +		return 0;
> +
> +	if (!gdev->ops->write_raw)
> +		return -EIO;
> +
> +	/* Ignoring O_NONBLOCK, write_raw() is synchronous. */
> +
> +	ret = mutex_lock_interruptible(&gdev->write_mutex);
> +	if (ret)
> +		return -ERESTARTSYS;
> +
> +	for (;;) {
> +		size_t n = count - written;
> +
> +		if (n > GNSS_WRITE_BUF_SIZE)
> +			n = GNSS_WRITE_BUF_SIZE;
> +
> +		if (copy_from_user(gdev->write_buf, buf, n)) {
> +			ret = -EFAULT;
> +			goto out_unlock;
> +		}
> +
> +		/*
> +		 * Assumes write_raw can always accept GNSS_WRITE_BUF_SIZE
> +		 * bytes.
> +		 *
> +		 * FIXME: revisit
> +		 */
> +		down_read(&gdev->rwsem);
> +		if (!gdev->disconnected)
> +			ret = gdev->ops->write_raw(gdev, gdev->write_buf, n);
> +		else
> +			ret = -EIO;
> +		up_read(&gdev->rwsem);
> +
> +		if (ret < 0)
> +			break;
> +
> +		written += ret;
> +		buf += ret;
> +
> +		if (written == count)
> +			break;
> +	}
> +
> +	if (written)
> +		ret = written;
> +out_unlock:
> +	mutex_unlock(&gdev->write_mutex);
> +
> +	return ret;
> +}
> +
> +static __poll_t gnss_poll(struct file *file, poll_table *wait)
> +{
> +	struct gnss_device *gdev = file->private_data;
> +	__poll_t mask = 0;
> +
> +	poll_wait(file, &gdev->read_queue, wait);
> +
> +	if (!kfifo_is_empty(&gdev->read_fifo))
> +		mask |= EPOLLIN | EPOLLRDNORM;
> +	if (gdev->disconnected)
> +		mask |= EPOLLHUP;
> +
> +	dev_dbg(&gdev->dev, "%s - mask = 0x%04x\n", __func__, mask);
> +
> +	return mask;
> +}
> +
> +static const struct file_operations gnss_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= gnss_open,
> +	.release	= gnss_release,
> +	.read		= gnss_read,
> +	.write		= gnss_write,
> +	.poll		= gnss_poll,
> +	.llseek		= no_llseek,
> +};
> +
> +static struct class *gnss_class;
> +
> +static void gnss_device_release(struct device *dev)
> +{
> +	struct gnss_device *gdev = to_gnss_device(dev);
> +
> +	dev_dbg(dev, "%s\n", __func__);
> +
> +	kfree(gdev->write_buf);
> +	kfifo_free(&gdev->read_fifo);
> +	ida_simple_remove(&gnss_minors, gdev->id);
> +	kfree(gdev);
> +}
> +
> +struct gnss_device *gnss_allocate_device(struct device *parent)
> +{
> +	struct gnss_device *gdev;
> +	struct device *dev;
> +	int id;
> +	int ret;
> +
> +	gdev = kzalloc(sizeof(*gdev), GFP_KERNEL);
> +	if (!gdev)
> +		return NULL;
> +
> +	id = ida_simple_get(&gnss_minors, 0, GNSS_MINORS, GFP_KERNEL);
> +	if (id < 0) {
> +		kfree(gdev);
> +		return ERR_PTR(id);
> +	}
> +
> +	gdev->id = id;
> +
> +	dev = &gdev->dev;
> +	device_initialize(dev);
> +	dev->devt = gnss_first + id;
> +	dev->class = gnss_class;
> +	dev->parent = parent;
> +	dev->release = gnss_device_release;
> +	dev_set_drvdata(dev, gdev);
> +	dev_set_name(dev, "gnss%d", id);
> +
> +	init_rwsem(&gdev->rwsem);
> +	mutex_init(&gdev->read_mutex);
> +	mutex_init(&gdev->write_mutex);
> +	init_waitqueue_head(&gdev->read_queue);
> +
> +	ret = kfifo_alloc(&gdev->read_fifo, GNSS_READ_FIFO_SIZE, GFP_KERNEL);
> +	if (ret)
> +		goto err_put_device;
> +
> +	gdev->write_buf = kzalloc(GNSS_WRITE_BUF_SIZE, GFP_KERNEL);
> +	if (!gdev->write_buf)
> +		goto err_put_device;
> +
> +	cdev_init(&gdev->cdev, &gnss_fops);
> +	gdev->cdev.owner = THIS_MODULE;

This protects this module from being unloaded, but how do you pass on
the module reference counts to the "child" gnss driver?  Am I just
missing that logic here somewhere?

Anyway, minor things, this looks really clean, nice job.

greg k-h

  reply	other threads:[~2018-04-25  8:56 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-24 16:34 [PATCH 0/7] gnss: add new GNSS subsystem Johan Hovold
2018-04-24 16:34 ` [PATCH 1/7] gnss: add GNSS receiver subsystem Johan Hovold
2018-04-25  8:56   ` Greg Kroah-Hartman [this message]
2018-04-25 10:56     ` Johan Hovold
2018-04-25 12:23       ` Johan Hovold
2018-04-29 13:35         ` Greg Kroah-Hartman
2018-05-02  7:57           ` Johan Hovold
2018-04-24 16:34 ` [PATCH 2/7] dt-bindings: add generic gnss binding Johan Hovold
2018-04-25 18:26   ` Rob Herring
2018-04-24 16:34 ` [PATCH 3/7] gnss: add generic serial driver Johan Hovold
2018-04-25  8:57   ` Greg Kroah-Hartman
2018-04-25 10:58     ` Johan Hovold
2018-04-25  9:00   ` Greg Kroah-Hartman
2018-04-25 11:05     ` Johan Hovold
2018-04-24 16:34 ` [PATCH 4/7] dt-bindings: gnss: add u-blox binding Johan Hovold
2018-04-25 18:16   ` Rob Herring
2018-04-26  9:10     ` Johan Hovold
2018-05-01 14:05       ` Rob Herring
2018-05-02  8:16         ` Johan Hovold
2018-05-02 13:16           ` Rob Herring
2018-05-07  9:06             ` Johan Hovold
2018-05-03  9:35           ` H. Nikolaus Schaller
2018-05-03 18:50             ` Andreas Kemnade
2018-05-04  5:16               ` H. Nikolaus Schaller
2018-05-04 11:42                 ` Sebastian Reichel
2018-05-04 12:04                   ` H. Nikolaus Schaller
2018-05-04 13:37                     ` Sebastian Reichel
2018-05-04 14:29                       ` Tony Lindgren
2018-05-07 10:07                     ` Johan Hovold
2018-05-07 10:01                   ` Johan Hovold
2018-05-07 15:45                     ` Tony Lindgren
2018-05-07 16:34                       ` Johan Hovold
2018-05-07 17:50                         ` Tony Lindgren
2018-05-08  6:58                           ` Johan Hovold
2018-05-08 15:22                             ` Tony Lindgren
2018-05-08 15:47                               ` Tony Lindgren
2018-05-08 15:54                                 ` Tony Lindgren
2018-05-08 16:49                                   ` Tony Lindgren
2018-05-09 13:10                                     ` OMAP serial runtime PM and autosuspend (was: Re: [PATCH 4/7] dt-bindings: gnss: add u-blox binding)) Johan Hovold
2018-05-09 13:57                                       ` Tony Lindgren
2018-05-17 10:09                                         ` Johan Hovold
2018-05-17 17:10                                           ` Tony Lindgren
2018-05-21 13:48                                             ` Johan Hovold
2018-05-21 15:48                                               ` Tony Lindgren
2018-05-24  9:17                                                 ` Johan Hovold
2018-05-24 13:32                                                   ` Tony Lindgren
2018-05-25 14:02                                                     ` Johan Hovold
2018-05-08 15:56                         ` [PATCH 4/7] dt-bindings: gnss: add u-blox binding Sebastian Reichel
2018-05-09  9:18                           ` Serdev runtime PM (was: Re: [PATCH 4/7] dt-bindings: gnss: add u-blox binding) Johan Hovold
2018-05-09  9:49                             ` Johan Hovold
2018-05-09 14:05                             ` Tony Lindgren
2018-05-17 10:25                               ` Johan Hovold
2018-05-07  9:47             ` [PATCH 4/7] dt-bindings: gnss: add u-blox binding Johan Hovold
2018-04-24 16:34 ` [PATCH 5/7] gnss: add driver for u-blox receivers Johan Hovold
2018-04-24 16:34 ` [PATCH 6/7] dt-bindings: gnss: add sirfstar binding Johan Hovold
2018-04-25 18:25   ` Rob Herring
2018-04-26  9:12     ` Johan Hovold
2018-04-24 16:34 ` [PATCH 7/7] gnss: add driver for sirfstar-based receivers Johan Hovold
2018-04-24 17:40 ` [PATCH 0/7] gnss: add new GNSS subsystem H. Nikolaus Schaller
2018-04-24 17:50   ` Johan Hovold
2018-04-24 19:44     ` H. Nikolaus Schaller
2018-04-25  8:11       ` Johan Hovold
2018-04-26 10:10         ` H. Nikolaus Schaller
2018-04-26 18:21           ` Johan Hovold
2018-04-24 20:13 ` Pavel Machek
2018-04-24 20:59   ` Andreas Kemnade
2018-04-25  7:32     ` Johan Hovold
2018-04-25  6:49   ` Marcel Holtmann
2018-04-25  7:24   ` Johan Hovold
2018-04-24 20:38 ` Pavel Machek
2018-04-25  6:26 ` Pavel Machek
2018-04-25  6:51   ` Johan Hovold
2018-04-25  8:48 ` Greg Kroah-Hartman
2018-04-25 10:31   ` Johan Hovold
2018-05-04 13:27 ` Sebastian Reichel
2018-05-04 20:03   ` Pavel Machek
2018-05-05 17:28     ` Sebastian Reichel
2018-05-05 21:11       ` Pavel Machek
2018-05-06  6:47         ` Marcel Holtmann
2018-05-07 10:20   ` Johan Hovold
2018-05-07 19:06     ` Marcel Holtmann
2018-05-08  7:01       ` Johan Hovold
2018-05-08  7:49         ` Marcel Holtmann
2018-05-08 12:48           ` Johan Hovold
2018-05-08 20:03             ` Marcel Holtmann
2018-05-30 10:26               ` Johan Hovold

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180425085649.GB13295@kroah.com \
    --to=gregkh@linuxfoundation.org \
    --cc=andreas@kemnade.info \
    --cc=arnd@arndb.de \
    --cc=devicetree@vger.kernel.org \
    --cc=hns@goldelico.com \
    --cc=johan@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=pavel@ucw.cz \
    --cc=robh+dt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).