diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 70 |
1 files changed, 24 insertions, 46 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 82ea1b7ec914..52b77477df57 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -197,7 +197,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) | |||
197 | /* inform drivers of new adapters */ | 197 | /* inform drivers of new adapters */ |
198 | list_for_each(item,&drivers) { | 198 | list_for_each(item,&drivers) { |
199 | driver = list_entry(item, struct i2c_driver, list); | 199 | driver = list_entry(item, struct i2c_driver, list); |
200 | if (driver->flags & I2C_DF_NOTIFY) | 200 | if (driver->attach_adapter) |
201 | /* We ignore the return code; if it fails, too bad */ | 201 | /* We ignore the return code; if it fails, too bad */ |
202 | driver->attach_adapter(adap); | 202 | driver->attach_adapter(adap); |
203 | } | 203 | } |
@@ -235,7 +235,8 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
235 | if (driver->detach_adapter) | 235 | if (driver->detach_adapter) |
236 | if ((res = driver->detach_adapter(adap))) { | 236 | if ((res = driver->detach_adapter(adap))) { |
237 | dev_err(&adap->dev, "detach_adapter failed " | 237 | dev_err(&adap->dev, "detach_adapter failed " |
238 | "for driver [%s]\n", driver->name); | 238 | "for driver [%s]\n", |
239 | driver->driver.name); | ||
239 | goto out_unlock; | 240 | goto out_unlock; |
240 | } | 241 | } |
241 | } | 242 | } |
@@ -245,10 +246,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
245 | list_for_each_safe(item, _n, &adap->clients) { | 246 | list_for_each_safe(item, _n, &adap->clients) { |
246 | client = list_entry(item, struct i2c_client, list); | 247 | client = list_entry(item, struct i2c_client, list); |
247 | 248 | ||
248 | /* detaching devices is unconditional of the set notify | ||
249 | * flag, as _all_ clients that reside on the adapter | ||
250 | * must be deleted, as this would cause invalid states. | ||
251 | */ | ||
252 | if ((res=client->driver->detach_client(client))) { | 249 | if ((res=client->driver->detach_client(client))) { |
253 | dev_err(&adap->dev, "detach_client failed for client " | 250 | dev_err(&adap->dev, "detach_client failed for client " |
254 | "[%s] at address 0x%02x\n", client->name, | 251 | "[%s] at address 0x%02x\n", client->name, |
@@ -286,7 +283,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
286 | * chips. | 283 | * chips. |
287 | */ | 284 | */ |
288 | 285 | ||
289 | int i2c_add_driver(struct i2c_driver *driver) | 286 | int i2c_register_driver(struct module *owner, struct i2c_driver *driver) |
290 | { | 287 | { |
291 | struct list_head *item; | 288 | struct list_head *item; |
292 | struct i2c_adapter *adapter; | 289 | struct i2c_adapter *adapter; |
@@ -295,8 +292,7 @@ int i2c_add_driver(struct i2c_driver *driver) | |||
295 | down(&core_lists); | 292 | down(&core_lists); |
296 | 293 | ||
297 | /* add the driver to the list of i2c drivers in the driver core */ | 294 | /* add the driver to the list of i2c drivers in the driver core */ |
298 | driver->driver.owner = driver->owner; | 295 | driver->driver.owner = owner; |
299 | driver->driver.name = driver->name; | ||
300 | driver->driver.bus = &i2c_bus_type; | 296 | driver->driver.bus = &i2c_bus_type; |
301 | driver->driver.probe = i2c_device_probe; | 297 | driver->driver.probe = i2c_device_probe; |
302 | driver->driver.remove = i2c_device_remove; | 298 | driver->driver.remove = i2c_device_remove; |
@@ -306,10 +302,10 @@ int i2c_add_driver(struct i2c_driver *driver) | |||
306 | goto out_unlock; | 302 | goto out_unlock; |
307 | 303 | ||
308 | list_add_tail(&driver->list,&drivers); | 304 | list_add_tail(&driver->list,&drivers); |
309 | pr_debug("i2c-core: driver [%s] registered\n", driver->name); | 305 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); |
310 | 306 | ||
311 | /* now look for instances of driver on our adapters */ | 307 | /* now look for instances of driver on our adapters */ |
312 | if (driver->flags & I2C_DF_NOTIFY) { | 308 | if (driver->attach_adapter) { |
313 | list_for_each(item,&adapters) { | 309 | list_for_each(item,&adapters) { |
314 | adapter = list_entry(item, struct i2c_adapter, list); | 310 | adapter = list_entry(item, struct i2c_adapter, list); |
315 | driver->attach_adapter(adapter); | 311 | driver->attach_adapter(adapter); |
@@ -320,6 +316,7 @@ int i2c_add_driver(struct i2c_driver *driver) | |||
320 | up(&core_lists); | 316 | up(&core_lists); |
321 | return res; | 317 | return res; |
322 | } | 318 | } |
319 | EXPORT_SYMBOL(i2c_register_driver); | ||
323 | 320 | ||
324 | int i2c_del_driver(struct i2c_driver *driver) | 321 | int i2c_del_driver(struct i2c_driver *driver) |
325 | { | 322 | { |
@@ -334,17 +331,14 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
334 | /* Have a look at each adapter, if clients of this driver are still | 331 | /* Have a look at each adapter, if clients of this driver are still |
335 | * attached. If so, detach them to be able to kill the driver | 332 | * attached. If so, detach them to be able to kill the driver |
336 | * afterwards. | 333 | * afterwards. |
337 | * | ||
338 | * Removing clients does not depend on the notify flag, else | ||
339 | * invalid operation might (will!) result, when using stale client | ||
340 | * pointers. | ||
341 | */ | 334 | */ |
342 | list_for_each(item1,&adapters) { | 335 | list_for_each(item1,&adapters) { |
343 | adap = list_entry(item1, struct i2c_adapter, list); | 336 | adap = list_entry(item1, struct i2c_adapter, list); |
344 | if (driver->detach_adapter) { | 337 | if (driver->detach_adapter) { |
345 | if ((res = driver->detach_adapter(adap))) { | 338 | if ((res = driver->detach_adapter(adap))) { |
346 | dev_err(&adap->dev, "detach_adapter failed " | 339 | dev_err(&adap->dev, "detach_adapter failed " |
347 | "for driver [%s]\n", driver->name); | 340 | "for driver [%s]\n", |
341 | driver->driver.name); | ||
348 | goto out_unlock; | 342 | goto out_unlock; |
349 | } | 343 | } |
350 | } else { | 344 | } else { |
@@ -368,7 +362,7 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
368 | 362 | ||
369 | driver_unregister(&driver->driver); | 363 | driver_unregister(&driver->driver); |
370 | list_del(&driver->list); | 364 | list_del(&driver->list); |
371 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->name); | 365 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); |
372 | 366 | ||
373 | out_unlock: | 367 | out_unlock: |
374 | up(&core_lists); | 368 | up(&core_lists); |
@@ -419,8 +413,7 @@ int i2c_attach_client(struct i2c_client *client) | |||
419 | } | 413 | } |
420 | } | 414 | } |
421 | 415 | ||
422 | if (client->flags & I2C_CLIENT_ALLOW_USE) | 416 | client->usage_count = 0; |
423 | client->usage_count = 0; | ||
424 | 417 | ||
425 | client->dev.parent = &client->adapter->dev; | 418 | client->dev.parent = &client->adapter->dev; |
426 | client->dev.driver = &client->driver->driver; | 419 | client->dev.driver = &client->driver->driver; |
@@ -443,8 +436,7 @@ int i2c_detach_client(struct i2c_client *client) | |||
443 | struct i2c_adapter *adapter = client->adapter; | 436 | struct i2c_adapter *adapter = client->adapter; |
444 | int res = 0; | 437 | int res = 0; |
445 | 438 | ||
446 | if ((client->flags & I2C_CLIENT_ALLOW_USE) | 439 | if (client->usage_count > 0) { |
447 | && (client->usage_count > 0)) { | ||
448 | dev_warn(&client->dev, "Client [%s] still busy, " | 440 | dev_warn(&client->dev, "Client [%s] still busy, " |
449 | "can't detach\n", client->name); | 441 | "can't detach\n", client->name); |
450 | return -EBUSY; | 442 | return -EBUSY; |
@@ -475,10 +467,10 @@ int i2c_detach_client(struct i2c_client *client) | |||
475 | static int i2c_inc_use_client(struct i2c_client *client) | 467 | static int i2c_inc_use_client(struct i2c_client *client) |
476 | { | 468 | { |
477 | 469 | ||
478 | if (!try_module_get(client->driver->owner)) | 470 | if (!try_module_get(client->driver->driver.owner)) |
479 | return -ENODEV; | 471 | return -ENODEV; |
480 | if (!try_module_get(client->adapter->owner)) { | 472 | if (!try_module_get(client->adapter->owner)) { |
481 | module_put(client->driver->owner); | 473 | module_put(client->driver->driver.owner); |
482 | return -ENODEV; | 474 | return -ENODEV; |
483 | } | 475 | } |
484 | 476 | ||
@@ -487,7 +479,7 @@ static int i2c_inc_use_client(struct i2c_client *client) | |||
487 | 479 | ||
488 | static void i2c_dec_use_client(struct i2c_client *client) | 480 | static void i2c_dec_use_client(struct i2c_client *client) |
489 | { | 481 | { |
490 | module_put(client->driver->owner); | 482 | module_put(client->driver->driver.owner); |
491 | module_put(client->adapter->owner); | 483 | module_put(client->adapter->owner); |
492 | } | 484 | } |
493 | 485 | ||
@@ -499,33 +491,20 @@ int i2c_use_client(struct i2c_client *client) | |||
499 | if (ret) | 491 | if (ret) |
500 | return ret; | 492 | return ret; |
501 | 493 | ||
502 | if (client->flags & I2C_CLIENT_ALLOW_USE) { | 494 | client->usage_count++; |
503 | if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE) | ||
504 | client->usage_count++; | ||
505 | else if (client->usage_count > 0) | ||
506 | goto busy; | ||
507 | else | ||
508 | client->usage_count++; | ||
509 | } | ||
510 | 495 | ||
511 | return 0; | 496 | return 0; |
512 | busy: | ||
513 | i2c_dec_use_client(client); | ||
514 | return -EBUSY; | ||
515 | } | 497 | } |
516 | 498 | ||
517 | int i2c_release_client(struct i2c_client *client) | 499 | int i2c_release_client(struct i2c_client *client) |
518 | { | 500 | { |
519 | if(client->flags & I2C_CLIENT_ALLOW_USE) { | 501 | if (!client->usage_count) { |
520 | if(client->usage_count>0) | 502 | pr_debug("i2c-core: %s used one too many times\n", |
521 | client->usage_count--; | 503 | __FUNCTION__); |
522 | else { | 504 | return -EPERM; |
523 | pr_debug("i2c-core: %s used one too many times\n", | ||
524 | __FUNCTION__); | ||
525 | return -EPERM; | ||
526 | } | ||
527 | } | 505 | } |
528 | 506 | ||
507 | client->usage_count--; | ||
529 | i2c_dec_use_client(client); | 508 | i2c_dec_use_client(client); |
530 | 509 | ||
531 | return 0; | 510 | return 0; |
@@ -539,14 +518,14 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) | |||
539 | down(&adap->clist_lock); | 518 | down(&adap->clist_lock); |
540 | list_for_each(item,&adap->clients) { | 519 | list_for_each(item,&adap->clients) { |
541 | client = list_entry(item, struct i2c_client, list); | 520 | client = list_entry(item, struct i2c_client, list); |
542 | if (!try_module_get(client->driver->owner)) | 521 | if (!try_module_get(client->driver->driver.owner)) |
543 | continue; | 522 | continue; |
544 | if (NULL != client->driver->command) { | 523 | if (NULL != client->driver->command) { |
545 | up(&adap->clist_lock); | 524 | up(&adap->clist_lock); |
546 | client->driver->command(client,cmd,arg); | 525 | client->driver->command(client,cmd,arg); |
547 | down(&adap->clist_lock); | 526 | down(&adap->clist_lock); |
548 | } | 527 | } |
549 | module_put(client->driver->owner); | 528 | module_put(client->driver->driver.owner); |
550 | } | 529 | } |
551 | up(&adap->clist_lock); | 530 | up(&adap->clist_lock); |
552 | } | 531 | } |
@@ -1147,7 +1126,6 @@ EXPORT_SYMBOL_GPL(i2c_bus_type); | |||
1147 | 1126 | ||
1148 | EXPORT_SYMBOL(i2c_add_adapter); | 1127 | EXPORT_SYMBOL(i2c_add_adapter); |
1149 | EXPORT_SYMBOL(i2c_del_adapter); | 1128 | EXPORT_SYMBOL(i2c_del_adapter); |
1150 | EXPORT_SYMBOL(i2c_add_driver); | ||
1151 | EXPORT_SYMBOL(i2c_del_driver); | 1129 | EXPORT_SYMBOL(i2c_del_driver); |
1152 | EXPORT_SYMBOL(i2c_attach_client); | 1130 | EXPORT_SYMBOL(i2c_attach_client); |
1153 | EXPORT_SYMBOL(i2c_detach_client); | 1131 | EXPORT_SYMBOL(i2c_detach_client); |