diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index 2517636..d9b358f 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -4422,3 +4422,24 @@ void ddb_unmap(struct ddb *dev) vfree(dev); } +int ddb_exit_ddbridge(int stage, int error) +{ + switch (stage) { + default: + case 2: + destroy_workqueue(ddb_wq); + case 1: + ddb_class_destroy(); + } + return error; +} + +int ddb_init_ddbridge(void) +{ + if (ddb_class_create() < 0) + return -1; + ddb_wq = alloc_workqueue("ddbridge", 0, 0); + if (!ddb_wq) + return ddb_exit_ddbridge(1, -1); + return 0; +} diff --git a/ddbridge/ddbridge-main.c b/ddbridge/ddbridge-main.c index f64d00f..4c93806 100644 --- a/ddbridge/ddbridge-main.c +++ b/ddbridge/ddbridge-main.c @@ -31,8 +31,6 @@ MODULE_PARM_DESC(msi, " Control MSI interrupts: 0-disable, 1-enable (default)"); #endif -extern struct workqueue_struct *ddb_wq; - #if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE) int pci_irq_vector(struct pci_dev *dev, unsigned int nr) { @@ -404,32 +402,24 @@ static struct pci_driver ddb_pci_driver = { static __init int module_init_ddbridge(void) { - int stat = -1; + int stat; pr_info("Digital Devices PCIE bridge driver " DDBRIDGE_VERSION ", Copyright (C) 2010-17 Digital Devices GmbH\n"); - if (ddb_class_create() < 0) - return -1; - ddb_wq = create_workqueue("ddbridge"); - if (!ddb_wq) - goto exit1; + stat = ddb_init_ddbridge(); + if (stat < 0) + return stat; stat = pci_register_driver(&ddb_pci_driver); if (stat < 0) - goto exit2; - return stat; -exit2: - destroy_workqueue(ddb_wq); -exit1: - ddb_class_destroy(); + ddb_exit_ddbridge(0, stat); return stat; } static __exit void module_exit_ddbridge(void) { pci_unregister_driver(&ddb_pci_driver); - destroy_workqueue(ddb_wq); - ddb_class_destroy(); + ddb_exit_ddbridge(0, 0); } module_init(module_init_ddbridge); diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index 0e891d7..47e9b65 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -560,8 +560,8 @@ irqreturn_t ddb_irq_handler(int irq, void *dev_id); irqreturn_t ddb_irq_handler_v2(int irq, void *dev_id); void ddb_reset_ios(struct ddb *dev); int ddb_init(struct ddb *dev); -int ddb_class_create(void); -void ddb_class_destroy(void); +int ddb_exit_ddbridge(int stage, int error); +int ddb_init_ddbridge(void); int ddb_i2c_init(struct ddb *dev); void ddb_i2c_release(struct ddb *dev); diff --git a/ddbridge/octonet-main.c b/ddbridge/octonet-main.c index c7a3d1c..48eabf8 100644 --- a/ddbridge/octonet-main.c +++ b/ddbridge/octonet-main.c @@ -141,25 +141,23 @@ static struct platform_driver octonet_driver __refdata = { static __init int init_octonet(void) { - int res; + int stat; pr_info("DDBridge: Digital Devices OctopusNet driver " DDBRIDGE_VERSION - ", Copyright (C) 2010-16 Digital Devices GmbH\n"); - res = ddb_class_create(); - if (res) - return res; - res = platform_driver_probe(&octonet_driver, octonet_probe); - if (res) { - ddb_class_destroy(); - return res; - } - return 0; + ", Copyright (C) 2010-17 Digital Devices GmbH\n"); + stat = ddb_init_ddbridge(); + if (stat < 0) + return stat; + stat = platform_driver_probe(&octonet_driver, octonet_probe); + if (stat < 0) + ddb_exit_ddbridge(0, stat); + return stat; } static __exit void exit_octonet(void) { platform_driver_unregister(&octonet_driver); - ddb_class_destroy(); + ddb_exit_ddbridge(0, 0); } module_init(init_octonet);