[PATCH V2] staging: dgnc: Creating and destroying sysfs files properly

Salah Triki salah.triki at acm.org
Fri Dec 18 10:57:18 UTC 2015


Delegate creation and destruction of sysfs files to device
and driver layers in order to eliminate races.

Signed-off-by: Salah Triki <salah.triki at acm.org>
---
 drivers/staging/dgnc/dgnc_driver.c |  11 ++--
 drivers/staging/dgnc/dgnc_sysfs.c  | 118 ++++++++++++++-----------------------
 drivers/staging/dgnc/dgnc_sysfs.h  |  10 +---
 drivers/staging/dgnc/dgnc_tty.c    |  10 ++--
 4 files changed, 54 insertions(+), 95 deletions(-)

diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
index fc6d298..cbfa412 100644
--- a/drivers/staging/dgnc/dgnc_driver.c
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -142,14 +142,11 @@ static void dgnc_cleanup_module(void)
 	/* Turn off poller right away. */
 	del_timer_sync(&dgnc_poll_timer);
 
-	dgnc_remove_driver_sysfiles(&dgnc_driver);
-
 	device_destroy(dgnc_class, MKDEV(dgnc_Major, 0));
 	class_destroy(dgnc_class);
 	unregister_chrdev(dgnc_Major, "dgnc");
 
 	for (i = 0; i < dgnc_NumBoards; ++i) {
-		dgnc_remove_ports_sysfiles(dgnc_Board[i]);
 		dgnc_tty_uninit(dgnc_Board[i]);
 		dgnc_cleanup_board(dgnc_Board[i]);
 	}
@@ -180,6 +177,8 @@ static int __init dgnc_init_module(void)
 	/*
 	 * Find and configure all the cards
 	 */
+	dgnc_driver.driver.groups = dgnc_drv_attr_groups;
+
 	rc = pci_register_driver(&dgnc_driver);
 
 	/*
@@ -193,8 +192,6 @@ static int __init dgnc_init_module(void)
 			pr_warn("WARNING: dgnc driver load failed.  No Digi Neo or Classic boards found.\n");
 
 		dgnc_cleanup_module();
-	} else {
-		dgnc_create_driver_sysfiles(&dgnc_driver);
 	}
 
 	return rc;
@@ -281,6 +278,8 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	int rc;
 
 	/* wake up and enable device */
+	pdev->dev.groups = dgnc_dev_attr_groups;
+
 	rc = pci_enable_device(pdev);
 
 	if (rc < 0) {
@@ -554,8 +553,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
 	brd->state = BOARD_READY;
 	brd->dpastatus = BD_RUNNING;
 
-	dgnc_create_ports_sysfiles(brd);
-
 	/* init our poll helper tasklet */
 	tasklet_init(&brd->helper_tasklet,
 		     brd->bd_ops->tasklet,
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c
index 74a0725..eef1a43 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.c
+++ b/drivers/staging/dgnc/dgnc_sysfs.c
@@ -24,6 +24,7 @@
 
 #include "dgnc_driver.h"
 #include "dgnc_mgmt.h"
+#include "dgnc_sysfs.h"
 
 static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf)
 {
@@ -68,28 +69,22 @@ static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp,
 static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show,
 		   dgnc_driver_pollrate_store);
 
-void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
-{
-	int rc = 0;
-	struct device_driver *driverfs = &dgnc_driver->driver;
-
-	rc |= driver_create_file(driverfs, &driver_attr_version);
-	rc |= driver_create_file(driverfs, &driver_attr_boards);
-	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
-	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
-	if (rc)
-		pr_err("DGNC: sysfs driver_create_file failed!\n");
-}
+static struct attribute *dgnc_drv_attrs[] = {
+	&driver_attr_version.attr,
+	&driver_attr_boards.attr,
+	&driver_attr_maxboards.attr,
+	&driver_attr_pollrate.attr,
+	NULL,
+};
 
-void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
-{
-	struct device_driver *driverfs = &dgnc_driver->driver;
+static struct attribute_group dgnc_drv_attr_group = {
+	.attrs = dgnc_drv_attrs,
+};
 
-	driver_remove_file(driverfs, &driver_attr_version);
-	driver_remove_file(driverfs, &driver_attr_boards);
-	driver_remove_file(driverfs, &driver_attr_maxboards);
-	driver_remove_file(driverfs, &driver_attr_pollrate);
-}
+const struct attribute_group *dgnc_drv_attr_groups[] = {
+	&dgnc_drv_attr_group,
+	NULL,
+};
 
 #define DGNC_VERIFY_BOARD(p, bd)				\
 	do {							\
@@ -338,43 +333,31 @@ static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL);
 /* this function creates the sys files that will export each signal status
  * to sysfs each value will be put in a separate filename
  */
-void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
-{
-	int rc = 0;
-
-	dev_set_drvdata(&bd->pdev->dev, bd);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_state);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_baud);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_vpd);
-	rc |= device_create_file(&bd->pdev->dev, &dev_attr_serial_number);
-	if (rc)
-		dev_err(&bd->pdev->dev, "dgnc: sysfs device_create_file failed!\n");
-}
 
-/* removes all the sys files created for that port */
-void dgnc_remove_ports_sysfiles(struct dgnc_board *bd)
-{
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_state);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
-	device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount);
-	device_remove_file(&bd->pdev->dev, &dev_attr_vpd);
-	device_remove_file(&bd->pdev->dev, &dev_attr_serial_number);
-}
+static struct attribute *dgnc_dev_attrs[] = {
+	&dev_attr_ports_state.attr,
+	&dev_attr_ports_baud.attr,
+	&dev_attr_ports_msignals.attr,
+	&dev_attr_ports_iflag.attr,
+	&dev_attr_ports_cflag.attr,
+	&dev_attr_ports_oflag.attr,
+	&dev_attr_ports_lflag.attr,
+	&dev_attr_ports_digi_flag.attr,
+	&dev_attr_ports_rxcount.attr,
+	&dev_attr_ports_txcount.attr,
+	&dev_attr_vpd.attr,
+	&dev_attr_serial_number.attr,
+	NULL,
+};
+
+static struct attribute_group dgnc_dev_attr_group = {
+	.attrs = dgnc_dev_attrs,
+};
+
+const struct attribute_group *dgnc_dev_attr_groups[] = {
+	&dgnc_dev_attr_group,
+	NULL,
+};
 
 static ssize_t dgnc_tty_state_show(struct device *d,
 				   struct device_attribute *attr, char *buf)
@@ -683,22 +666,7 @@ static struct attribute_group dgnc_tty_attribute_group = {
 	.attrs = dgnc_sysfs_tty_entries,
 };
 
-void dgnc_create_tty_sysfs(struct un_t *un, struct device *c)
-{
-	int ret;
-
-	ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group);
-	if (ret) {
-		dev_err(c, "dgnc: failed to create sysfs tty device attributes.\n");
-		sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
-		return;
-	}
-
-	dev_set_drvdata(c, un);
-}
-
-void dgnc_remove_tty_sysfs(struct device *c)
-{
-	sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
-}
-
+const struct attribute_group *dgnc_tty_attr_groups[] = {
+	&dgnc_tty_attribute_group,
+	NULL,
+};
diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h
index 7be7d55..00e7589 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.h
+++ b/drivers/staging/dgnc/dgnc_sysfs.h
@@ -25,16 +25,12 @@ struct un_t;
 struct pci_driver;
 struct class_device;
 
-void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
-void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
+extern const struct attribute_group *dgnc_drv_attr_groups[];
+extern const struct attribute_group *dgnc_dev_attr_groups[];
+extern const struct attribute_group *dgnc_tty_attr_groups[];
 
-void dgnc_create_driver_sysfiles(struct pci_driver *);
-void dgnc_remove_driver_sysfiles(struct pci_driver *);
 
 int dgnc_tty_class_init(void);
 int dgnc_tty_class_destroy(void);
 
-void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
-void dgnc_remove_tty_sysfs(struct device *c);
-
 #endif
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c
index 48e4b90..9ebee55 100644
--- a/drivers/staging/dgnc/dgnc_tty.c
+++ b/drivers/staging/dgnc/dgnc_tty.c
@@ -367,12 +367,14 @@ int dgnc_tty_init(struct dgnc_board *brd)
 			classp = tty_register_device(&brd->SerialDriver, i,
 						     &ch->ch_bd->pdev->dev);
 			ch->ch_tun.un_sysfs = classp;
-			dgnc_create_tty_sysfs(&ch->ch_tun, classp);
+			classp->groups = dgnc_tty_attr_groups;
+			dev_set_drvdata(classp, &ch->ch_tun);
 
 			classp = tty_register_device(&brd->PrintDriver, i,
 						     &ch->ch_bd->pdev->dev);
 			ch->ch_pun.un_sysfs = classp;
-			dgnc_create_tty_sysfs(&ch->ch_pun, classp);
+			classp->groups = dgnc_tty_attr_groups;
+			dev_set_drvdata(classp, &ch->ch_pun);
 		}
 	}
 
@@ -412,8 +414,6 @@ void dgnc_tty_uninit(struct dgnc_board *brd)
 		brd->dgnc_Serial_Major = 0;
 		for (i = 0; i < brd->nasync; i++) {
 			if (brd->channels[i])
-				dgnc_remove_tty_sysfs(brd->channels[i]->
-						      ch_tun.un_sysfs);
 			tty_unregister_device(&brd->SerialDriver, i);
 		}
 		tty_unregister_driver(&brd->SerialDriver);
@@ -425,8 +425,6 @@ void dgnc_tty_uninit(struct dgnc_board *brd)
 		brd->dgnc_TransparentPrint_Major = 0;
 		for (i = 0; i < brd->nasync; i++) {
 			if (brd->channels[i])
-				dgnc_remove_tty_sysfs(brd->channels[i]->
-						      ch_pun.un_sysfs);
 			tty_unregister_device(&brd->PrintDriver, i);
 		}
 		tty_unregister_driver(&brd->PrintDriver);
-- 
1.9.1



More information about the devel mailing list