lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Thu, 11 Nov 2010 21:24:07 +0000
From:	Sean Young <sean@...s.org>
To:	Alan Cox <alan@...rguk.ukuu.org.uk>
Cc:	linux-kernel@...r.kernel.org, jesse.barnes@...el.com,
	David Härdeman <david@...deman.nu>
Subject: [PATCH v2] Fix Winbond CIR and nsc-ircc driver initialisation

Booting a vanilla kernel results in:

[    4.771256] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    4.771365] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    4.771452] serial8250: ttyS1 at I/O 0x2f8 (irq = 3) is a NS16550A
[    4.771674] 00:03: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A

Which prevents the winbond-cir driver from initialising since ttyS1 is
a bastardised serial port, which can only be used for IR using the
winbond-cir driver.

[   13.947470] Winbond CIR 00:03: Region 0x2f8-0x2ff already in use!
[   13.947741] Winbond CIR 00:03: disabled
[   13.947746] Winbond CIR: probe of 00:03 failed with error -16

A workaround is to boot with argument 8250.nr_uarts=1. This is not really
desirable, so this patch makes ttyS1 go away when it's not a real
serial port.

The nsc-ircc suffers from the same problem.

Signed-off-by: Sean Young <sean@...s.org>
---
diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c
index 64f1de7..fa4e9e8 100644
--- a/drivers/input/misc/winbond-cir.c
+++ b/drivers/input/misc/winbond-cir.c
@@ -57,6 +57,7 @@
 #include <linux/bitrev.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/serial_8250.h>
 
 #define DRVNAME "winbond-cir"
 
@@ -1392,10 +1393,23 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	}
 
 	if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
-		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-			data->sbase, data->sbase + SP_IOMEM_LEN - 1);
-		err = -EBUSY;
-		goto exit_release_ebase;
+		bool ok = false;
+#ifdef CONFIG_SERIAL_8250
+		/*
+		 * This device is a hacked serial port which will be
+		 * detected by the serial 8250 driver.
+		 */
+		if (serial8250_port_non_uart(PORT_NS16550A, data->sbase,
+								data->irq)) {
+			ok = request_region(data->sbase, SP_IOMEM_LEN, DRVNAME);
+		}
+#endif
+		if (!ok) {
+			dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+				data->sbase, data->sbase + SP_IOMEM_LEN - 1);
+			err = -EBUSY;
+			goto exit_release_ebase;
+		}
 	}
 
 	err = request_irq(data->irq, wbcir_irq_handler,
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 559fe85..ccfdfd5 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -56,6 +56,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pnp.h>
 #include <linux/platform_device.h>
+#include <linux/serial_8250.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -406,6 +407,13 @@ static int __init nsc_ircc_open(chipio_t *info)
 	
 	/* Reserve the ioports that we need */
 	ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+#ifdef CONFIG_SERIAL_8250
+	if (!ret && serial8250_port_non_uart(PORT_NS16550A, self->io.fir_base,
+								self->io.irq)) {
+		ret = request_region(self->io.fir_base,
+						self->io.fir_ext, driver_name);
+	}
+#endif
 	if (!ret) {
 		IRDA_WARNING("%s(), can't get iobase of 0x%03x\n",
 			     __func__, self->io.fir_base);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 4d8e14b..6a30e05 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -3231,6 +3231,25 @@ void serial8250_unregister_port(int line)
 }
 EXPORT_SYMBOL(serial8250_unregister_port);
 
+bool serial8250_port_non_uart(uint type, uint iobase, uint irq)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		struct uart_port *p = &serial8250_ports[i].port;
+
+		if (p->iobase == iobase && p->irq == irq && p->type == type) {
+			printk(KERN_INFO "ttyS%d: not in uart mode\n",
+							serial_index(p));
+			serial8250_unregister_port(i);
+			return true;
+		}
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(serial8250_port_non_uart);
+
 static int __init serial8250_init(void)
 {
 	int ret;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 97f5b45..30cf6df 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -70,6 +70,7 @@ int serial8250_register_port(struct uart_port *);
 void serial8250_unregister_port(int line);
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
+bool serial8250_port_non_uart(uint type, uint iobase, uint irq);
 
 extern int early_serial_setup(struct uart_port *port);
 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ