diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/i2c-core.c | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index f75344ac4663..3495ab4035ec 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -34,11 +34,11 @@ | |||
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | #include <linux/completion.h> | 35 | #include <linux/completion.h> |
36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
37 | #include <asm/semaphore.h> | ||
37 | 38 | ||
38 | #include "i2c-core.h" | 39 | #include "i2c-core.h" |
39 | 40 | ||
40 | 41 | ||
41 | static LIST_HEAD(adapters); | ||
42 | static LIST_HEAD(drivers); | 42 | static LIST_HEAD(drivers); |
43 | static DEFINE_MUTEX(core_lists); | 43 | static DEFINE_MUTEX(core_lists); |
44 | static DEFINE_IDR(i2c_adapter_idr); | 44 | static DEFINE_IDR(i2c_adapter_idr); |
@@ -331,7 +331,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
331 | INIT_LIST_HEAD(&adap->clients); | 331 | INIT_LIST_HEAD(&adap->clients); |
332 | 332 | ||
333 | mutex_lock(&core_lists); | 333 | mutex_lock(&core_lists); |
334 | list_add_tail(&adap->list, &adapters); | ||
335 | 334 | ||
336 | /* Add the adapter to the driver core. | 335 | /* Add the adapter to the driver core. |
337 | * If the parent pointer is not set up, | 336 | * If the parent pointer is not set up, |
@@ -368,7 +367,6 @@ out_unlock: | |||
368 | return res; | 367 | return res; |
369 | 368 | ||
370 | out_list: | 369 | out_list: |
371 | list_del(&adap->list); | ||
372 | idr_remove(&i2c_adapter_idr, adap->nr); | 370 | idr_remove(&i2c_adapter_idr, adap->nr); |
373 | goto out_unlock; | 371 | goto out_unlock; |
374 | } | 372 | } |
@@ -473,7 +471,6 @@ EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); | |||
473 | int i2c_del_adapter(struct i2c_adapter *adap) | 471 | int i2c_del_adapter(struct i2c_adapter *adap) |
474 | { | 472 | { |
475 | struct list_head *item, *_n; | 473 | struct list_head *item, *_n; |
476 | struct i2c_adapter *adap_from_list; | ||
477 | struct i2c_driver *driver; | 474 | struct i2c_driver *driver; |
478 | struct i2c_client *client; | 475 | struct i2c_client *client; |
479 | int res = 0; | 476 | int res = 0; |
@@ -481,11 +478,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
481 | mutex_lock(&core_lists); | 478 | mutex_lock(&core_lists); |
482 | 479 | ||
483 | /* First make sure that this adapter was ever added */ | 480 | /* First make sure that this adapter was ever added */ |
484 | list_for_each_entry(adap_from_list, &adapters, list) { | 481 | if (idr_find(&i2c_adapter_idr, adap->nr) != adap) { |
485 | if (adap_from_list == adap) | ||
486 | break; | ||
487 | } | ||
488 | if (adap_from_list != adap) { | ||
489 | pr_debug("i2c-core: attempting to delete unregistered " | 482 | pr_debug("i2c-core: attempting to delete unregistered " |
490 | "adapter [%s]\n", adap->name); | 483 | "adapter [%s]\n", adap->name); |
491 | res = -EINVAL; | 484 | res = -EINVAL; |
@@ -529,7 +522,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
529 | /* clean up the sysfs representation */ | 522 | /* clean up the sysfs representation */ |
530 | init_completion(&adap->dev_released); | 523 | init_completion(&adap->dev_released); |
531 | device_unregister(&adap->dev); | 524 | device_unregister(&adap->dev); |
532 | list_del(&adap->list); | ||
533 | 525 | ||
534 | /* wait for sysfs to drop all references */ | 526 | /* wait for sysfs to drop all references */ |
535 | wait_for_completion(&adap->dev_released); | 527 | wait_for_completion(&adap->dev_released); |
@@ -592,9 +584,12 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
592 | if (driver->attach_adapter) { | 584 | if (driver->attach_adapter) { |
593 | struct i2c_adapter *adapter; | 585 | struct i2c_adapter *adapter; |
594 | 586 | ||
595 | list_for_each_entry(adapter, &adapters, list) { | 587 | down(&i2c_adapter_class.sem); |
588 | list_for_each_entry(adapter, &i2c_adapter_class.devices, | ||
589 | dev.node) { | ||
596 | driver->attach_adapter(adapter); | 590 | driver->attach_adapter(adapter); |
597 | } | 591 | } |
592 | up(&i2c_adapter_class.sem); | ||
598 | } | 593 | } |
599 | 594 | ||
600 | mutex_unlock(&core_lists); | 595 | mutex_unlock(&core_lists); |
@@ -609,7 +604,7 @@ EXPORT_SYMBOL(i2c_register_driver); | |||
609 | */ | 604 | */ |
610 | void i2c_del_driver(struct i2c_driver *driver) | 605 | void i2c_del_driver(struct i2c_driver *driver) |
611 | { | 606 | { |
612 | struct list_head *item1, *item2, *_n; | 607 | struct list_head *item2, *_n; |
613 | struct i2c_client *client; | 608 | struct i2c_client *client; |
614 | struct i2c_adapter *adap; | 609 | struct i2c_adapter *adap; |
615 | 610 | ||
@@ -623,8 +618,8 @@ void i2c_del_driver(struct i2c_driver *driver) | |||
623 | * attached. If so, detach them to be able to kill the driver | 618 | * attached. If so, detach them to be able to kill the driver |
624 | * afterwards. | 619 | * afterwards. |
625 | */ | 620 | */ |
626 | list_for_each(item1,&adapters) { | 621 | down(&i2c_adapter_class.sem); |
627 | adap = list_entry(item1, struct i2c_adapter, list); | 622 | list_for_each_entry(adap, &i2c_adapter_class.devices, dev.node) { |
628 | if (driver->detach_adapter) { | 623 | if (driver->detach_adapter) { |
629 | if (driver->detach_adapter(adap)) { | 624 | if (driver->detach_adapter(adap)) { |
630 | dev_err(&adap->dev, "detach_adapter failed " | 625 | dev_err(&adap->dev, "detach_adapter failed " |
@@ -648,6 +643,7 @@ void i2c_del_driver(struct i2c_driver *driver) | |||
648 | } | 643 | } |
649 | } | 644 | } |
650 | } | 645 | } |
646 | up(&i2c_adapter_class.sem); | ||
651 | 647 | ||
652 | unregister: | 648 | unregister: |
653 | driver_unregister(&driver->driver); | 649 | driver_unregister(&driver->driver); |