[PATCH 17/41] TTY: pass flags to alloc_tty_driver

From: Jiri Slaby
Date: Tue Aug 07 2012 - 15:53:39 EST


We need to allow drivers that use neither tty_port_install nor
tty_port_register_device to link a tty_port to a tty somehow. To
avoid a race with open, this has to be performed before
tty_register_device. But currently tty_driver->ports is allocated even
in tty_register_device because we do not know whether this is the PTY
driver. The PTY driver is special here due to an excessive count of
lines it declares to handle. We cannot handle tty_ports there this
way.

To circumvent this, we start passing tty_driver flags to
alloc_tty_driver already and we create tty_alloc_driver for this
purpose. There we can allocate tty_driver->ports and do all the magic
between tty_alloc_driver and tty_register_device. Later we will
introduce tty_port_link_device function for that purpose.

All drivers should eventually switch to this new tty driver allocation
interface.

Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>
---
drivers/tty/tty_io.c | 34 +++++++++++++++++++++++++---------
include/linux/tty_driver.h | 23 +++++++++++++++++++----
2 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index c6f4d71..e024521 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3046,21 +3046,37 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
}
EXPORT_SYMBOL(tty_unregister_device);

-struct tty_driver *__alloc_tty_driver(int lines, struct module *owner)
+/**
+ * __tty_alloc_driver -- allocate tty driver
+ * @lines: count of lines this driver can handle at most
+ * @owner: module which is repsonsible for this driver
+ * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags
+ *
+ * This should not be called directly, some of the provided macros should be
+ * used instead. Use IS_ERR and friends on @retval.
+ */
+struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
+ unsigned long flags)
{
struct tty_driver *driver;

+ if (!lines)
+ return ERR_PTR(-EINVAL);
+
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
- if (driver) {
- kref_init(&driver->kref);
- driver->magic = TTY_DRIVER_MAGIC;
- driver->num = lines;
- driver->owner = owner;
- /* later we'll move allocation of tables here */
- }
+ if (!driver)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&driver->kref);
+ driver->magic = TTY_DRIVER_MAGIC;
+ driver->num = lines;
+ driver->owner = owner;
+ driver->flags = flags;
+ /* later we'll move allocation of tables here */
+
return driver;
}
-EXPORT_SYMBOL(__alloc_tty_driver);
+EXPORT_SYMBOL(__tty_alloc_driver);

static void destruct_tty_driver(struct kref *kref)
{
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 80e72dc..3adc362 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -296,11 +296,11 @@ struct tty_driver {
int name_base; /* offset of printed name */
int major; /* major device number */
int minor_start; /* start of minor device number */
- int num; /* number of devices allocated */
+ unsigned int num; /* number of devices allocated */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
struct ktermios init_termios; /* Initial termios */
- int flags; /* tty driver flags */
+ unsigned long flags; /* tty driver flags */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
struct tty_driver *other; /* only used for the PTY driver */

@@ -322,7 +322,8 @@ struct tty_driver {

extern struct list_head tty_drivers;

-extern struct tty_driver *__alloc_tty_driver(int lines, struct module *owner);
+extern struct tty_driver *__tty_alloc_driver(unsigned int lines,
+ struct module *owner, unsigned long flags);
extern void put_tty_driver(struct tty_driver *driver);
extern void tty_set_operations(struct tty_driver *driver,
const struct tty_operations *op);
@@ -330,7 +331,21 @@ extern struct tty_driver *tty_find_polling_driver(char *name, int *line);

extern void tty_driver_kref_put(struct tty_driver *driver);

-#define alloc_tty_driver(lines) __alloc_tty_driver(lines, THIS_MODULE)
+/* Use TTY_DRIVER_* flags below */
+#define tty_alloc_driver(lines, flags) \
+ __tty_alloc_driver(lines, THIS_MODULE, flags)
+
+/*
+ * DEPRECATED Do not use this in new code, use tty_alloc_driver instead.
+ * (And change the return value checks.)
+ */
+static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
+{
+ struct tty_driver *ret = tty_alloc_driver(lines, 0);
+ if (IS_ERR(ret))
+ return NULL;
+ return ret;
+}

static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
{
--
1.7.10.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/