mxser: allow overlapping vector
authorJiri Slaby <jslaby@suse.cz>
Tue, 7 Aug 2012 19:47:37 +0000 (21:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Aug 2012 20:29:57 +0000 (13:29 -0700)
For many cards, this saves some IO space because interrupt status port
has precedence over the rest of ports on the card. Hence it can be
mapped to a hole in I/O ports.

Here we add a kernel parameter which allows that if a user wants to.
But they need to explicitly enable it by a module parameter.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/mxser.c

index c162ee93116750dbcaabd01f633fe010b5bb6c96..e64fe40618cd90b0b83beb18c78c551460374810 100644 (file)
@@ -2337,11 +2337,36 @@ static struct tty_port_operations mxser_port_ops = {
  * The MOXA Smartio/Industio serial driver boot-time initialization code!
  */
 
+static bool allow_overlapping_vector;
+module_param(allow_overlapping_vector, bool, 444);
+MODULE_PARM_DESC(allow_overlapping_vector, "whether we allow ISA cards to be configured such that vector overlabs IO ports (default=no)");
+
+static bool mxser_overlapping_vector(struct mxser_board *brd)
+{
+       return allow_overlapping_vector &&
+               brd->vector >= brd->ports[0].ioaddr &&
+               brd->vector < brd->ports[0].ioaddr + 8 * brd->info->nports;
+}
+
+static int mxser_request_vector(struct mxser_board *brd)
+{
+       if (mxser_overlapping_vector(brd))
+               return 0;
+       return request_region(brd->vector, 1, "mxser(vector)") ? 0 : -EIO;
+}
+
+static void mxser_release_vector(struct mxser_board *brd)
+{
+       if (mxser_overlapping_vector(brd))
+               return;
+       release_region(brd->vector, 1);
+}
+
 static void mxser_release_ISA_res(struct mxser_board *brd)
 {
        free_irq(brd->irq, brd);
        release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-       release_region(brd->vector, 1);
+       mxser_release_vector(brd);
 }
 
 static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2396,7 +2421,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
 
 static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
 {
-       int id, i, bits;
+       int id, i, bits, ret;
        unsigned short regs[16], irq;
        unsigned char scratch, scratch2;
 
@@ -2492,13 +2517,15 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
                                8 * brd->info->nports - 1);
                return -EIO;
        }
-       if (!request_region(brd->vector, 1, "mxser(vector)")) {
+
+       ret = mxser_request_vector(brd);
+       if (ret) {
                release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
                printk(KERN_ERR "mxser: can't request interrupt vector region: "
                                "0x%.8lx-0x%.8lx\n",
                                brd->ports[0].ioaddr, brd->ports[0].ioaddr +
                                8 * brd->info->nports - 1);
-               return -EIO;
+               return ret;
        }
        return brd->info->nports;