aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r--drivers/i2c/i2c-core.c24
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
41static LIST_HEAD(adapters);
42static LIST_HEAD(drivers); 42static LIST_HEAD(drivers);
43static DEFINE_MUTEX(core_lists); 43static DEFINE_MUTEX(core_lists);
44static DEFINE_IDR(i2c_adapter_idr); 44static 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
370out_list: 369out_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);
473int i2c_del_adapter(struct i2c_adapter *adap) 471int 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 */
610void i2c_del_driver(struct i2c_driver *driver) 605void 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);