In a multi-platform scenario, the hard-coded major/minor numbers in serial drivers may conflict with each other. A typical scenario is observed with amba-pl011 and samsung-uart drivers, both of these drivers use same set of major/minor numbers. If both of these drivers are enabled, probe of samsung-uart driver fails because the desired node is busy.
The issue is fixed by adding a fallback in driver core, so that we can use dynamic major number in case device node allocation fails for hard-coded major/minor number.
Signed-off-by: Tushar Behera tushar.behera@linaro.org --- Initial approach to fix this problem was by forcing samsung-uart driver to use dynamic major number, but it was rejected [1] because of possible user-space breakage. Current approach falls back to dynamic major number as a fallback in case of failure. [1] https://lkml.org/lkml/2013/12/27/2
Can I get an Acked-by/Reviewed-by before I send this to lkml?
Changes for V2: * Added warning message in case major number is getting orverriden
drivers/tty/tty_io.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c74a00a..ff4aada 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3341,6 +3341,24 @@ int tty_register_driver(struct tty_driver *driver) dev_t dev; struct device *d;
+ if (driver->major) { + dev = MKDEV(driver->major, driver->minor_start); + error = register_chrdev_region(dev, driver->num, driver->name); + /* In case of error, fall back to dynamic allocation */ + if (error < 0) { + printk(KERN_WARNING + "Default device node (%d:%d) for %s is busy, " + "using dynamic major number\n", + driver->major, driver->minor_start, + driver->name); + driver->major = 0; + } + } + + /* + * Don't replace the following check with an else to above if statement, + * as it may also be called as a fallback. + */ if (!driver->major) { error = alloc_chrdev_region(&dev, driver->minor_start, driver->num, driver->name); @@ -3348,9 +3366,6 @@ int tty_register_driver(struct tty_driver *driver) driver->major = MAJOR(dev); driver->minor_start = MINOR(dev); } - } else { - dev = MKDEV(driver->major, driver->minor_start); - error = register_chrdev_region(dev, driver->num, driver->name); } if (error < 0) goto err;
On Wed, Jan 15, 2014 at 03:00:51PM +0530, Tushar Behera wrote:
In a multi-platform scenario, the hard-coded major/minor numbers in serial drivers may conflict with each other. A typical scenario is observed with amba-pl011 and samsung-uart drivers, both of these
You really need to submit this to see if Greg is OK with the approach. Feel free to blame me for the idea if you're worried about him getting angry. I'd add some discussion to the changelog about how this will have no effect on already working systems, and I would consider making this controllable by a Kconfig option (possibly as a followup patch so the first one has more chance of getting merged).
printk(KERN_WARNING
"Default device node (%d:%d) for %s is busy, "
"using dynamic major number\n",
driver->major, driver->minor_start,
driver->name);
driver->major = 0;
Don't split log mesages over multiple lines, this makes it harder to grep for them.
linaro-kernel@lists.linaro.org