Thread (79 messages) flat view 79 messages, 11 authors, 2015-06-06

Re: [PATCH 2/3] TTY: add support for tty_slave devices.

From: Jiri Slaby <hidden>
Date: 2015-03-24 10:32:07
Also in: lkml

Hi,

On 03/18/2015, 06:58 AM, NeilBrown wrote:
quoted hunk ↗ jump to hunk
--- /dev/null
+++ b/drivers/tty/slave/tty_slave_core.c
@@ -0,0 +1,136 @@
...
+static int tty_slave_match(struct device *dev, struct device_driver *drv)
+{
+	return of_driver_match_device(dev, drv);
+}
+
+static void tty_slave_release(struct device *dev)
+{
+	kfree(dev);
This should free the slave where the dev is contained. This is never
called IMO due to missing put_device's in the code.
+}
+
+struct bus_type tty_slave_bus_type = {
+	.name		= "tty-slave",
+	.match		= tty_slave_match,
+};
+
+int tty_slave_register(struct device *parent, struct device_node *node,
+		       struct device *tty, struct tty_driver *drv)
+{
+	struct tty_slave *slave;
+	int retval;
+
+	if (!of_get_property(node, "compatible", NULL))
+		return -ENODEV;
+
+	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+	if (!slave)
+		return -ENOMEM;
+
device_initialize();
+	slave->dev.bus = &tty_slave_bus_type;
+	slave->dev.parent = parent;
+	slave->dev.release = tty_slave_release;
+	slave->dev.of_node = of_node_get(node);
+	dev_set_name(&slave->dev, "%s", node->name);
+	slave->tty_dev = tty;
+	slave->tty_drv = drv;
+	slave->ops = *drv->ops;
+	retval = device_register(&slave->dev);
+	if (retval) {
+		of_node_put(node);
+		kfree(slave);
Do device_put() instead of the two. And do the two in .release.
+	}
+	return retval;
+}
+EXPORT_SYMBOL(tty_slave_register);
...
quoted hunk ↗ jump to hunk
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
...
quoted hunk ↗ jump to hunk
@@ -3205,6 +3208,29 @@ static void tty_device_create_release(struct device *dev)
 	kfree(dev);
 }
 
+int tty_register_finalize(struct tty_driver *driver, struct device *dev)
+{
+	int retval;
+	bool cdev = false;
+	int index = dev->devt - MKDEV(driver->major,
+				      driver->minor_start);
+	printk("REGISTER %d %d 0x%x %d\n", driver->major, driver->minor_start, dev->devt, index);
+	if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+		retval = tty_cdev_add(driver,
+				      dev->devt,
+				      index, 1);
+		if (retval)
+			return retval;
+		cdev = true;
+	}
+	retval = device_register(dev);
+	if (retval == 0)
+		return 0;
+	if (cdev)
+		cdev_del(&driver->cdevs[index]);
+	return retval;
+}
+EXPORT_SYMBOL(tty_register_finalize);
 /**
  *	tty_register_device_attr - register a tty device
  *	@driver: the tty driver that describes the tty device
@@ -3234,7 +3260,8 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 	dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
 	struct device *dev = NULL;
 	int retval = -ENODEV;
-	bool cdev = false;
+	struct device_node *node;
+	bool slave_registered = false;
 
 	if (index >= driver->num) {
 		printk(KERN_ERR "Attempt to register invalid tty line number "
@@ -3247,13 +3274,6 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 	else
 		tty_line_name(driver, index, name);
 
-	if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
-		retval = tty_cdev_add(driver, devt, index, 1);
-		if (retval)
-			goto error;
-		cdev = true;
-	}
-
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
 		retval = -ENOMEM;
@@ -3268,16 +3288,24 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 	dev->groups = attr_grp;
 	dev_set_drvdata(dev, drvdata);
 
-	retval = device_register(dev);
-	if (retval)
-		goto error;
+	if (device && device->of_node)
+		for_each_available_child_of_node(device->of_node, node) {
+			if (tty_slave_register(device, node, dev, driver) == 0)
+				slave_registered = true;
+			if (slave_registered)
+				break;
+		}
+
+	if (!slave_registered) {
+		retval = tty_register_finalize(driver, dev);
+		if (retval)
+			goto error;
+	}
 
 	return dev;
And what about ttys not using the tty_register_device* helpers?

What happens when the tty is unregistered?
quoted hunk ↗ jump to hunk
--- /dev/null
+++ b/include/linux/tty_slave.h
@@ -0,0 +1,26 @@
+
+struct tty_slave {
+	struct device *tty_dev;
+	struct tty_driver *tty_drv;
+	struct tty_operations ops;
+	struct device dev;
+};
+
+int tty_slave_finalize(struct tty_slave *slave);
+int tty_slave_driver_register(struct device_driver *drv);
+#if config_enabled(CONFIG_TTY_SLAVE)
Since TTY_SLAVE is tristate, this will work only for TTY_SLAVE == y, not
m. Use IS_ENABLED instead.
+void tty_slave_activate(struct tty_struct *tty);
+int tty_slave_register(struct device *parent, struct device_node *node,
+		       struct device *tty, struct tty_driver *drv);
+#else
+static inline void tty_slave_activate(struct tty_struct *tty)
+{
+}
+static inline int tty_slave_register(struct device *parent,
+				     struct device_node *node,
+				     struct device *tty,
+				     struct tty_driver *drv)
+{
+	return -ENODEV;
+}
+#endif
thanks,
-- 
js
suse labs
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help