[PATCH RFC only] staging: dgap: fix OOPS on open of port

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When opening a port the dgap driver OOPs with a message:

tty_init_dev: driver does not set tty->port... will crash the kernel... fix the driver... etc...

Then I have to reboot the box.

I think before too much more work is done on this driver (by me anyway), 
it should at least be in a usable state. There are a lot more changes to come 
and I would like to be able to "test" along the way.

I've looked at some of the other drivers as examples and come up with this patch that 
does in fact allow me to use the driver. I would like to submit it but am uncertain that this
is proper.   

Thanks for reviewing.
mark

diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
index 7cb1ad5..d56b3b2 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_sysfs_create(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_sysfs_create(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].port);
 			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].port);
 			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,51 @@ 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_sysfs_create(struct board_t *brd)
 {
 	struct channel_t *ch;
-	int j = 0;
+	struct dgap_port *p;
+	int j;
+
+	brd->SerialPorts = kcalloc(brd->nasync, sizeof(*brd->SerialPorts),
+					GFP_KERNEL);
+	if (brd->SerialPorts == NULL) {
+		pr_err("dgap: Cannot allocate serial port memory\n");
+		return -ENOMEM;
+	}
+
+	for (j = 0, p = brd->SerialPorts; j < brd->nasync; j++, p++)
+		tty_port_init(&p->port);
+
+	brd->PrinterPorts = kcalloc(brd->nasync, sizeof(*brd->PrinterPorts),
+					GFP_KERNEL);
+	if (brd->PrinterPorts == NULL) {
+		pr_err("dgap: Cannot allocate printer port memory\n");
+		return -ENOMEM;
+	}
+
+	for (j = 0, p = brd->PrinterPorts; j < brd->nasync; j++, p++)
+		tty_port_init(&p->port);
 
 	ch = brd->channels[0];
 	for (j = 0; j < brd->nasync; j++, ch = brd->channels[j]) {
 		struct device *classp;
-		classp = tty_register_device(brd->SerialDriver, j,
-						&(ch->ch_bd->pdev->dev));
+
+		classp = tty_port_register_device(&brd->SerialPorts[j].port,
+				brd->SerialDriver, brd->firstminor + j, NULL);
+
 		ch->ch_tun.un_sysfs = classp;
 		dgap_create_tty_sysfs(&ch->ch_tun, classp);
 
-		classp = tty_register_device(brd->PrintDriver, j,
-						&(ch->ch_bd->pdev->dev));
+		classp = tty_port_register_device(&brd->PrinterPorts[j].port,
+				brd->PrintDriver, brd->firstminor + j, NULL);
+
 		ch->ch_pun.un_sysfs = classp;
 		dgap_create_tty_sysfs(&ch->ch_pun, classp);
 	}
 	dgap_create_ports_sysfiles(brd);
+
+	return 0;
 }
 
 
diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h
index 573aa18..656d3ad 100644
--- a/drivers/staging/dgap/dgap.h
+++ b/drivers/staging/dgap/dgap.h
@@ -703,6 +703,9 @@ struct macounter
 #define	BD_FEP5PLUS	0x0001          /* Supports FEP5 Plus commands */
 #define BD_HAS_VPD	0x0002		/* Board has VPD info available */
 
+struct dgap_port {
+	struct tty_port port;
+};
 
 /*
  *	Per-board information
@@ -761,8 +764,10 @@ struct board_t
 	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
 
 	struct tty_driver	*SerialDriver;
+	struct dgap_port *SerialPorts;
 	char		SerialName[200];
 	struct tty_driver	*PrintDriver;
+	struct dgap_port *PrinterPorts;
 	char		PrintName[200];
 
 	u32		dgap_Major_Serial_Registered;
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux