root/drivers/media/v4l2-core/v4l2-async.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. v4l2_async_notifier_call_bound
  2. v4l2_async_notifier_call_unbind
  3. v4l2_async_notifier_call_complete
  4. match_i2c
  5. match_devname
  6. match_fwnode
  7. match_custom
  8. v4l2_async_find_match
  9. asd_equal
  10. v4l2_async_find_subdev_notifier
  11. v4l2_async_notifier_find_v4l2_dev
  12. v4l2_async_notifier_can_complete
  13. v4l2_async_notifier_try_complete
  14. v4l2_async_match_notify
  15. v4l2_async_notifier_try_all_subdevs
  16. v4l2_async_cleanup
  17. v4l2_async_notifier_unbind_all_subdevs
  18. __v4l2_async_notifier_has_async_subdev
  19. v4l2_async_notifier_has_async_subdev
  20. v4l2_async_notifier_asd_valid
  21. v4l2_async_notifier_init
  22. __v4l2_async_notifier_register
  23. v4l2_async_notifier_register
  24. v4l2_async_subdev_notifier_register
  25. __v4l2_async_notifier_unregister
  26. v4l2_async_notifier_unregister
  27. __v4l2_async_notifier_cleanup
  28. v4l2_async_notifier_cleanup
  29. v4l2_async_notifier_add_subdev
  30. v4l2_async_notifier_add_fwnode_subdev
  31. v4l2_async_notifier_add_fwnode_remote_subdev
  32. v4l2_async_notifier_add_i2c_subdev
  33. v4l2_async_notifier_add_devname_subdev
  34. v4l2_async_register_subdev
  35. v4l2_async_unregister_subdev

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * V4L2 asynchronous subdevice registration API
   4  *
   5  * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
   6  */
   7 
   8 #include <linux/device.h>
   9 #include <linux/err.h>
  10 #include <linux/i2c.h>
  11 #include <linux/list.h>
  12 #include <linux/mm.h>
  13 #include <linux/module.h>
  14 #include <linux/mutex.h>
  15 #include <linux/of.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/slab.h>
  18 #include <linux/types.h>
  19 
  20 #include <media/v4l2-async.h>
  21 #include <media/v4l2-device.h>
  22 #include <media/v4l2-fwnode.h>
  23 #include <media/v4l2-subdev.h>
  24 
  25 static int v4l2_async_notifier_call_bound(struct v4l2_async_notifier *n,
  26                                           struct v4l2_subdev *subdev,
  27                                           struct v4l2_async_subdev *asd)
  28 {
  29         if (!n->ops || !n->ops->bound)
  30                 return 0;
  31 
  32         return n->ops->bound(n, subdev, asd);
  33 }
  34 
  35 static void v4l2_async_notifier_call_unbind(struct v4l2_async_notifier *n,
  36                                             struct v4l2_subdev *subdev,
  37                                             struct v4l2_async_subdev *asd)
  38 {
  39         if (!n->ops || !n->ops->unbind)
  40                 return;
  41 
  42         n->ops->unbind(n, subdev, asd);
  43 }
  44 
  45 static int v4l2_async_notifier_call_complete(struct v4l2_async_notifier *n)
  46 {
  47         if (!n->ops || !n->ops->complete)
  48                 return 0;
  49 
  50         return n->ops->complete(n);
  51 }
  52 
  53 static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
  54 {
  55 #if IS_ENABLED(CONFIG_I2C)
  56         struct i2c_client *client = i2c_verify_client(sd->dev);
  57 
  58         return client &&
  59                 asd->match.i2c.adapter_id == client->adapter->nr &&
  60                 asd->match.i2c.address == client->addr;
  61 #else
  62         return false;
  63 #endif
  64 }
  65 
  66 static bool match_devname(struct v4l2_subdev *sd,
  67                           struct v4l2_async_subdev *asd)
  68 {
  69         return !strcmp(asd->match.device_name, dev_name(sd->dev));
  70 }
  71 
  72 static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
  73 {
  74         return sd->fwnode == asd->match.fwnode;
  75 }
  76 
  77 static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
  78 {
  79         if (!asd->match.custom.match)
  80                 /* Match always */
  81                 return true;
  82 
  83         return asd->match.custom.match(sd->dev, asd);
  84 }
  85 
  86 static LIST_HEAD(subdev_list);
  87 static LIST_HEAD(notifier_list);
  88 static DEFINE_MUTEX(list_lock);
  89 
  90 static struct v4l2_async_subdev *
  91 v4l2_async_find_match(struct v4l2_async_notifier *notifier,
  92                       struct v4l2_subdev *sd)
  93 {
  94         bool (*match)(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd);
  95         struct v4l2_async_subdev *asd;
  96 
  97         list_for_each_entry(asd, &notifier->waiting, list) {
  98                 /* bus_type has been verified valid before */
  99                 switch (asd->match_type) {
 100                 case V4L2_ASYNC_MATCH_CUSTOM:
 101                         match = match_custom;
 102                         break;
 103                 case V4L2_ASYNC_MATCH_DEVNAME:
 104                         match = match_devname;
 105                         break;
 106                 case V4L2_ASYNC_MATCH_I2C:
 107                         match = match_i2c;
 108                         break;
 109                 case V4L2_ASYNC_MATCH_FWNODE:
 110                         match = match_fwnode;
 111                         break;
 112                 default:
 113                         /* Cannot happen, unless someone breaks us */
 114                         WARN_ON(true);
 115                         return NULL;
 116                 }
 117 
 118                 /* match cannot be NULL here */
 119                 if (match(sd, asd))
 120                         return asd;
 121         }
 122 
 123         return NULL;
 124 }
 125 
 126 /* Compare two async sub-device descriptors for equivalence */
 127 static bool asd_equal(struct v4l2_async_subdev *asd_x,
 128                       struct v4l2_async_subdev *asd_y)
 129 {
 130         if (asd_x->match_type != asd_y->match_type)
 131                 return false;
 132 
 133         switch (asd_x->match_type) {
 134         case V4L2_ASYNC_MATCH_DEVNAME:
 135                 return strcmp(asd_x->match.device_name,
 136                               asd_y->match.device_name) == 0;
 137         case V4L2_ASYNC_MATCH_I2C:
 138                 return asd_x->match.i2c.adapter_id ==
 139                         asd_y->match.i2c.adapter_id &&
 140                         asd_x->match.i2c.address ==
 141                         asd_y->match.i2c.address;
 142         case V4L2_ASYNC_MATCH_FWNODE:
 143                 return asd_x->match.fwnode == asd_y->match.fwnode;
 144         default:
 145                 break;
 146         }
 147 
 148         return false;
 149 }
 150 
 151 /* Find the sub-device notifier registered by a sub-device driver. */
 152 static struct v4l2_async_notifier *
 153 v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
 154 {
 155         struct v4l2_async_notifier *n;
 156 
 157         list_for_each_entry(n, &notifier_list, list)
 158                 if (n->sd == sd)
 159                         return n;
 160 
 161         return NULL;
 162 }
 163 
 164 /* Get v4l2_device related to the notifier if one can be found. */
 165 static struct v4l2_device *
 166 v4l2_async_notifier_find_v4l2_dev(struct v4l2_async_notifier *notifier)
 167 {
 168         while (notifier->parent)
 169                 notifier = notifier->parent;
 170 
 171         return notifier->v4l2_dev;
 172 }
 173 
 174 /*
 175  * Return true if all child sub-device notifiers are complete, false otherwise.
 176  */
 177 static bool
 178 v4l2_async_notifier_can_complete(struct v4l2_async_notifier *notifier)
 179 {
 180         struct v4l2_subdev *sd;
 181 
 182         if (!list_empty(&notifier->waiting))
 183                 return false;
 184 
 185         list_for_each_entry(sd, &notifier->done, async_list) {
 186                 struct v4l2_async_notifier *subdev_notifier =
 187                         v4l2_async_find_subdev_notifier(sd);
 188 
 189                 if (subdev_notifier &&
 190                     !v4l2_async_notifier_can_complete(subdev_notifier))
 191                         return false;
 192         }
 193 
 194         return true;
 195 }
 196 
 197 /*
 198  * Complete the master notifier if possible. This is done when all async
 199  * sub-devices have been bound; v4l2_device is also available then.
 200  */
 201 static int
 202 v4l2_async_notifier_try_complete(struct v4l2_async_notifier *notifier)
 203 {
 204         /* Quick check whether there are still more sub-devices here. */
 205         if (!list_empty(&notifier->waiting))
 206                 return 0;
 207 
 208         /* Check the entire notifier tree; find the root notifier first. */
 209         while (notifier->parent)
 210                 notifier = notifier->parent;
 211 
 212         /* This is root if it has v4l2_dev. */
 213         if (!notifier->v4l2_dev)
 214                 return 0;
 215 
 216         /* Is everything ready? */
 217         if (!v4l2_async_notifier_can_complete(notifier))
 218                 return 0;
 219 
 220         return v4l2_async_notifier_call_complete(notifier);
 221 }
 222 
 223 static int
 224 v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier);
 225 
 226 static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 227                                    struct v4l2_device *v4l2_dev,
 228                                    struct v4l2_subdev *sd,
 229                                    struct v4l2_async_subdev *asd)
 230 {
 231         struct v4l2_async_notifier *subdev_notifier;
 232         int ret;
 233 
 234         ret = v4l2_device_register_subdev(v4l2_dev, sd);
 235         if (ret < 0)
 236                 return ret;
 237 
 238         ret = v4l2_async_notifier_call_bound(notifier, sd, asd);
 239         if (ret < 0) {
 240                 v4l2_device_unregister_subdev(sd);
 241                 return ret;
 242         }
 243 
 244         /* Remove from the waiting list */
 245         list_del(&asd->list);
 246         sd->asd = asd;
 247         sd->notifier = notifier;
 248 
 249         /* Move from the global subdevice list to notifier's done */
 250         list_move(&sd->async_list, &notifier->done);
 251 
 252         /*
 253          * See if the sub-device has a notifier. If not, return here.
 254          */
 255         subdev_notifier = v4l2_async_find_subdev_notifier(sd);
 256         if (!subdev_notifier || subdev_notifier->parent)
 257                 return 0;
 258 
 259         /*
 260          * Proceed with checking for the sub-device notifier's async
 261          * sub-devices, and return the result. The error will be handled by the
 262          * caller.
 263          */
 264         subdev_notifier->parent = notifier;
 265 
 266         return v4l2_async_notifier_try_all_subdevs(subdev_notifier);
 267 }
 268 
 269 /* Test all async sub-devices in a notifier for a match. */
 270 static int
 271 v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier)
 272 {
 273         struct v4l2_device *v4l2_dev =
 274                 v4l2_async_notifier_find_v4l2_dev(notifier);
 275         struct v4l2_subdev *sd;
 276 
 277         if (!v4l2_dev)
 278                 return 0;
 279 
 280 again:
 281         list_for_each_entry(sd, &subdev_list, async_list) {
 282                 struct v4l2_async_subdev *asd;
 283                 int ret;
 284 
 285                 asd = v4l2_async_find_match(notifier, sd);
 286                 if (!asd)
 287                         continue;
 288 
 289                 ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
 290                 if (ret < 0)
 291                         return ret;
 292 
 293                 /*
 294                  * v4l2_async_match_notify() may lead to registering a
 295                  * new notifier and thus changing the async subdevs
 296                  * list. In order to proceed safely from here, restart
 297                  * parsing the list from the beginning.
 298                  */
 299                 goto again;
 300         }
 301 
 302         return 0;
 303 }
 304 
 305 static void v4l2_async_cleanup(struct v4l2_subdev *sd)
 306 {
 307         v4l2_device_unregister_subdev(sd);
 308         /*
 309          * Subdevice driver will reprobe and put the subdev back
 310          * onto the list
 311          */
 312         list_del_init(&sd->async_list);
 313         sd->asd = NULL;
 314 }
 315 
 316 /* Unbind all sub-devices in the notifier tree. */
 317 static void
 318 v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
 319 {
 320         struct v4l2_subdev *sd, *tmp;
 321 
 322         list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
 323                 struct v4l2_async_notifier *subdev_notifier =
 324                         v4l2_async_find_subdev_notifier(sd);
 325 
 326                 if (subdev_notifier)
 327                         v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
 328 
 329                 v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
 330                 v4l2_async_cleanup(sd);
 331 
 332                 list_move(&sd->async_list, &subdev_list);
 333         }
 334 
 335         notifier->parent = NULL;
 336 }
 337 
 338 /* See if an async sub-device can be found in a notifier's lists. */
 339 static bool
 340 __v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
 341                                        struct v4l2_async_subdev *asd)
 342 {
 343         struct v4l2_async_subdev *asd_y;
 344         struct v4l2_subdev *sd;
 345 
 346         list_for_each_entry(asd_y, &notifier->waiting, list)
 347                 if (asd_equal(asd, asd_y))
 348                         return true;
 349 
 350         list_for_each_entry(sd, &notifier->done, async_list) {
 351                 if (WARN_ON(!sd->asd))
 352                         continue;
 353 
 354                 if (asd_equal(asd, sd->asd))
 355                         return true;
 356         }
 357 
 358         return false;
 359 }
 360 
 361 /*
 362  * Find out whether an async sub-device was set up already or
 363  * whether it exists in a given notifier before @this_index.
 364  * If @this_index < 0, search the notifier's entire @asd_list.
 365  */
 366 static bool
 367 v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
 368                                      struct v4l2_async_subdev *asd,
 369                                      int this_index)
 370 {
 371         struct v4l2_async_subdev *asd_y;
 372         int j = 0;
 373 
 374         lockdep_assert_held(&list_lock);
 375 
 376         /* Check that an asd is not being added more than once. */
 377         list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
 378                 if (this_index >= 0 && j++ >= this_index)
 379                         break;
 380                 if (asd_equal(asd, asd_y))
 381                         return true;
 382         }
 383 
 384         /* Check that an asd does not exist in other notifiers. */
 385         list_for_each_entry(notifier, &notifier_list, list)
 386                 if (__v4l2_async_notifier_has_async_subdev(notifier, asd))
 387                         return true;
 388 
 389         return false;
 390 }
 391 
 392 static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
 393                                          struct v4l2_async_subdev *asd,
 394                                          int this_index)
 395 {
 396         struct device *dev =
 397                 notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
 398 
 399         if (!asd)
 400                 return -EINVAL;
 401 
 402         switch (asd->match_type) {
 403         case V4L2_ASYNC_MATCH_CUSTOM:
 404         case V4L2_ASYNC_MATCH_DEVNAME:
 405         case V4L2_ASYNC_MATCH_I2C:
 406         case V4L2_ASYNC_MATCH_FWNODE:
 407                 if (v4l2_async_notifier_has_async_subdev(notifier, asd,
 408                                                          this_index)) {
 409                         dev_dbg(dev, "subdev descriptor already listed in this or other notifiers\n");
 410                         return -EEXIST;
 411                 }
 412                 break;
 413         default:
 414                 dev_err(dev, "Invalid match type %u on %p\n",
 415                         asd->match_type, asd);
 416                 return -EINVAL;
 417         }
 418 
 419         return 0;
 420 }
 421 
 422 void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier)
 423 {
 424         INIT_LIST_HEAD(&notifier->asd_list);
 425 }
 426 EXPORT_SYMBOL(v4l2_async_notifier_init);
 427 
 428 static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
 429 {
 430         struct v4l2_async_subdev *asd;
 431         int ret, i = 0;
 432 
 433         INIT_LIST_HEAD(&notifier->waiting);
 434         INIT_LIST_HEAD(&notifier->done);
 435 
 436         mutex_lock(&list_lock);
 437 
 438         list_for_each_entry(asd, &notifier->asd_list, asd_list) {
 439                 ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
 440                 if (ret)
 441                         goto err_unlock;
 442 
 443                 list_add_tail(&asd->list, &notifier->waiting);
 444         }
 445 
 446         ret = v4l2_async_notifier_try_all_subdevs(notifier);
 447         if (ret < 0)
 448                 goto err_unbind;
 449 
 450         ret = v4l2_async_notifier_try_complete(notifier);
 451         if (ret < 0)
 452                 goto err_unbind;
 453 
 454         /* Keep also completed notifiers on the list */
 455         list_add(&notifier->list, &notifier_list);
 456 
 457         mutex_unlock(&list_lock);
 458 
 459         return 0;
 460 
 461 err_unbind:
 462         /*
 463          * On failure, unbind all sub-devices registered through this notifier.
 464          */
 465         v4l2_async_notifier_unbind_all_subdevs(notifier);
 466 
 467 err_unlock:
 468         mutex_unlock(&list_lock);
 469 
 470         return ret;
 471 }
 472 
 473 int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
 474                                  struct v4l2_async_notifier *notifier)
 475 {
 476         int ret;
 477 
 478         if (WARN_ON(!v4l2_dev || notifier->sd))
 479                 return -EINVAL;
 480 
 481         notifier->v4l2_dev = v4l2_dev;
 482 
 483         ret = __v4l2_async_notifier_register(notifier);
 484         if (ret)
 485                 notifier->v4l2_dev = NULL;
 486 
 487         return ret;
 488 }
 489 EXPORT_SYMBOL(v4l2_async_notifier_register);
 490 
 491 int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
 492                                         struct v4l2_async_notifier *notifier)
 493 {
 494         int ret;
 495 
 496         if (WARN_ON(!sd || notifier->v4l2_dev))
 497                 return -EINVAL;
 498 
 499         notifier->sd = sd;
 500 
 501         ret = __v4l2_async_notifier_register(notifier);
 502         if (ret)
 503                 notifier->sd = NULL;
 504 
 505         return ret;
 506 }
 507 EXPORT_SYMBOL(v4l2_async_subdev_notifier_register);
 508 
 509 static void
 510 __v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
 511 {
 512         if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
 513                 return;
 514 
 515         v4l2_async_notifier_unbind_all_subdevs(notifier);
 516 
 517         notifier->sd = NULL;
 518         notifier->v4l2_dev = NULL;
 519 
 520         list_del(&notifier->list);
 521 }
 522 
 523 void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
 524 {
 525         mutex_lock(&list_lock);
 526 
 527         __v4l2_async_notifier_unregister(notifier);
 528 
 529         mutex_unlock(&list_lock);
 530 }
 531 EXPORT_SYMBOL(v4l2_async_notifier_unregister);
 532 
 533 static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 534 {
 535         struct v4l2_async_subdev *asd, *tmp;
 536 
 537         if (!notifier || !notifier->asd_list.next)
 538                 return;
 539 
 540         list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
 541                 switch (asd->match_type) {
 542                 case V4L2_ASYNC_MATCH_FWNODE:
 543                         fwnode_handle_put(asd->match.fwnode);
 544                         break;
 545                 default:
 546                         break;
 547                 }
 548 
 549                 list_del(&asd->asd_list);
 550                 kfree(asd);
 551         }
 552 }
 553 
 554 void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 555 {
 556         mutex_lock(&list_lock);
 557 
 558         __v4l2_async_notifier_cleanup(notifier);
 559 
 560         mutex_unlock(&list_lock);
 561 }
 562 EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
 563 
 564 int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 565                                    struct v4l2_async_subdev *asd)
 566 {
 567         int ret;
 568 
 569         mutex_lock(&list_lock);
 570 
 571         ret = v4l2_async_notifier_asd_valid(notifier, asd, -1);
 572         if (ret)
 573                 goto unlock;
 574 
 575         list_add_tail(&asd->asd_list, &notifier->asd_list);
 576 
 577 unlock:
 578         mutex_unlock(&list_lock);
 579         return ret;
 580 }
 581 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
 582 
 583 struct v4l2_async_subdev *
 584 v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
 585                                       struct fwnode_handle *fwnode,
 586                                       unsigned int asd_struct_size)
 587 {
 588         struct v4l2_async_subdev *asd;
 589         int ret;
 590 
 591         asd = kzalloc(asd_struct_size, GFP_KERNEL);
 592         if (!asd)
 593                 return ERR_PTR(-ENOMEM);
 594 
 595         asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 596         asd->match.fwnode = fwnode_handle_get(fwnode);
 597 
 598         ret = v4l2_async_notifier_add_subdev(notifier, asd);
 599         if (ret) {
 600                 fwnode_handle_put(fwnode);
 601                 kfree(asd);
 602                 return ERR_PTR(ret);
 603         }
 604 
 605         return asd;
 606 }
 607 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev);
 608 
 609 int
 610 v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
 611                                              struct fwnode_handle *endpoint,
 612                                              struct v4l2_async_subdev *asd)
 613 {
 614         struct fwnode_handle *remote;
 615         int ret;
 616 
 617         remote = fwnode_graph_get_remote_port_parent(endpoint);
 618         if (!remote)
 619                 return -ENOTCONN;
 620 
 621         asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 622         asd->match.fwnode = remote;
 623 
 624         ret = v4l2_async_notifier_add_subdev(notif, asd);
 625         if (ret)
 626                 fwnode_handle_put(remote);
 627 
 628         return ret;
 629 }
 630 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_remote_subdev);
 631 
 632 struct v4l2_async_subdev *
 633 v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
 634                                    int adapter_id, unsigned short address,
 635                                    unsigned int asd_struct_size)
 636 {
 637         struct v4l2_async_subdev *asd;
 638         int ret;
 639 
 640         asd = kzalloc(asd_struct_size, GFP_KERNEL);
 641         if (!asd)
 642                 return ERR_PTR(-ENOMEM);
 643 
 644         asd->match_type = V4L2_ASYNC_MATCH_I2C;
 645         asd->match.i2c.adapter_id = adapter_id;
 646         asd->match.i2c.address = address;
 647 
 648         ret = v4l2_async_notifier_add_subdev(notifier, asd);
 649         if (ret) {
 650                 kfree(asd);
 651                 return ERR_PTR(ret);
 652         }
 653 
 654         return asd;
 655 }
 656 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_i2c_subdev);
 657 
 658 struct v4l2_async_subdev *
 659 v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
 660                                        const char *device_name,
 661                                        unsigned int asd_struct_size)
 662 {
 663         struct v4l2_async_subdev *asd;
 664         int ret;
 665 
 666         asd = kzalloc(asd_struct_size, GFP_KERNEL);
 667         if (!asd)
 668                 return ERR_PTR(-ENOMEM);
 669 
 670         asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
 671         asd->match.device_name = device_name;
 672 
 673         ret = v4l2_async_notifier_add_subdev(notifier, asd);
 674         if (ret) {
 675                 kfree(asd);
 676                 return ERR_PTR(ret);
 677         }
 678 
 679         return asd;
 680 }
 681 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_devname_subdev);
 682 
 683 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 684 {
 685         struct v4l2_async_notifier *subdev_notifier;
 686         struct v4l2_async_notifier *notifier;
 687         int ret;
 688 
 689         /*
 690          * No reference taken. The reference is held by the device
 691          * (struct v4l2_subdev.dev), and async sub-device does not
 692          * exist independently of the device at any point of time.
 693          */
 694         if (!sd->fwnode && sd->dev)
 695                 sd->fwnode = dev_fwnode(sd->dev);
 696 
 697         mutex_lock(&list_lock);
 698 
 699         INIT_LIST_HEAD(&sd->async_list);
 700 
 701         list_for_each_entry(notifier, &notifier_list, list) {
 702                 struct v4l2_device *v4l2_dev =
 703                         v4l2_async_notifier_find_v4l2_dev(notifier);
 704                 struct v4l2_async_subdev *asd;
 705 
 706                 if (!v4l2_dev)
 707                         continue;
 708 
 709                 asd = v4l2_async_find_match(notifier, sd);
 710                 if (!asd)
 711                         continue;
 712 
 713                 ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
 714                 if (ret)
 715                         goto err_unbind;
 716 
 717                 ret = v4l2_async_notifier_try_complete(notifier);
 718                 if (ret)
 719                         goto err_unbind;
 720 
 721                 goto out_unlock;
 722         }
 723 
 724         /* None matched, wait for hot-plugging */
 725         list_add(&sd->async_list, &subdev_list);
 726 
 727 out_unlock:
 728         mutex_unlock(&list_lock);
 729 
 730         return 0;
 731 
 732 err_unbind:
 733         /*
 734          * Complete failed. Unbind the sub-devices bound through registering
 735          * this async sub-device.
 736          */
 737         subdev_notifier = v4l2_async_find_subdev_notifier(sd);
 738         if (subdev_notifier)
 739                 v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
 740 
 741         if (sd->asd)
 742                 v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
 743         v4l2_async_cleanup(sd);
 744 
 745         mutex_unlock(&list_lock);
 746 
 747         return ret;
 748 }
 749 EXPORT_SYMBOL(v4l2_async_register_subdev);
 750 
 751 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 752 {
 753         mutex_lock(&list_lock);
 754 
 755         __v4l2_async_notifier_unregister(sd->subdev_notifier);
 756         __v4l2_async_notifier_cleanup(sd->subdev_notifier);
 757         kfree(sd->subdev_notifier);
 758         sd->subdev_notifier = NULL;
 759 
 760         if (sd->asd) {
 761                 struct v4l2_async_notifier *notifier = sd->notifier;
 762 
 763                 list_add(&sd->asd->list, &notifier->waiting);
 764 
 765                 v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
 766         }
 767 
 768         v4l2_async_cleanup(sd);
 769 
 770         mutex_unlock(&list_lock);
 771 }
 772 EXPORT_SYMBOL(v4l2_async_unregister_subdev);

/* [<][>][^][v][top][bottom][index][help] */