From 6c8b84efe51073b11ffddf992a7b5a2059a53c14 Mon Sep 17 00:00:00 2001 From: Mark Hounschell Date: Wed, 26 Feb 2014 10:18:26 -0500 Subject: [PATCH] staging: dgap: fix kernel oops on port open 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 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgap/dgap.c | 52 +++++++++++++++++++++++++++++-------- drivers/staging/dgap/dgap.h | 3 ++- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index 7cb1ad597ced..f9adf8a308c2 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -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; } diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h index 573aa18ee499..24db46860f2d 100644 --- a/drivers/staging/dgap/dgap.h +++ b/drivers/staging/dgap/dgap.h @@ -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; -- 2.34.1