staging: dgap: fix kernel oops on port open
authorMark Hounschell <markh@compro.net>
Wed, 26 Feb 2014 15:18:26 +0000 (10:18 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Feb 2014 20:58:16 +0000 (12:58 -0800)
This patch addresses the follow error message followed
by a kernel oops:

dgap: driver does not set tty->port. This will crash the kernel later. Fix the driver

It also renames the main function this patch addresses because
its name is misleading.

Signed-off-by: Mark Hounschell <markh@compro.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/dgap/dgap.c
drivers/staging/dgap/dgap.h

index 7cb1ad597cedbbd747b827bc4d5f776431adfb62..f9adf8a308c2d2fb7bd690607cdc09c40ad00ce5 100644 (file)
@@ -223,7 +223,7 @@ static void dgap_get_vpd(struct board_t *brd);
 static void dgap_do_reset_board(struct board_t *brd);
 static void dgap_do_wait_for_bios(struct board_t *brd);
 static void dgap_do_wait_for_fep(struct board_t *brd);
-static void dgap_sysfs_create(struct board_t *brd);
+static int dgap_tty_register_ports(struct board_t *brd);
 static int dgap_firmware_load(struct pci_dev *pdev, int card_type);
 
 /* Driver load/unload functions */
@@ -1098,7 +1098,9 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
                return ret;
        }
 
-       dgap_sysfs_create(brd);
+       ret = dgap_tty_register_ports(brd);
+       if (ret)
+               return ret;
 
        brd->state = BOARD_READY;
        brd->dpastatus = BD_RUNNING;
@@ -1730,6 +1732,7 @@ static void dgap_tty_uninit(struct board_t *brd)
                dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
                brd->dgap_Serial_Major = 0;
                for (i = 0; i < brd->nasync; i++) {
+                       tty_port_destroy(&brd->SerialPorts[i]);
                        dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
                        tty_unregister_device(brd->SerialDriver, i);
                }
@@ -1737,6 +1740,7 @@ static void dgap_tty_uninit(struct board_t *brd)
                kfree(brd->SerialDriver->ttys);
                brd->SerialDriver->ttys = NULL;
                put_tty_driver(brd->SerialDriver);
+               kfree(brd->SerialPorts);
                brd->dgap_Major_Serial_Registered = FALSE;
        }
 
@@ -1744,6 +1748,7 @@ static void dgap_tty_uninit(struct board_t *brd)
                dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
                brd->dgap_TransparentPrint_Major = 0;
                for (i = 0; i < brd->nasync; i++) {
+                       tty_port_destroy(&brd->PrinterPorts[i]);
                        dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
                        tty_unregister_device(brd->PrintDriver, i);
                }
@@ -1751,6 +1756,7 @@ static void dgap_tty_uninit(struct board_t *brd)
                kfree(brd->PrintDriver->ttys);
                brd->PrintDriver->ttys = NULL;
                put_tty_driver(brd->PrintDriver);
+               kfree(brd->PrinterPorts);
                brd->dgap_Major_TransparentPrint_Registered = FALSE;
        }
 }
@@ -4813,25 +4819,49 @@ static int dgap_after_config_loaded(int board)
 /*
  * Create pr and tty device entries
  */
-static void dgap_sysfs_create(struct board_t *brd)
+static int dgap_tty_register_ports(struct board_t *brd)
 {
        struct channel_t *ch;
-       int j = 0;
+       int i;
+
+       brd->SerialPorts = kcalloc(brd->nasync, sizeof(*brd->SerialPorts),
+                                       GFP_KERNEL);
+       if (brd->SerialPorts == NULL)
+               return -ENOMEM;
+       for (i = 0; i < brd->nasync; i++)
+               tty_port_init(&brd->SerialPorts[i]);
+
+       brd->PrinterPorts = kcalloc(brd->nasync, sizeof(*brd->PrinterPorts),
+                                       GFP_KERNEL);
+       if (brd->PrinterPorts == NULL) {
+               kfree(brd->SerialPorts);
+               return -ENOMEM;
+       }
+       for (i = 0; i < brd->nasync; i++)
+               tty_port_init(&brd->PrinterPorts[i]);
 
        ch = brd->channels[0];
-       for (j = 0; j < brd->nasync; j++, ch = brd->channels[j]) {
+       for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
                struct device *classp;
-               classp = tty_register_device(brd->SerialDriver, j,
-                                               &(ch->ch_bd->pdev->dev));
-               ch->ch_tun.un_sysfs = classp;
+
+               classp = tty_port_register_device(&brd->SerialPorts[i],
+                                       brd->SerialDriver,
+                                       brd->firstminor + i, NULL);
+
                dgap_create_tty_sysfs(&ch->ch_tun, classp);
+               ch->ch_tun.un_sysfs = classp;
+
+               classp = tty_port_register_device(&brd->PrinterPorts[i],
+                                       brd->PrintDriver,
+                                       brd->firstminor + i, NULL);
 
-               classp = tty_register_device(brd->PrintDriver, j,
-                                               &(ch->ch_bd->pdev->dev));
-               ch->ch_pun.un_sysfs = classp;
                dgap_create_tty_sysfs(&ch->ch_pun, classp);
+               ch->ch_pun.un_sysfs = classp;
        }
        dgap_create_ports_sysfiles(brd);
+
+       return 0;
 }
 
 
index 573aa18ee499922ebe88eb734d4751672d1a037a..24db46860f2db85d7955902980d4b7e0c462822d 100644 (file)
@@ -703,7 +703,6 @@ struct macounter
 #define        BD_FEP5PLUS     0x0001          /* Supports FEP5 Plus commands */
 #define BD_HAS_VPD     0x0002          /* Board has VPD info available */
 
-
 /*
  *     Per-board information
  */
@@ -761,8 +760,10 @@ struct board_t
        struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
 
        struct tty_driver       *SerialDriver;
+       struct tty_port *SerialPorts;
        char            SerialName[200];
        struct tty_driver       *PrintDriver;
+       struct tty_port *PrinterPorts;
        char            PrintName[200];
 
        u32             dgap_Major_Serial_Registered;