From 2eb1eb02dda368fb224bf5a379d2448c742b71db Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 13 Mar 2015 01:45:49 +0100 Subject: PNP / ACPI: Use ACPI_COMPANION_SET() during initialization pnpacpi_add_device() calls acpi_bind_one() on an already registered device, which is a mistake, but it can initialize the ACPI companion field of the struct device to be registered using ACPI_COMPANION_SET() instead, so make it do that. Signed-off-by: Rafael J. Wysocki Reviewed-by: Mika Westerberg --- drivers/pnp/pnpacpi/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index d2b780aade89..5153d1d69aee 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -248,6 +248,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) if (!dev) return -ENOMEM; + ACPI_COMPANION_SET(&dev->dev, device); dev->data = device; /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; @@ -290,11 +291,9 @@ static int __init pnpacpi_add_device(struct acpi_device *device) return error; } - error = acpi_bind_one(&dev->dev, device); - num++; - return error; + return 0; } static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, -- cgit v1.2.3 From 1551660369d00a7e8cdfa12e9af132053eb67140 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:31 +0100 Subject: PNP: tpm/tpm_infineon: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/char/tpm/tpm_infineon.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 6d492132ad2b..29ba520ac24d 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -637,18 +637,7 @@ static struct pnp_driver tpm_inf_pnp_driver = { .remove = tpm_inf_pnp_remove }; -static int __init init_inf(void) -{ - return pnp_register_driver(&tpm_inf_pnp_driver); -} - -static void __exit cleanup_inf(void) -{ - pnp_unregister_driver(&tpm_inf_pnp_driver); -} - -module_init(init_inf); -module_exit(cleanup_inf); +module_pnp_driver(tpm_inf_pnp_driver); MODULE_AUTHOR("Marcel Selhorst "); MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); -- cgit v1.2.3 From 99c876bec30d064679c07d53b44a4e99da10f576 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:32 +0100 Subject: PNP: ata/pata_isapnp: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/ata/pata_isapnp.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index b33d1f99b3a4..994f168b54a8 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -128,20 +128,8 @@ static struct pnp_driver isapnp_driver = { .remove = isapnp_remove_one, }; -static int __init isapnp_init(void) -{ - return pnp_register_driver(&isapnp_driver); -} - -static void __exit isapnp_exit(void) -{ - pnp_unregister_driver(&isapnp_driver); -} - +module_pnp_driver(isapnp_driver); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for ISA PnP ATA"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(isapnp_init); -module_exit(isapnp_exit); -- cgit v1.2.3 From 6a5333092e4674c1e1f7de05ce6a167273f5afdb Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:33 +0100 Subject: PNP: ide/ide-pnp: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/ide/ide-pnp.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index e5f3db831373..f5f2b62471da 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -96,17 +96,5 @@ static struct pnp_driver idepnp_driver = { .remove = idepnp_remove, }; -static int __init pnpide_init(void) -{ - return pnp_register_driver(&idepnp_driver); -} - -static void __exit pnpide_exit(void) -{ - pnp_unregister_driver(&idepnp_driver); -} - -module_init(pnpide_init); -module_exit(pnpide_exit); - +module_pnp_driver(idepnp_driver); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From af638a04070f54c22c2fe7523e742d06b5f980bf Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:34 +0100 Subject: PNP: media/rc: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/media/rc/ene_ir.c | 13 +------------ drivers/media/rc/fintek-cir.c | 13 +------------ drivers/media/rc/ite-cir.c | 13 +------------ drivers/media/rc/nuvoton-cir.c | 13 +------------ 4 files changed, 4 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index e80f2c6c5f1a..8d77e1c4a141 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -1195,16 +1195,6 @@ static struct pnp_driver ene_driver = { .shutdown = ene_shutdown, }; -static int __init ene_init(void) -{ - return pnp_register_driver(&ene_driver); -} - -static void ene_exit(void) -{ - pnp_unregister_driver(&ene_driver); -} - module_param(sample_period, int, S_IRUGO); MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); @@ -1226,5 +1216,4 @@ MODULE_DESCRIPTION MODULE_AUTHOR("Maxim Levitsky"); MODULE_LICENSE("GPL"); -module_init(ene_init); -module_exit(ene_exit); +module_pnp_driver(ene_driver); diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index b5167573240e..5c63c2ec6183 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -684,16 +684,6 @@ static struct pnp_driver fintek_driver = { .shutdown = fintek_shutdown, }; -static int __init fintek_init(void) -{ - return pnp_register_driver(&fintek_driver); -} - -static void __exit fintek_exit(void) -{ - pnp_unregister_driver(&fintek_driver); -} - module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging output"); @@ -703,5 +693,4 @@ MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver"); MODULE_AUTHOR("Jarod Wilson "); MODULE_LICENSE("GPL"); -module_init(fintek_init); -module_exit(fintek_exit); +module_pnp_driver(fintek_driver); diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 56abf9120cc2..0f301903aa6f 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1708,21 +1708,10 @@ static struct pnp_driver ite_driver = { .shutdown = ite_shutdown, }; -static int __init ite_init(void) -{ - return pnp_register_driver(&ite_driver); -} - -static void __exit ite_exit(void) -{ - pnp_unregister_driver(&ite_driver); -} - MODULE_DEVICE_TABLE(pnp, ite_ids); MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver"); MODULE_AUTHOR("Juan J. Garcia de Soria "); MODULE_LICENSE("GPL"); -module_init(ite_init); -module_exit(ite_exit); +module_pnp_driver(ite_driver); diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 9c2c8635ff33..85af7a869167 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1219,16 +1219,6 @@ static struct pnp_driver nvt_driver = { .shutdown = nvt_shutdown, }; -static int __init nvt_init(void) -{ - return pnp_register_driver(&nvt_driver); -} - -static void __exit nvt_exit(void) -{ - pnp_unregister_driver(&nvt_driver); -} - module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging output"); @@ -1238,5 +1228,4 @@ MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver"); MODULE_AUTHOR("Jarod Wilson "); MODULE_LICENSE("GPL"); -module_init(nvt_init); -module_exit(nvt_exit); +module_pnp_driver(nvt_driver); -- cgit v1.2.3 From ed03538aa8d5f03432ddd5ed73fc0ba2725af93d Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:35 +0100 Subject: PNP: net/sb1000: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/net/sb1000.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 66c2f1a01963..aad0b59d41e3 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -1175,17 +1175,4 @@ MODULE_AUTHOR("Franco Venturi "); MODULE_DESCRIPTION("General Instruments SB1000 driver"); MODULE_LICENSE("GPL"); -static int __init -sb1000_init(void) -{ - return pnp_register_driver(&sb1000_driver); -} - -static void __exit -sb1000_exit(void) -{ - pnp_unregister_driver(&sb1000_driver); -} - -module_init(sb1000_init); -module_exit(sb1000_exit); +module_pnp_driver(sb1000_driver); -- cgit v1.2.3 From 99f74f12e87426be0f83b87b5e46c1ec8b00bd0f Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:36 +0100 Subject: PNP: platform/x86/apple-gmux: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/apple-gmux.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index b9429fbf1cd8..66d6d22c239c 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -624,19 +624,7 @@ static struct pnp_driver gmux_pnp_driver = { }, }; -static int __init apple_gmux_init(void) -{ - return pnp_register_driver(&gmux_pnp_driver); -} - -static void __exit apple_gmux_exit(void) -{ - pnp_unregister_driver(&gmux_pnp_driver); -} - -module_init(apple_gmux_init); -module_exit(apple_gmux_exit); - +module_pnp_driver(gmux_pnp_driver); MODULE_AUTHOR("Seth Forshee "); MODULE_DESCRIPTION("Apple Gmux Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From aee94467d9858b5441c278ffa39dcd19bef548cf Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 16 Mar 2015 21:46:37 +0100 Subject: PNP: tty/serial/8250/8250_fintek: Use module_pnp_driver to register driver Removing some boilerplate by using module_pnp_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Rafael J. Wysocki --- drivers/tty/serial/8250/8250_fintek.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 1e6899bc9429..5815e81b5fc6 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -234,18 +234,7 @@ static struct pnp_driver fintek_8250_driver = { .id_table = fintek_dev_table, }; -static int fintek_8250_init(void) -{ - return pnp_register_driver(&fintek_8250_driver); -} -module_init(fintek_8250_init); - -static void fintek_8250_exit(void) -{ - pnp_unregister_driver(&fintek_8250_driver); -} -module_exit(fintek_8250_exit); - +module_pnp_driver(fintek_8250_driver); MODULE_DESCRIPTION("Fintek F812164 module"); MODULE_AUTHOR("Ricardo Ribalda "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 38f6b38dbb0896511c509fbb6ceabbedbee8e87d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 18 Mar 2015 22:39:55 +0100 Subject: PNP: Convert pnp_lock into a mutex pnp_lock is a spinlock, but it is only acquired from process context, so it may be a mutex just fine. Signed-off-by: Rafael J. Wysocki --- drivers/pnp/base.h | 2 +- drivers/pnp/card.c | 25 +++++++++++++------------ drivers/pnp/core.c | 19 ++++++++++--------- drivers/pnp/driver.c | 10 +++++----- 4 files changed, 29 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index c8873b0ca551..3151fd164614 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -3,7 +3,7 @@ * Bjorn Helgaas */ -extern spinlock_t pnp_lock; +extern struct mutex pnp_lock; extern const struct attribute_group *pnp_dev_groups[]; void *pnp_alloc(long size); diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 874c236ac1a7..31ad9fc3f701 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -244,10 +245,10 @@ int pnp_add_card(struct pnp_card *card) } pnp_interface_attach_card(card); - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_add_tail(&card->global_list, &pnp_cards); list_add_tail(&card->protocol_list, &card->protocol->cards); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); /* we wait until now to add devices in order to ensure the drivers * will be able to use all of the related devices on the card @@ -276,10 +277,10 @@ void pnp_remove_card(struct pnp_card *card) struct list_head *pos, *temp; device_unregister(&card->dev); - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_del(&card->global_list); list_del(&card->protocol_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); list_for_each_safe(pos, temp, &card->devices) { struct pnp_dev *dev = card_to_pnp_dev(pos); pnp_remove_card_device(dev); @@ -297,10 +298,10 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) dev->card_link = NULL; dev_set_name(&dev->dev, "%02x:%02x.%02x", dev->protocol->number, card->number, dev->number); - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); dev->card = card; list_add_tail(&dev->card_list, &card->devices); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); return 0; } @@ -310,10 +311,10 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) */ void pnp_remove_card_device(struct pnp_dev *dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); dev->card = NULL; list_del(&dev->card_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); __pnp_remove_device(dev); } @@ -426,9 +427,9 @@ int pnp_register_card_driver(struct pnp_card_driver *drv) if (error < 0) return error; - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_add_tail(&drv->global_list, &pnp_card_drivers); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); list_for_each_safe(pos, temp, &pnp_cards) { struct pnp_card *card = @@ -444,9 +445,9 @@ int pnp_register_card_driver(struct pnp_card_driver *drv) */ void pnp_unregister_card_driver(struct pnp_card_driver *drv) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_del(&drv->global_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); pnp_unregister_driver(&drv->link); } diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index cb6ce42f8e77..ef2f59c4e57c 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,7 @@ static LIST_HEAD(pnp_protocols); LIST_HEAD(pnp_global); -DEFINE_SPINLOCK(pnp_lock); +DEFINE_MUTEX(pnp_lock); /* * ACPI or PNPBIOS should tell us about all platform devices, so we can @@ -55,7 +56,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol) INIT_LIST_HEAD(&protocol->devices); INIT_LIST_HEAD(&protocol->cards); nodenum = 0; - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); /* assign the lowest unused number */ list_for_each(pos, &pnp_protocols) { @@ -67,7 +68,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol) } list_add_tail(&protocol->protocol_list, &pnp_protocols); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); protocol->number = nodenum; dev_set_name(&protocol->dev, "pnp%d", nodenum); @@ -80,9 +81,9 @@ int pnp_register_protocol(struct pnp_protocol *protocol) */ void pnp_unregister_protocol(struct pnp_protocol *protocol) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_del(&protocol->protocol_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); device_unregister(&protocol->dev); } @@ -161,10 +162,10 @@ int __pnp_add_device(struct pnp_dev *dev) { pnp_fixup_device(dev); dev->status = PNP_READY; - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->protocol_list, &dev->protocol->devices); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); if (dev->protocol->can_wakeup) device_set_wakeup_capable(&dev->dev, dev->protocol->can_wakeup(dev)); @@ -203,10 +204,10 @@ int pnp_add_device(struct pnp_dev *dev) void __pnp_remove_device(struct pnp_dev *dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); list_del(&dev->global_list); list_del(&dev->protocol_list); - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); device_unregister(&dev->dev); } diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 4e57d3370368..153a493b5413 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -58,22 +58,22 @@ static const struct pnp_device_id *match_device(struct pnp_driver *drv, int pnp_device_attach(struct pnp_dev *pnp_dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); if (pnp_dev->status != PNP_READY) { - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); return -EBUSY; } pnp_dev->status = PNP_ATTACHED; - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); return 0; } void pnp_device_detach(struct pnp_dev *pnp_dev) { - spin_lock(&pnp_lock); + mutex_lock(&pnp_lock); if (pnp_dev->status == PNP_ATTACHED) pnp_dev->status = PNP_READY; - spin_unlock(&pnp_lock); + mutex_unlock(&pnp_lock); pnp_disable_dev(pnp_dev); } -- cgit v1.2.3 From 71150d226564686ef32d15d29edfd18346f6e929 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 18 Mar 2015 22:40:04 +0100 Subject: PNP: Avoid leaving unregistered device objects in lists pnp_register_protocol() and __pnp_add_device() both have a problem that if device_register() fails, the objects they create will be left in the lists they have been put one beforehand. Unfortunately, that is not handled by the callers of those routines either, so in case of a device registration errors the PNP bus type's data structures will end up in an inconsistent state. Make pnp_register_protocol() and __pnp_add_device() remove the objects from the lists if device registration fails. Signed-off-by: Rafael J. Wysocki --- drivers/pnp/core.c | 53 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index ef2f59c4e57c..b54620e53830 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -42,6 +42,13 @@ void *pnp_alloc(long size) return result; } +static void pnp_remove_protocol(struct pnp_protocol *protocol) +{ + mutex_lock(&pnp_lock); + list_del(&protocol->protocol_list); + mutex_unlock(&pnp_lock); +} + /** * pnp_protocol_register - adds a pnp protocol to the pnp layer * @protocol: pointer to the corresponding pnp_protocol structure @@ -50,12 +57,13 @@ void *pnp_alloc(long size) */ int pnp_register_protocol(struct pnp_protocol *protocol) { - int nodenum; struct list_head *pos; + int nodenum, ret; INIT_LIST_HEAD(&protocol->devices); INIT_LIST_HEAD(&protocol->cards); nodenum = 0; + mutex_lock(&pnp_lock); /* assign the lowest unused number */ @@ -67,12 +75,18 @@ int pnp_register_protocol(struct pnp_protocol *protocol) } } + protocol->number = nodenum; + dev_set_name(&protocol->dev, "pnp%d", nodenum); + list_add_tail(&protocol->protocol_list, &pnp_protocols); + mutex_unlock(&pnp_lock); - protocol->number = nodenum; - dev_set_name(&protocol->dev, "pnp%d", nodenum); - return device_register(&protocol->dev); + ret = device_register(&protocol->dev); + if (ret) + pnp_remove_protocol(protocol); + + return ret; } /** @@ -81,9 +95,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol) */ void pnp_unregister_protocol(struct pnp_protocol *protocol) { - mutex_lock(&pnp_lock); - list_del(&protocol->protocol_list); - mutex_unlock(&pnp_lock); + pnp_remove_protocol(protocol); device_unregister(&protocol->dev); } @@ -158,18 +170,36 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, return dev; } +static void pnp_delist_device(struct pnp_dev *dev) +{ + mutex_lock(&pnp_lock); + list_del(&dev->global_list); + list_del(&dev->protocol_list); + mutex_unlock(&pnp_lock); +} + int __pnp_add_device(struct pnp_dev *dev) { + int ret; + pnp_fixup_device(dev); dev->status = PNP_READY; + mutex_lock(&pnp_lock); + list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->protocol_list, &dev->protocol->devices); + mutex_unlock(&pnp_lock); - if (dev->protocol->can_wakeup) + + ret = device_register(&dev->dev); + if (ret) + pnp_delist_device(dev); + else if (dev->protocol->can_wakeup) device_set_wakeup_capable(&dev->dev, dev->protocol->can_wakeup(dev)); - return device_register(&dev->dev); + + return ret; } /* @@ -204,10 +234,7 @@ int pnp_add_device(struct pnp_dev *dev) void __pnp_remove_device(struct pnp_dev *dev) { - mutex_lock(&pnp_lock); - list_del(&dev->global_list); - list_del(&dev->protocol_list); - mutex_unlock(&pnp_lock); + pnp_delist_device(dev); device_unregister(&dev->dev); } -- cgit v1.2.3