Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: platform: Switch to v4l2_async_notifier_add_subdev

Switch all media platform drivers to call v4l2_async_notifier_add_subdev()
to add asd's to a notifier, in place of referencing the notifier->subdevs[]
array. These drivers also must now call v4l2_async_notifier_init() before
adding asd's to their notifiers.

There may still be cases where a platform driver maintains a list of
asd's that is a duplicate of the notifier asd_list, in which case its
possible the platform driver list can be removed, and can reference the
notifier asd_list instead. One example of where a duplicate list has
been removed in this patch is xilinx-vipp.c. If there are such cases
remaining, those drivers should be optimized to remove the duplicate
platform driver asd lists.

None of the changes to the platform drivers in this patch have been
tested. Verify that the async subdevices needed by the platform are
bound at load time, and that the driver unloads and reloads correctly
with no memory leaking of asd objects.

Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

authored by

Steve Longerbeam and committed by
Mauro Carvalho Chehab
d079f94c d5099f81

+417 -333
+1 -1
drivers/media/pci/intel/ipu3/ipu3-cio2.c
··· 1506 1506 if (ret < 0) 1507 1507 return ret; 1508 1508 1509 - if (!cio2->notifier.num_subdevs) 1509 + if (list_empty(&cio2->notifier.asd_list)) 1510 1510 return -ENODEV; /* no endpoint */ 1511 1511 1512 1512 cio2->notifier.ops = &cio2_async_ops;
+43 -39
drivers/media/platform/am437x/am437x-vpfe.c
··· 2423 2423 }; 2424 2424 2425 2425 static struct vpfe_config * 2426 - vpfe_get_pdata(struct platform_device *pdev) 2426 + vpfe_get_pdata(struct vpfe_device *vpfe) 2427 2427 { 2428 2428 struct device_node *endpoint = NULL; 2429 2429 struct v4l2_fwnode_endpoint bus_cfg; 2430 + struct device *dev = vpfe->pdev; 2430 2431 struct vpfe_subdev_info *sdinfo; 2431 2432 struct vpfe_config *pdata; 2432 2433 unsigned int flags; 2433 2434 unsigned int i; 2434 2435 int err; 2435 2436 2436 - dev_dbg(&pdev->dev, "vpfe_get_pdata\n"); 2437 + dev_dbg(dev, "vpfe_get_pdata\n"); 2437 2438 2438 - if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) 2439 - return pdev->dev.platform_data; 2439 + v4l2_async_notifier_init(&vpfe->notifier); 2440 2440 2441 - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 2441 + if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) 2442 + return dev->platform_data; 2443 + 2444 + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 2442 2445 if (!pdata) 2443 2446 return NULL; 2444 2447 2445 2448 for (i = 0; ; i++) { 2446 2449 struct device_node *rem; 2447 2450 2448 - endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, 2449 - endpoint); 2451 + endpoint = of_graph_get_next_endpoint(dev->of_node, endpoint); 2450 2452 if (!endpoint) 2451 2453 break; 2452 2454 ··· 2476 2474 err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), 2477 2475 &bus_cfg); 2478 2476 if (err) { 2479 - dev_err(&pdev->dev, "Could not parse the endpoint\n"); 2480 - goto done; 2477 + dev_err(dev, "Could not parse the endpoint\n"); 2478 + goto cleanup; 2481 2479 } 2482 2480 2483 2481 sdinfo->vpfe_param.bus_width = bus_cfg.bus.parallel.bus_width; 2484 2482 2485 2483 if (sdinfo->vpfe_param.bus_width < 8 || 2486 2484 sdinfo->vpfe_param.bus_width > 16) { 2487 - dev_err(&pdev->dev, "Invalid bus width.\n"); 2488 - goto done; 2485 + dev_err(dev, "Invalid bus width.\n"); 2486 + goto cleanup; 2489 2487 } 2490 2488 2491 2489 flags = bus_cfg.bus.parallel.flags; ··· 2498 2496 2499 2497 rem = of_graph_get_remote_port_parent(endpoint); 2500 2498 if (!rem) { 2501 - dev_err(&pdev->dev, "Remote device at %pOF not found\n", 2499 + dev_err(dev, "Remote device at %pOF not found\n", 2502 2500 endpoint); 2503 - goto done; 2501 + goto cleanup; 2504 2502 } 2505 2503 2506 - pdata->asd[i] = devm_kzalloc(&pdev->dev, 2507 - sizeof(struct v4l2_async_subdev), 2508 - GFP_KERNEL); 2509 - if (!pdata->asd[i]) { 2504 + pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( 2505 + &vpfe->notifier, of_fwnode_handle(rem), 2506 + sizeof(struct v4l2_async_subdev)); 2507 + if (IS_ERR(pdata->asd[i])) { 2510 2508 of_node_put(rem); 2511 - pdata = NULL; 2512 - goto done; 2509 + goto cleanup; 2513 2510 } 2514 - 2515 - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; 2516 - pdata->asd[i]->match.fwnode = of_fwnode_handle(rem); 2517 - of_node_put(rem); 2518 2511 } 2519 2512 2520 2513 of_node_put(endpoint); 2521 2514 return pdata; 2522 2515 2523 - done: 2516 + cleanup: 2517 + v4l2_async_notifier_cleanup(&vpfe->notifier); 2524 2518 of_node_put(endpoint); 2525 2519 return NULL; 2526 2520 } ··· 2528 2530 */ 2529 2531 static int vpfe_probe(struct platform_device *pdev) 2530 2532 { 2531 - struct vpfe_config *vpfe_cfg = vpfe_get_pdata(pdev); 2533 + struct vpfe_config *vpfe_cfg; 2532 2534 struct vpfe_device *vpfe; 2533 2535 struct vpfe_ccdc *ccdc; 2534 2536 struct resource *res; 2535 2537 int ret; 2536 - 2537 - if (!vpfe_cfg) { 2538 - dev_err(&pdev->dev, "No platform data\n"); 2539 - return -EINVAL; 2540 - } 2541 2538 2542 2539 vpfe = devm_kzalloc(&pdev->dev, sizeof(*vpfe), GFP_KERNEL); 2543 2540 if (!vpfe) 2544 2541 return -ENOMEM; 2545 2542 2546 2543 vpfe->pdev = &pdev->dev; 2544 + 2545 + vpfe_cfg = vpfe_get_pdata(vpfe); 2546 + if (!vpfe_cfg) { 2547 + dev_err(&pdev->dev, "No platform data\n"); 2548 + return -EINVAL; 2549 + } 2550 + 2547 2551 vpfe->cfg = vpfe_cfg; 2548 2552 ccdc = &vpfe->ccdc; 2549 2553 2550 2554 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2551 2555 ccdc->ccdc_cfg.base_addr = devm_ioremap_resource(&pdev->dev, res); 2552 - if (IS_ERR(ccdc->ccdc_cfg.base_addr)) 2553 - return PTR_ERR(ccdc->ccdc_cfg.base_addr); 2556 + if (IS_ERR(ccdc->ccdc_cfg.base_addr)) { 2557 + ret = PTR_ERR(ccdc->ccdc_cfg.base_addr); 2558 + goto probe_out_cleanup; 2559 + } 2554 2560 2555 2561 ret = platform_get_irq(pdev, 0); 2556 2562 if (ret <= 0) { 2557 2563 dev_err(&pdev->dev, "No IRQ resource\n"); 2558 - return -ENODEV; 2564 + ret = -ENODEV; 2565 + goto probe_out_cleanup; 2559 2566 } 2560 2567 vpfe->irq = ret; 2561 2568 ··· 2568 2565 "vpfe_capture0", vpfe); 2569 2566 if (ret) { 2570 2567 dev_err(&pdev->dev, "Unable to request interrupt\n"); 2571 - return -EINVAL; 2568 + ret = -EINVAL; 2569 + goto probe_out_cleanup; 2572 2570 } 2573 2571 2574 2572 ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev); 2575 2573 if (ret) { 2576 2574 vpfe_err(vpfe, 2577 2575 "Unable to register v4l2 device.\n"); 2578 - return ret; 2576 + goto probe_out_cleanup; 2579 2577 } 2580 2578 2581 2579 /* set the driver data in platform device */ ··· 2600 2596 goto probe_out_v4l2_unregister; 2601 2597 } 2602 2598 2603 - vpfe->notifier.subdevs = vpfe->cfg->asd; 2604 - vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd); 2605 2599 vpfe->notifier.ops = &vpfe_async_ops; 2606 - ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, 2607 - &vpfe->notifier); 2600 + ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, &vpfe->notifier); 2608 2601 if (ret) { 2609 2602 vpfe_err(vpfe, "Error registering async notifier\n"); 2610 2603 ret = -EINVAL; ··· 2612 2611 2613 2612 probe_out_v4l2_unregister: 2614 2613 v4l2_device_unregister(&vpfe->v4l2_dev); 2614 + probe_out_cleanup: 2615 + v4l2_async_notifier_cleanup(&vpfe->notifier); 2615 2616 return ret; 2616 2617 } 2617 2618 ··· 2629 2626 pm_runtime_disable(&pdev->dev); 2630 2627 2631 2628 v4l2_async_notifier_unregister(&vpfe->notifier); 2629 + v4l2_async_notifier_cleanup(&vpfe->notifier); 2632 2630 v4l2_device_unregister(&vpfe->v4l2_dev); 2633 2631 video_unregister_device(&vpfe->video_dev); 2634 2632
+12 -3
drivers/media/platform/atmel/atmel-isc.c
··· 1983 1983 { 1984 1984 struct isc_subdev_entity *subdev_entity; 1985 1985 1986 - list_for_each_entry(subdev_entity, &isc->subdev_entities, list) 1986 + list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { 1987 1987 v4l2_async_notifier_unregister(&subdev_entity->notifier); 1988 + v4l2_async_notifier_cleanup(&subdev_entity->notifier); 1989 + } 1988 1990 1989 1991 INIT_LIST_HEAD(&isc->subdev_entities); 1990 1992 } ··· 2203 2201 } 2204 2202 2205 2203 list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { 2206 - subdev_entity->notifier.subdevs = &subdev_entity->asd; 2207 - subdev_entity->notifier.num_subdevs = 1; 2204 + v4l2_async_notifier_init(&subdev_entity->notifier); 2205 + 2206 + ret = v4l2_async_notifier_add_subdev(&subdev_entity->notifier, 2207 + subdev_entity->asd); 2208 + if (ret) { 2209 + fwnode_handle_put(subdev_entity->asd->match.fwnode); 2210 + goto cleanup_subdev; 2211 + } 2212 + 2208 2213 subdev_entity->notifier.ops = &isc_async_ops; 2209 2214 2210 2215 ret = v4l2_async_notifier_register(&isc->v4l2_dev,
+7 -10
drivers/media/platform/atmel/atmel-isi.c
··· 1124 1124 1125 1125 static int isi_graph_init(struct atmel_isi *isi) 1126 1126 { 1127 - struct v4l2_async_subdev **subdevs = NULL; 1128 1127 int ret; 1129 1128 1130 1129 /* Parse the graph to extract a list of subdevice DT nodes. */ ··· 1133 1134 return ret; 1134 1135 } 1135 1136 1136 - /* Register the subdevices notifier. */ 1137 - subdevs = devm_kzalloc(isi->dev, sizeof(*subdevs), GFP_KERNEL); 1138 - if (!subdevs) { 1137 + v4l2_async_notifier_init(&isi->notifier); 1138 + 1139 + ret = v4l2_async_notifier_add_subdev(&isi->notifier, &isi->entity.asd); 1140 + if (ret) { 1139 1141 of_node_put(isi->entity.node); 1140 - return -ENOMEM; 1142 + return ret; 1141 1143 } 1142 1144 1143 - subdevs[0] = &isi->entity.asd; 1144 - 1145 - isi->notifier.subdevs = subdevs; 1146 - isi->notifier.num_subdevs = 1; 1147 1145 isi->notifier.ops = &isi_graph_notify_ops; 1148 1146 1149 1147 ret = v4l2_async_notifier_register(&isi->v4l2_dev, &isi->notifier); 1150 1148 if (ret < 0) { 1151 1149 dev_err(isi->dev, "Notifier registration failed\n"); 1152 - of_node_put(isi->entity.node); 1150 + v4l2_async_notifier_cleanup(&isi->notifier); 1153 1151 return ret; 1154 1152 } 1155 1153 ··· 1299 1303 isi->fb_descriptors_phys); 1300 1304 pm_runtime_disable(&pdev->dev); 1301 1305 v4l2_async_notifier_unregister(&isi->notifier); 1306 + v4l2_async_notifier_cleanup(&isi->notifier); 1302 1307 v4l2_device_unregister(&isi->v4l2_dev); 1303 1308 1304 1309 return 0;
+17 -11
drivers/media/platform/cadence/cdns-csi2rx.c
··· 399 399 csi2rx->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 400 400 of_node_put(ep); 401 401 402 - csi2rx->notifier.subdevs = devm_kzalloc(csi2rx->dev, 403 - sizeof(*csi2rx->notifier.subdevs), 404 - GFP_KERNEL); 405 - if (!csi2rx->notifier.subdevs) 406 - return -ENOMEM; 402 + v4l2_async_notifier_init(&csi2rx->notifier); 407 403 408 - csi2rx->notifier.subdevs[0] = &csi2rx->asd; 409 - csi2rx->notifier.num_subdevs = 1; 404 + ret = v4l2_async_notifier_add_subdev(&csi2rx->notifier, &csi2rx->asd); 405 + if (ret) { 406 + fwnode_handle_put(csi2rx->asd.match.fwnode); 407 + return ret; 408 + } 409 + 410 410 csi2rx->notifier.ops = &csi2rx_notifier_ops; 411 411 412 - return v4l2_async_subdev_notifier_register(&csi2rx->subdev, 413 - &csi2rx->notifier); 412 + ret = v4l2_async_subdev_notifier_register(&csi2rx->subdev, 413 + &csi2rx->notifier); 414 + if (ret) 415 + v4l2_async_notifier_cleanup(&csi2rx->notifier); 416 + 417 + return ret; 414 418 } 415 419 416 420 static int csi2rx_probe(struct platform_device *pdev) ··· 454 450 ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX, 455 451 csi2rx->pads); 456 452 if (ret) 457 - goto err_free_priv; 453 + goto err_cleanup; 458 454 459 455 ret = v4l2_async_register_subdev(&csi2rx->subdev); 460 456 if (ret < 0) 461 - goto err_free_priv; 457 + goto err_cleanup; 462 458 463 459 dev_info(&pdev->dev, 464 460 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n", ··· 467 463 468 464 return 0; 469 465 466 + err_cleanup: 467 + v4l2_async_notifier_cleanup(&csi2rx->notifier); 470 468 err_free_priv: 471 469 kfree(csi2rx); 472 470 return ret;
+38 -33
drivers/media/platform/davinci/vpif_capture.c
··· 1517 1517 struct vpif_capture_chan_config *chan; 1518 1518 unsigned int i; 1519 1519 1520 + v4l2_async_notifier_init(&vpif_obj.notifier); 1521 + 1520 1522 /* 1521 1523 * DT boot: OF node from parent device contains 1522 1524 * video ports & endpoints data. ··· 1550 1548 if (!endpoint) 1551 1549 break; 1552 1550 1551 + rem = of_graph_get_remote_port_parent(endpoint); 1552 + if (!rem) { 1553 + dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", 1554 + endpoint); 1555 + of_node_put(endpoint); 1556 + goto done; 1557 + } 1558 + 1553 1559 sdinfo = &pdata->subdev_info[i]; 1554 1560 chan = &pdata->chan_config[i]; 1555 1561 chan->inputs = devm_kcalloc(&pdev->dev, 1556 1562 VPIF_CAPTURE_NUM_CHANNELS, 1557 1563 sizeof(*chan->inputs), 1558 1564 GFP_KERNEL); 1559 - if (!chan->inputs) 1560 - return NULL; 1565 + if (!chan->inputs) { 1566 + of_node_put(rem); 1567 + of_node_put(endpoint); 1568 + goto err_cleanup; 1569 + } 1561 1570 1562 1571 chan->input_count++; 1563 1572 chan->inputs[i].input.type = V4L2_INPUT_TYPE_CAMERA; ··· 1577 1564 1578 1565 err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), 1579 1566 &bus_cfg); 1567 + of_node_put(endpoint); 1580 1568 if (err) { 1581 1569 dev_err(&pdev->dev, "Could not parse the endpoint\n"); 1570 + of_node_put(rem); 1582 1571 goto done; 1583 1572 } 1573 + 1584 1574 dev_dbg(&pdev->dev, "Endpoint %pOF, bus_width = %d\n", 1585 1575 endpoint, bus_cfg.bus.parallel.bus_width); 1576 + 1586 1577 flags = bus_cfg.bus.parallel.flags; 1587 1578 1588 1579 if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) ··· 1595 1578 if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) 1596 1579 chan->vpif_if.vd_pol = 1; 1597 1580 1598 - rem = of_graph_get_remote_port_parent(endpoint); 1599 - if (!rem) { 1600 - dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", 1601 - endpoint); 1602 - goto done; 1603 - } 1604 - 1605 1581 dev_dbg(&pdev->dev, "Remote device %pOF found\n", rem); 1606 1582 sdinfo->name = rem->full_name; 1607 1583 1608 - pdata->asd[i] = devm_kzalloc(&pdev->dev, 1609 - sizeof(struct v4l2_async_subdev), 1610 - GFP_KERNEL); 1611 - if (!pdata->asd[i]) { 1584 + pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( 1585 + &vpif_obj.notifier, of_fwnode_handle(rem), 1586 + sizeof(struct v4l2_async_subdev)); 1587 + if (IS_ERR(pdata->asd[i])) { 1612 1588 of_node_put(rem); 1613 - pdata = NULL; 1614 - goto done; 1589 + goto err_cleanup; 1615 1590 } 1616 - 1617 - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; 1618 - pdata->asd[i]->match.fwnode = of_fwnode_handle(rem); 1619 - of_node_put(rem); 1620 1591 } 1621 1592 1622 1593 done: 1623 - if (pdata) { 1624 - pdata->asd_sizes[0] = i; 1625 - pdata->subdev_count = i; 1626 - pdata->card_name = "DA850/OMAP-L138 Video Capture"; 1627 - } 1594 + pdata->asd_sizes[0] = i; 1595 + pdata->subdev_count = i; 1596 + pdata->card_name = "DA850/OMAP-L138 Video Capture"; 1628 1597 1629 1598 return pdata; 1599 + 1600 + err_cleanup: 1601 + v4l2_async_notifier_cleanup(&vpif_obj.notifier); 1602 + 1603 + return NULL; 1630 1604 } 1631 1605 1632 1606 /** ··· 1642 1634 return -EINVAL; 1643 1635 } 1644 1636 1645 - if (!pdev->dev.platform_data) { 1646 - dev_warn(&pdev->dev, "Missing platform data. Giving up.\n"); 1647 - return -EINVAL; 1648 - } 1649 - 1650 1637 vpif_dev = &pdev->dev; 1651 1638 1652 1639 err = initialize_vpif(); 1653 1640 if (err) { 1654 1641 v4l2_err(vpif_dev->driver, "Error initializing vpif\n"); 1655 - return err; 1642 + goto cleanup; 1656 1643 } 1657 1644 1658 1645 err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); 1659 1646 if (err) { 1660 1647 v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); 1661 - return err; 1648 + goto cleanup; 1662 1649 } 1663 1650 1664 1651 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { ··· 1702 1699 } 1703 1700 vpif_probe_complete(); 1704 1701 } else { 1705 - vpif_obj.notifier.subdevs = vpif_obj.config->asd; 1706 - vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; 1707 1702 vpif_obj.notifier.ops = &vpif_async_ops; 1708 1703 err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, 1709 1704 &vpif_obj.notifier); ··· 1719 1718 kfree(vpif_obj.sd); 1720 1719 vpif_unregister: 1721 1720 v4l2_device_unregister(&vpif_obj.v4l2_dev); 1721 + cleanup: 1722 + v4l2_async_notifier_cleanup(&vpif_obj.notifier); 1722 1723 1723 1724 return err; 1724 1725 } ··· 1736 1733 struct channel_obj *ch; 1737 1734 int i; 1738 1735 1736 + v4l2_async_notifier_unregister(&vpif_obj.notifier); 1737 + v4l2_async_notifier_cleanup(&vpif_obj.notifier); 1739 1738 v4l2_device_unregister(&vpif_obj.v4l2_dev); 1740 1739 1741 1740 kfree(vpif_obj.sd);
+17 -3
drivers/media/platform/davinci/vpif_display.c
··· 1300 1300 goto vpif_unregister; 1301 1301 } 1302 1302 1303 + v4l2_async_notifier_init(&vpif_obj.notifier); 1304 + 1303 1305 if (!vpif_obj.config->asd_sizes) { 1304 1306 i2c_adap = i2c_get_adapter(vpif_obj.config->i2c_adapter_id); 1305 1307 for (i = 0; i < subdev_count; i++) { ··· 1325 1323 goto probe_subdev_out; 1326 1324 } 1327 1325 } else { 1328 - vpif_obj.notifier.subdevs = vpif_obj.config->asd; 1329 - vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; 1326 + for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) { 1327 + err = v4l2_async_notifier_add_subdev( 1328 + &vpif_obj.notifier, vpif_obj.config->asd[i]); 1329 + if (err) 1330 + goto probe_cleanup; 1331 + } 1332 + 1330 1333 vpif_obj.notifier.ops = &vpif_async_ops; 1331 1334 err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, 1332 1335 &vpif_obj.notifier); 1333 1336 if (err) { 1334 1337 vpif_err("Error registering async notifier\n"); 1335 1338 err = -EINVAL; 1336 - goto probe_subdev_out; 1339 + goto probe_cleanup; 1337 1340 } 1338 1341 } 1339 1342 1340 1343 return 0; 1341 1344 1345 + probe_cleanup: 1346 + v4l2_async_notifier_cleanup(&vpif_obj.notifier); 1342 1347 probe_subdev_out: 1343 1348 kfree(vpif_obj.sd); 1344 1349 vpif_unregister: ··· 1363 1354 { 1364 1355 struct channel_obj *ch; 1365 1356 int i; 1357 + 1358 + if (vpif_obj.config->asd_sizes) { 1359 + v4l2_async_notifier_unregister(&vpif_obj.notifier); 1360 + v4l2_async_notifier_cleanup(&vpif_obj.notifier); 1361 + } 1366 1362 1367 1363 v4l2_device_unregister(&vpif_obj.v4l2_dev); 1368 1364
+23 -9
drivers/media/platform/exynos4-is/media-dev.c
··· 457 457 458 458 fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 459 459 fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem); 460 - fmd->async_subdevs[index] = &fmd->sensor[index].asd; 460 + 461 + ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier, 462 + &fmd->sensor[index].asd); 463 + if (ret) { 464 + of_node_put(rem); 465 + return ret; 466 + } 461 467 462 468 fmd->num_sensors++; 463 469 464 - of_node_put(rem); 465 470 return 0; 466 471 } 467 472 ··· 505 500 ret = fimc_md_parse_port_node(fmd, port, index); 506 501 if (ret < 0) { 507 502 of_node_put(node); 508 - goto rpm_put; 503 + goto cleanup; 509 504 } 510 505 index++; 511 506 } ··· 519 514 ret = fimc_md_parse_port_node(fmd, node, index); 520 515 if (ret < 0) { 521 516 of_node_put(node); 522 - break; 517 + goto cleanup; 523 518 } 524 519 index++; 525 520 } 521 + 526 522 rpm_put: 523 + pm_runtime_put(fmd->pmf); 524 + return 0; 525 + 526 + cleanup: 527 + v4l2_async_notifier_cleanup(&fmd->subdev_notifier); 527 528 pm_runtime_put(fmd->pmf); 528 529 return ret; 529 530 } ··· 1471 1460 1472 1461 platform_set_drvdata(pdev, fmd); 1473 1462 1463 + v4l2_async_notifier_init(&fmd->subdev_notifier); 1464 + 1474 1465 ret = fimc_md_register_platform_entities(fmd, dev->of_node); 1475 1466 if (ret) 1476 1467 goto err_clk; ··· 1483 1470 1484 1471 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); 1485 1472 if (ret) 1486 - goto err_m_ent; 1473 + goto err_cleanup; 1487 1474 /* 1488 1475 * FIMC platform devices need to be registered before the sclk_cam 1489 1476 * clocks provider, as one of these devices needs to be activated ··· 1496 1483 } 1497 1484 1498 1485 if (fmd->num_sensors > 0) { 1499 - fmd->subdev_notifier.subdevs = fmd->async_subdevs; 1500 - fmd->subdev_notifier.num_subdevs = fmd->num_sensors; 1501 1486 fmd->subdev_notifier.ops = &subdev_notifier_ops; 1502 1487 fmd->num_sensors = 0; 1503 1488 ··· 1511 1500 fimc_md_unregister_clk_provider(fmd); 1512 1501 err_attr: 1513 1502 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); 1514 - err_clk: 1515 - fimc_md_put_clocks(fmd); 1503 + err_cleanup: 1504 + v4l2_async_notifier_cleanup(&fmd->subdev_notifier); 1516 1505 err_m_ent: 1517 1506 fimc_md_unregister_entities(fmd); 1507 + err_clk: 1508 + fimc_md_put_clocks(fmd); 1518 1509 err_md: 1519 1510 media_device_cleanup(&fmd->media_dev); 1520 1511 v4l2_device_unregister(&fmd->v4l2_dev); ··· 1532 1519 1533 1520 fimc_md_unregister_clk_provider(fmd); 1534 1521 v4l2_async_notifier_unregister(&fmd->subdev_notifier); 1522 + v4l2_async_notifier_cleanup(&fmd->subdev_notifier); 1535 1523 1536 1524 v4l2_device_unregister(&fmd->v4l2_dev); 1537 1525 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
-1
drivers/media/platform/exynos4-is/media-dev.h
··· 149 149 } clk_provider; 150 150 151 151 struct v4l2_async_notifier subdev_notifier; 152 - struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS]; 153 152 154 153 bool user_subdev_api; 155 154 spinlock_t slock;
+15 -10
drivers/media/platform/pxa_camera.c
··· 697 697 struct v4l2_pix_format current_pix; 698 698 699 699 struct v4l2_async_subdev asd; 700 - struct v4l2_async_subdev *asds[1]; 701 700 702 701 /* 703 702 * PXA27x is only supposed to handle one camera on its Quick Capture ··· 2351 2352 2352 2353 asd->match_type = V4L2_ASYNC_MATCH_FWNODE; 2353 2354 remote = of_graph_get_remote_port(np); 2354 - if (remote) { 2355 + if (remote) 2355 2356 asd->match.fwnode = of_fwnode_handle(remote); 2356 - of_node_put(remote); 2357 - } else { 2357 + else 2358 2358 dev_notice(dev, "no remote for %pOF\n", np); 2359 - } 2360 2359 2361 2360 out: 2362 2361 of_node_put(np); ··· 2492 2495 if (err) 2493 2496 goto exit_deactivate; 2494 2497 2495 - pcdev->asds[0] = &pcdev->asd; 2496 - pcdev->notifier.subdevs = pcdev->asds; 2497 - pcdev->notifier.num_subdevs = 1; 2498 + v4l2_async_notifier_init(&pcdev->notifier); 2499 + 2500 + err = v4l2_async_notifier_add_subdev(&pcdev->notifier, &pcdev->asd); 2501 + if (err) { 2502 + fwnode_handle_put(pcdev->asd.match.fwnode); 2503 + goto exit_free_v4l2dev; 2504 + } 2505 + 2498 2506 pcdev->notifier.ops = &pxa_camera_sensor_ops; 2499 2507 2500 2508 if (!of_have_populated_dt()) ··· 2507 2505 2508 2506 err = pxa_camera_init_videobuf2(pcdev); 2509 2507 if (err) 2510 - goto exit_free_v4l2dev; 2508 + goto exit_notifier_cleanup; 2511 2509 2512 2510 if (pcdev->mclk) { 2513 2511 v4l2_clk_name_i2c(clk_name, sizeof(clk_name), ··· 2518 2516 clk_name, NULL); 2519 2517 if (IS_ERR(pcdev->mclk_clk)) { 2520 2518 err = PTR_ERR(pcdev->mclk_clk); 2521 - goto exit_free_v4l2dev; 2519 + goto exit_notifier_cleanup; 2522 2520 } 2523 2521 } 2524 2522 ··· 2529 2527 return 0; 2530 2528 exit_free_clk: 2531 2529 v4l2_clk_unregister(pcdev->mclk_clk); 2530 + exit_notifier_cleanup: 2531 + v4l2_async_notifier_cleanup(&pcdev->notifier); 2532 2532 exit_free_v4l2dev: 2533 2533 v4l2_device_unregister(&pcdev->v4l2_dev); 2534 2534 exit_deactivate: ··· 2554 2550 dma_release_channel(pcdev->dma_chans[2]); 2555 2551 2556 2552 v4l2_async_notifier_unregister(&pcdev->notifier); 2553 + v4l2_async_notifier_cleanup(&pcdev->notifier); 2557 2554 2558 2555 if (pcdev->mclk_clk) { 2559 2556 v4l2_clk_unregister(pcdev->mclk_clk);
+43 -48
drivers/media/platform/qcom/camss/camss.c
··· 462 462 * 463 463 * Return number of "port" nodes found in "ports" node 464 464 */ 465 - static int camss_of_parse_ports(struct device *dev, 466 - struct v4l2_async_notifier *notifier) 465 + static int camss_of_parse_ports(struct camss *camss) 467 466 { 467 + struct device *dev = camss->dev; 468 468 struct device_node *node = NULL; 469 469 struct device_node *remote = NULL; 470 - unsigned int size, i; 471 - int ret; 470 + int ret, num_subdevs = 0; 472 471 473 - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) 474 - if (of_device_is_available(node)) 475 - notifier->num_subdevs++; 476 - 477 - of_node_put(node); 478 - size = sizeof(*notifier->subdevs) * notifier->num_subdevs; 479 - notifier->subdevs = devm_kzalloc(dev, size, GFP_KERNEL); 480 - if (!notifier->subdevs) { 481 - dev_err(dev, "Failed to allocate memory\n"); 482 - return -ENOMEM; 483 - } 484 - 485 - i = 0; 486 - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) { 472 + for_each_endpoint_of_node(dev->of_node, node) { 487 473 struct camss_async_subdev *csd; 474 + struct v4l2_async_subdev *asd; 488 475 489 476 if (!of_device_is_available(node)) 490 477 continue; 491 478 492 - csd = devm_kzalloc(dev, sizeof(*csd), GFP_KERNEL); 493 - if (!csd) { 494 - of_node_put(node); 495 - dev_err(dev, "Failed to allocate memory\n"); 496 - return -ENOMEM; 497 - } 498 - 499 - notifier->subdevs[i++] = &csd->asd; 500 - 501 - ret = camss_of_parse_endpoint_node(dev, node, csd); 502 - if (ret < 0) { 503 - of_node_put(node); 504 - return ret; 505 - } 506 - 507 479 remote = of_graph_get_remote_port_parent(node); 508 480 if (!remote) { 509 481 dev_err(dev, "Cannot get remote parent\n"); 510 - of_node_put(node); 511 - return -EINVAL; 482 + ret = -EINVAL; 483 + goto err_cleanup; 512 484 } 513 485 514 - csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 515 - csd->asd.match.fwnode = of_fwnode_handle(remote); 516 - } 517 - of_node_put(node); 486 + asd = v4l2_async_notifier_add_fwnode_subdev( 487 + &camss->notifier, of_fwnode_handle(remote), 488 + sizeof(*csd)); 489 + if (IS_ERR(asd)) { 490 + ret = PTR_ERR(asd); 491 + of_node_put(remote); 492 + goto err_cleanup; 493 + } 518 494 519 - return notifier->num_subdevs; 495 + csd = container_of(asd, struct camss_async_subdev, asd); 496 + 497 + ret = camss_of_parse_endpoint_node(dev, node, csd); 498 + if (ret < 0) 499 + goto err_cleanup; 500 + 501 + num_subdevs++; 502 + } 503 + 504 + return num_subdevs; 505 + 506 + err_cleanup: 507 + v4l2_async_notifier_cleanup(&camss->notifier); 508 + of_node_put(node); 509 + return ret; 520 510 } 521 511 522 512 /* ··· 813 823 { 814 824 struct device *dev = &pdev->dev; 815 825 struct camss *camss; 816 - int ret; 826 + int num_subdevs, ret; 817 827 818 828 camss = kzalloc(sizeof(*camss), GFP_KERNEL); 819 829 if (!camss) ··· 853 863 if (!camss->vfe) 854 864 return -ENOMEM; 855 865 856 - ret = camss_of_parse_ports(dev, &camss->notifier); 857 - if (ret < 0) 858 - return ret; 866 + v4l2_async_notifier_init(&camss->notifier); 867 + 868 + num_subdevs = camss_of_parse_ports(camss); 869 + if (num_subdevs < 0) 870 + return num_subdevs; 859 871 860 872 ret = camss_init_subdevices(camss); 861 873 if (ret < 0) 862 - return ret; 874 + goto err_cleanup; 863 875 864 876 ret = dma_set_mask_and_coherent(dev, 0xffffffff); 865 877 if (ret) 866 - return ret; 878 + goto err_cleanup; 867 879 868 880 camss->media_dev.dev = camss->dev; 869 881 strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem", ··· 877 885 ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); 878 886 if (ret < 0) { 879 887 dev_err(dev, "Failed to register V4L2 device: %d\n", ret); 880 - return ret; 888 + goto err_cleanup; 881 889 } 882 890 883 891 ret = camss_register_entities(camss); 884 892 if (ret < 0) 885 893 goto err_register_entities; 886 894 887 - if (camss->notifier.num_subdevs) { 895 + if (num_subdevs) { 888 896 camss->notifier.ops = &camss_subdev_notifier_ops; 889 897 890 898 ret = v4l2_async_notifier_register(&camss->v4l2_dev, ··· 934 942 camss_unregister_entities(camss); 935 943 err_register_entities: 936 944 v4l2_device_unregister(&camss->v4l2_dev); 945 + err_cleanup: 946 + v4l2_async_notifier_cleanup(&camss->notifier); 937 947 938 948 return ret; 939 949 } ··· 972 978 msm_vfe_stop_streaming(&camss->vfe[i]); 973 979 974 980 v4l2_async_notifier_unregister(&camss->notifier); 981 + v4l2_async_notifier_cleanup(&camss->notifier); 975 982 camss_unregister_entities(camss); 976 983 977 984 if (atomic_read(&camss->ref_count) == 0)
+1 -1
drivers/media/platform/qcom/camss/camss.h
··· 91 91 }; 92 92 93 93 struct camss_async_subdev { 94 + struct v4l2_async_subdev asd; /* must be first */ 94 95 struct camss_camera_interface interface; 95 - struct v4l2_async_subdev asd; 96 96 }; 97 97 98 98 struct camss_clock {
+1 -1
drivers/media/platform/rcar-vin/rcar-core.c
··· 827 827 828 828 mutex_unlock(&vin->group->lock); 829 829 830 - if (!vin->group->notifier.num_subdevs) 830 + if (list_empty(&vin->group->notifier.asd_list)) 831 831 return 0; 832 832 833 833 vin->group->notifier.ops = &rvin_group_notify_ops;
+13 -9
drivers/media/platform/rcar-vin/rcar-csi2.c
··· 771 771 772 772 of_node_put(ep); 773 773 774 - priv->notifier.subdevs = devm_kzalloc(priv->dev, 775 - sizeof(*priv->notifier.subdevs), 776 - GFP_KERNEL); 777 - if (!priv->notifier.subdevs) 778 - return -ENOMEM; 774 + v4l2_async_notifier_init(&priv->notifier); 779 775 780 - priv->notifier.num_subdevs = 1; 781 - priv->notifier.subdevs[0] = &priv->asd; 776 + ret = v4l2_async_notifier_add_subdev(&priv->notifier, &priv->asd); 777 + if (ret) { 778 + fwnode_handle_put(priv->asd.match.fwnode); 779 + return ret; 780 + } 781 + 782 782 priv->notifier.ops = &rcar_csi2_notify_ops; 783 783 784 784 dev_dbg(priv->dev, "Found '%pOF'\n", 785 785 to_of_node(priv->asd.match.fwnode)); 786 786 787 - return v4l2_async_subdev_notifier_register(&priv->subdev, 788 - &priv->notifier); 787 + ret = v4l2_async_subdev_notifier_register(&priv->subdev, 788 + &priv->notifier); 789 + if (ret) 790 + v4l2_async_notifier_cleanup(&priv->notifier); 791 + 792 + return ret; 789 793 } 790 794 791 795 /* -----------------------------------------------------------------------------
+11 -7
drivers/media/platform/rcar_drif.c
··· 1213 1213 { 1214 1214 struct v4l2_async_notifier *notifier = &sdr->notifier; 1215 1215 struct fwnode_handle *fwnode, *ep; 1216 + int ret; 1216 1217 1217 - notifier->subdevs = devm_kzalloc(sdr->dev, sizeof(*notifier->subdevs), 1218 - GFP_KERNEL); 1219 - if (!notifier->subdevs) 1220 - return -ENOMEM; 1218 + v4l2_async_notifier_init(notifier); 1221 1219 1222 1220 ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node), 1223 1221 NULL); 1224 1222 if (!ep) 1225 1223 return 0; 1226 1224 1227 - notifier->subdevs[notifier->num_subdevs] = &sdr->ep.asd; 1228 1225 fwnode = fwnode_graph_get_remote_port_parent(ep); 1229 1226 if (!fwnode) { 1230 1227 dev_warn(sdr->dev, "bad remote port parent\n"); ··· 1231 1234 1232 1235 sdr->ep.asd.match.fwnode = fwnode; 1233 1236 sdr->ep.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 1234 - notifier->num_subdevs++; 1237 + ret = v4l2_async_notifier_add_subdev(notifier, &sdr->ep.asd); 1238 + if (ret) { 1239 + fwnode_handle_put(fwnode); 1240 + return ret; 1241 + } 1235 1242 1236 1243 /* Get the endpoint properties */ 1237 1244 rcar_drif_get_ep_properties(sdr, ep); ··· 1357 1356 ret = v4l2_async_notifier_register(&sdr->v4l2_dev, &sdr->notifier); 1358 1357 if (ret < 0) { 1359 1358 dev_err(sdr->dev, "failed: notifier register ret %d\n", ret); 1360 - goto error; 1359 + goto cleanup; 1361 1360 } 1362 1361 1363 1362 return ret; 1364 1363 1364 + cleanup: 1365 + v4l2_async_notifier_cleanup(&sdr->notifier); 1365 1366 error: 1366 1367 v4l2_device_unregister(&sdr->v4l2_dev); 1367 1368 ··· 1374 1371 static void rcar_drif_sdr_remove(struct rcar_drif_sdr *sdr) 1375 1372 { 1376 1373 v4l2_async_notifier_unregister(&sdr->notifier); 1374 + v4l2_async_notifier_cleanup(&sdr->notifier); 1377 1375 v4l2_device_unregister(&sdr->v4l2_dev); 1378 1376 } 1379 1377
+29 -24
drivers/media/platform/renesas-ceu.c
··· 189 189 190 190 /* async subdev notification helpers */ 191 191 struct v4l2_async_notifier notifier; 192 - /* pointers to "struct ceu_subdevice -> asd" */ 193 - struct v4l2_async_subdev **asds; 194 192 195 193 /* vb2 queue, capture buffer list and active buffer pointer */ 196 194 struct vb2_queue vb2_vq; ··· 1480 1482 if (!ceudev->subdevs) 1481 1483 return -ENOMEM; 1482 1484 1483 - /* 1484 - * Reserve memory for 'n_sd' pointers to async_subdevices. 1485 - * ceudev->asds members will point to &ceu_subdev.asd 1486 - */ 1487 - ceudev->asds = devm_kcalloc(ceudev->dev, n_sd, 1488 - sizeof(*ceudev->asds), GFP_KERNEL); 1489 - if (!ceudev->asds) 1490 - return -ENOMEM; 1491 - 1492 1485 ceudev->sd = NULL; 1493 1486 ceudev->sd_index = 0; 1494 1487 ceudev->num_sd = 0; ··· 1507 1518 return ret; 1508 1519 1509 1520 for (i = 0; i < pdata->num_subdevs; i++) { 1521 + 1510 1522 /* Setup the ceu subdevice and the async subdevice. */ 1511 1523 async_sd = &pdata->subdevs[i]; 1512 1524 ceu_sd = &ceudev->subdevs[i]; ··· 1519 1529 ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id; 1520 1530 ceu_sd->asd.match.i2c.address = async_sd->i2c_address; 1521 1531 1522 - ceudev->asds[i] = &ceu_sd->asd; 1532 + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, 1533 + &ceu_sd->asd); 1534 + if (ret) { 1535 + v4l2_async_notifier_cleanup(&ceudev->notifier); 1536 + return ret; 1537 + } 1523 1538 } 1524 1539 1525 1540 return pdata->num_subdevs; ··· 1537 1542 { 1538 1543 struct device_node *of = ceudev->dev->of_node; 1539 1544 struct v4l2_fwnode_endpoint fw_ep; 1545 + struct device_node *ep, *remote; 1540 1546 struct ceu_subdev *ceu_sd; 1541 - struct device_node *ep; 1542 1547 unsigned int i; 1543 1548 int num_ep; 1544 1549 int ret; ··· 1557 1562 dev_err(ceudev->dev, 1558 1563 "No subdevice connected on endpoint %u.\n", i); 1559 1564 ret = -ENODEV; 1560 - goto error_put_node; 1565 + goto error_cleanup; 1561 1566 } 1562 1567 1563 1568 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep); 1564 1569 if (ret) { 1565 1570 dev_err(ceudev->dev, 1566 1571 "Unable to parse endpoint #%u.\n", i); 1567 - goto error_put_node; 1572 + goto error_cleanup; 1568 1573 } 1569 1574 1570 1575 if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) { 1571 1576 dev_err(ceudev->dev, 1572 1577 "Only parallel input supported.\n"); 1573 1578 ret = -EINVAL; 1574 - goto error_put_node; 1579 + goto error_cleanup; 1575 1580 } 1576 1581 1577 1582 /* Setup the ceu subdevice and the async subdevice. */ 1578 1583 ceu_sd = &ceudev->subdevs[i]; 1579 1584 INIT_LIST_HEAD(&ceu_sd->asd.list); 1580 1585 1586 + remote = of_graph_get_remote_port_parent(ep); 1581 1587 ceu_sd->mbus_flags = fw_ep.bus.parallel.flags; 1582 1588 ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 1583 - ceu_sd->asd.match.fwnode = 1584 - fwnode_graph_get_remote_port_parent( 1585 - of_fwnode_handle(ep)); 1589 + ceu_sd->asd.match.fwnode = of_fwnode_handle(remote); 1586 1590 1587 - ceudev->asds[i] = &ceu_sd->asd; 1591 + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, 1592 + &ceu_sd->asd); 1593 + if (ret) { 1594 + of_node_put(remote); 1595 + goto error_cleanup; 1596 + } 1597 + 1588 1598 of_node_put(ep); 1589 1599 } 1590 1600 1591 1601 return num_ep; 1592 1602 1593 - error_put_node: 1603 + error_cleanup: 1604 + v4l2_async_notifier_cleanup(&ceudev->notifier); 1594 1605 of_node_put(ep); 1595 1606 return ret; 1596 1607 } ··· 1675 1674 if (ret) 1676 1675 goto error_pm_disable; 1677 1676 1677 + v4l2_async_notifier_init(&ceudev->notifier); 1678 + 1678 1679 if (IS_ENABLED(CONFIG_OF) && dev->of_node) { 1679 1680 ceu_data = of_match_device(ceu_of_match, dev)->data; 1680 1681 num_subdevs = ceu_parse_dt(ceudev); ··· 1696 1693 ceudev->irq_mask = ceu_data->irq_mask; 1697 1694 1698 1695 ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev; 1699 - ceudev->notifier.subdevs = ceudev->asds; 1700 - ceudev->notifier.num_subdevs = num_subdevs; 1701 1696 ceudev->notifier.ops = &ceu_notify_ops; 1702 1697 ret = v4l2_async_notifier_register(&ceudev->v4l2_dev, 1703 1698 &ceudev->notifier); 1704 1699 if (ret) 1705 - goto error_v4l2_unregister; 1700 + goto error_cleanup; 1706 1701 1707 1702 dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev)); 1708 1703 1709 1704 return 0; 1710 1705 1706 + error_cleanup: 1707 + v4l2_async_notifier_cleanup(&ceudev->notifier); 1711 1708 error_v4l2_unregister: 1712 1709 v4l2_device_unregister(&ceudev->v4l2_dev); 1713 1710 error_pm_disable: ··· 1725 1722 pm_runtime_disable(ceudev->dev); 1726 1723 1727 1724 v4l2_async_notifier_unregister(&ceudev->notifier); 1725 + 1726 + v4l2_async_notifier_cleanup(&ceudev->notifier); 1728 1727 1729 1728 v4l2_device_unregister(&ceudev->v4l2_dev); 1730 1729
+25 -10
drivers/media/platform/soc_camera/soc_camera.c
··· 1442 1442 goto eaddpdev; 1443 1443 } 1444 1444 1445 - sasc->notifier.subdevs = asd; 1446 - sasc->notifier.num_subdevs = size; 1445 + v4l2_async_notifier_init(&sasc->notifier); 1446 + 1447 + for (i = 0; i < size; i++) { 1448 + ret = v4l2_async_notifier_add_subdev(&sasc->notifier, asd[i]); 1449 + if (ret) 1450 + goto eaddasd; 1451 + } 1452 + 1447 1453 sasc->notifier.ops = &soc_camera_async_ops; 1448 1454 1449 1455 icd->sasc = sasc; ··· 1472 1466 v4l2_clk_unregister(icd->clk); 1473 1467 eclkreg: 1474 1468 icd->clk = NULL; 1469 + eaddasd: 1470 + v4l2_async_notifier_cleanup(&sasc->notifier); 1475 1471 platform_device_del(sasc->pdev); 1476 1472 eaddpdev: 1477 1473 platform_device_put(sasc->pdev); ··· 1548 1540 goto eaddpdev; 1549 1541 } 1550 1542 1551 - sasc->notifier.subdevs = &info->subdev; 1552 - sasc->notifier.num_subdevs = 1; 1543 + v4l2_async_notifier_init(&sasc->notifier); 1544 + 1545 + ret = v4l2_async_notifier_add_subdev(&sasc->notifier, info->subdev); 1546 + if (ret) { 1547 + of_node_put(remote); 1548 + goto eaddasd; 1549 + } 1550 + 1553 1551 sasc->notifier.ops = &soc_camera_async_ops; 1554 1552 1555 1553 icd->sasc = sasc; ··· 1582 1568 v4l2_clk_unregister(icd->clk); 1583 1569 eclkreg: 1584 1570 icd->clk = NULL; 1571 + eaddasd: 1572 + v4l2_async_notifier_cleanup(&sasc->notifier); 1585 1573 platform_device_del(sasc->pdev); 1586 1574 eaddpdev: 1587 1575 platform_device_put(sasc->pdev); ··· 1598 1582 { 1599 1583 struct device *dev = ici->v4l2_dev.dev; 1600 1584 struct device_node *np = dev->of_node; 1601 - struct device_node *epn = NULL, *ren; 1585 + struct device_node *epn = NULL, *rem; 1602 1586 unsigned int i; 1603 1587 1604 1588 for (i = 0; ; i++) { ··· 1606 1590 if (!epn) 1607 1591 break; 1608 1592 1609 - ren = of_graph_get_remote_port(epn); 1610 - if (!ren) { 1593 + rem = of_graph_get_remote_port_parent(epn); 1594 + if (!rem) { 1611 1595 dev_notice(dev, "no remote for %pOF\n", epn); 1612 1596 continue; 1613 1597 } 1614 1598 1615 1599 /* so we now have a remote node to connect */ 1616 1600 if (!i) 1617 - soc_of_bind(ici, epn, ren->parent); 1618 - 1619 - of_node_put(ren); 1601 + soc_of_bind(ici, epn, rem); 1620 1602 1621 1603 if (i) { 1622 1604 dev_err(dev, "multiple subdevices aren't supported yet!\n"); ··· 1940 1926 list_for_each_entry(sasc, &notifiers, list) { 1941 1927 /* Must call unlocked to avoid AB-BA dead-lock */ 1942 1928 v4l2_async_notifier_unregister(&sasc->notifier); 1929 + v4l2_async_notifier_cleanup(&sasc->notifier); 1943 1930 put_device(&sasc->pdev->dev); 1944 1931 } 1945 1932
+12 -12
drivers/media/platform/stm32/stm32-dcmi.c
··· 1590 1590 1591 1591 static int dcmi_graph_init(struct stm32_dcmi *dcmi) 1592 1592 { 1593 - struct v4l2_async_subdev **subdevs = NULL; 1594 1593 int ret; 1595 1594 1596 1595 /* Parse the graph to extract a list of subdevice DT nodes. */ ··· 1599 1600 return ret; 1600 1601 } 1601 1602 1602 - /* Register the subdevices notifier. */ 1603 - subdevs = devm_kzalloc(dcmi->dev, sizeof(*subdevs), GFP_KERNEL); 1604 - if (!subdevs) { 1603 + v4l2_async_notifier_init(&dcmi->notifier); 1604 + 1605 + ret = v4l2_async_notifier_add_subdev(&dcmi->notifier, 1606 + &dcmi->entity.asd); 1607 + if (ret) { 1605 1608 of_node_put(dcmi->entity.node); 1606 - return -ENOMEM; 1609 + return ret; 1607 1610 } 1608 1611 1609 - subdevs[0] = &dcmi->entity.asd; 1610 - 1611 - dcmi->notifier.subdevs = subdevs; 1612 - dcmi->notifier.num_subdevs = 1; 1613 1612 dcmi->notifier.ops = &dcmi_graph_notify_ops; 1614 1613 1615 1614 ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier); 1616 1615 if (ret < 0) { 1617 1616 dev_err(dcmi->dev, "Notifier registration failed\n"); 1618 - of_node_put(dcmi->entity.node); 1617 + v4l2_async_notifier_cleanup(&dcmi->notifier); 1619 1618 return ret; 1620 1619 } 1621 1620 ··· 1770 1773 ret = reset_control_assert(dcmi->rstc); 1771 1774 if (ret) { 1772 1775 dev_err(&pdev->dev, "Failed to assert the reset line\n"); 1773 - goto err_device_release; 1776 + goto err_cleanup; 1774 1777 } 1775 1778 1776 1779 usleep_range(3000, 5000); ··· 1778 1781 ret = reset_control_deassert(dcmi->rstc); 1779 1782 if (ret) { 1780 1783 dev_err(&pdev->dev, "Failed to deassert the reset line\n"); 1781 - goto err_device_release; 1784 + goto err_cleanup; 1782 1785 } 1783 1786 1784 1787 dev_info(&pdev->dev, "Probe done\n"); ··· 1789 1792 1790 1793 return 0; 1791 1794 1795 + err_cleanup: 1796 + v4l2_async_notifier_cleanup(&dcmi->notifier); 1792 1797 err_device_release: 1793 1798 video_device_release(dcmi->vdev); 1794 1799 err_device_unregister: ··· 1808 1809 pm_runtime_disable(&pdev->dev); 1809 1810 1810 1811 v4l2_async_notifier_unregister(&dcmi->notifier); 1812 + v4l2_async_notifier_cleanup(&dcmi->notifier); 1811 1813 v4l2_device_unregister(&dcmi->v4l2_dev); 1812 1814 1813 1815 dma_release_channel(dcmi->dma_chan);
+29 -4
drivers/media/platform/ti-vpe/cal.c
··· 270 270 struct v4l2_fwnode_endpoint endpoint; 271 271 272 272 struct v4l2_async_subdev asd; 273 - struct v4l2_async_subdev *asd_list[1]; 274 273 275 274 struct v4l2_fh fh; 276 275 struct cal_dev *dev; ··· 1734 1735 ctx_dbg(1, ctx, "Port: %d found sub-device %pOFn\n", 1735 1736 inst, sensor_node); 1736 1737 1737 - ctx->asd_list[0] = asd; 1738 - ctx->notifier.subdevs = ctx->asd_list; 1739 - ctx->notifier.num_subdevs = 1; 1738 + v4l2_async_notifier_init(&ctx->notifier); 1739 + 1740 + ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd); 1741 + if (ret) { 1742 + ctx_err(ctx, "Error adding asd\n"); 1743 + goto cleanup_exit; 1744 + } 1745 + 1740 1746 ctx->notifier.ops = &cal_async_ops; 1741 1747 ret = v4l2_async_notifier_register(&ctx->v4l2_dev, 1742 1748 &ctx->notifier); 1743 1749 if (ret) { 1744 1750 ctx_err(ctx, "Error registering async notifier\n"); 1751 + v4l2_async_notifier_cleanup(&ctx->notifier); 1745 1752 ret = -EINVAL; 1746 1753 } 1754 + 1755 + /* 1756 + * On success we need to keep reference on sensor_node, or 1757 + * if notifier_cleanup was called above, sensor_node was 1758 + * already put. 1759 + */ 1760 + sensor_node = NULL; 1747 1761 1748 1762 cleanup_exit: 1749 1763 of_node_put(remote_ep); ··· 1818 1806 static int cal_probe(struct platform_device *pdev) 1819 1807 { 1820 1808 struct cal_dev *dev; 1809 + struct cal_ctx *ctx; 1821 1810 int ret; 1822 1811 int irq; 1812 + int i; 1823 1813 1824 1814 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 1825 1815 if (!dev) ··· 1889 1875 1890 1876 runtime_disable: 1891 1877 pm_runtime_disable(&pdev->dev); 1878 + for (i = 0; i < CAL_NUM_CONTEXT; i++) { 1879 + ctx = dev->ctx[i]; 1880 + if (ctx) { 1881 + v4l2_async_notifier_unregister(&ctx->notifier); 1882 + v4l2_async_notifier_cleanup(&ctx->notifier); 1883 + v4l2_ctrl_handler_free(&ctx->ctrl_handler); 1884 + v4l2_device_unregister(&ctx->v4l2_dev); 1885 + } 1886 + } 1887 + 1892 1888 return ret; 1893 1889 } 1894 1890 ··· 1920 1896 video_device_node_name(&ctx->vdev)); 1921 1897 camerarx_phy_disable(ctx); 1922 1898 v4l2_async_notifier_unregister(&ctx->notifier); 1899 + v4l2_async_notifier_cleanup(&ctx->notifier); 1923 1900 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 1924 1901 v4l2_device_unregister(&ctx->v4l2_dev); 1925 1902 video_unregister_device(&ctx->vdev);
+80 -93
drivers/media/platform/xilinx/xilinx-vipp.c
··· 32 32 33 33 /** 34 34 * struct xvip_graph_entity - Entity in the video graph 35 - * @list: list entry in a graph entities list 36 - * @node: the entity's DT node 37 - * @entity: media entity, from the corresponding V4L2 subdev 38 35 * @asd: subdev asynchronous registration information 36 + * @entity: media entity, from the corresponding V4L2 subdev 39 37 * @subdev: V4L2 subdev 40 38 */ 41 39 struct xvip_graph_entity { 42 - struct list_head list; 43 - struct device_node *node; 40 + struct v4l2_async_subdev asd; /* must be first */ 44 41 struct media_entity *entity; 45 - 46 - struct v4l2_async_subdev asd; 47 42 struct v4l2_subdev *subdev; 48 43 }; 44 + 45 + static inline struct xvip_graph_entity * 46 + to_xvip_entity(struct v4l2_async_subdev *asd) 47 + { 48 + return container_of(asd, struct xvip_graph_entity, asd); 49 + } 49 50 50 51 /* ----------------------------------------------------------------------------- 51 52 * Graph Management ··· 54 53 55 54 static struct xvip_graph_entity * 56 55 xvip_graph_find_entity(struct xvip_composite_device *xdev, 57 - const struct device_node *node) 56 + const struct fwnode_handle *fwnode) 58 57 { 59 58 struct xvip_graph_entity *entity; 59 + struct v4l2_async_subdev *asd; 60 60 61 - list_for_each_entry(entity, &xdev->entities, list) { 62 - if (entity->node == node) 61 + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { 62 + entity = to_xvip_entity(asd); 63 + if (entity->asd.match.fwnode == fwnode) 63 64 return entity; 64 65 } 65 66 ··· 78 75 struct media_pad *remote_pad; 79 76 struct xvip_graph_entity *ent; 80 77 struct v4l2_fwnode_link link; 81 - struct device_node *ep = NULL; 78 + struct fwnode_handle *ep = NULL; 82 79 int ret = 0; 83 80 84 81 dev_dbg(xdev->dev, "creating links for entity %s\n", local->name); 85 82 86 83 while (1) { 87 84 /* Get the next endpoint and parse its link. */ 88 - ep = of_graph_get_next_endpoint(entity->node, ep); 85 + ep = fwnode_graph_get_next_endpoint(entity->asd.match.fwnode, 86 + ep); 89 87 if (ep == NULL) 90 88 break; 91 89 92 - dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep); 90 + dev_dbg(xdev->dev, "processing endpoint %p\n", ep); 93 91 94 - ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); 92 + ret = v4l2_fwnode_parse_link(ep, &link); 95 93 if (ret < 0) { 96 - dev_err(xdev->dev, "failed to parse link for %pOF\n", 94 + dev_err(xdev->dev, "failed to parse link for %p\n", 97 95 ep); 98 96 continue; 99 97 } ··· 103 99 * the link. 104 100 */ 105 101 if (link.local_port >= local->num_pads) { 106 - dev_err(xdev->dev, "invalid port number %u for %pOF\n", 107 - link.local_port, 108 - to_of_node(link.local_node)); 102 + dev_err(xdev->dev, "invalid port number %u for %p\n", 103 + link.local_port, link.local_node); 109 104 v4l2_fwnode_put_link(&link); 110 105 ret = -EINVAL; 111 106 break; ··· 113 110 local_pad = &local->pads[link.local_port]; 114 111 115 112 if (local_pad->flags & MEDIA_PAD_FL_SINK) { 116 - dev_dbg(xdev->dev, "skipping sink port %pOF:%u\n", 117 - to_of_node(link.local_node), 118 - link.local_port); 113 + dev_dbg(xdev->dev, "skipping sink port %p:%u\n", 114 + link.local_node, link.local_port); 119 115 v4l2_fwnode_put_link(&link); 120 116 continue; 121 117 } 122 118 123 119 /* Skip DMA engines, they will be processed separately. */ 124 120 if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) { 125 - dev_dbg(xdev->dev, "skipping DMA port %pOF:%u\n", 126 - to_of_node(link.local_node), 127 - link.local_port); 121 + dev_dbg(xdev->dev, "skipping DMA port %p:%u\n", 122 + link.local_node, link.local_port); 128 123 v4l2_fwnode_put_link(&link); 129 124 continue; 130 125 } 131 126 132 127 /* Find the remote entity. */ 133 - ent = xvip_graph_find_entity(xdev, 134 - to_of_node(link.remote_node)); 128 + ent = xvip_graph_find_entity(xdev, link.remote_node); 135 129 if (ent == NULL) { 136 - dev_err(xdev->dev, "no entity found for %pOF\n", 137 - to_of_node(link.remote_node)); 130 + dev_err(xdev->dev, "no entity found for %p\n", 131 + link.remote_node); 138 132 v4l2_fwnode_put_link(&link); 139 133 ret = -ENODEV; 140 134 break; ··· 140 140 remote = ent->entity; 141 141 142 142 if (link.remote_port >= remote->num_pads) { 143 - dev_err(xdev->dev, "invalid port number %u on %pOF\n", 144 - link.remote_port, to_of_node(link.remote_node)); 143 + dev_err(xdev->dev, "invalid port number %u on %p\n", 144 + link.remote_port, link.remote_node); 145 145 v4l2_fwnode_put_link(&link); 146 146 ret = -EINVAL; 147 147 break; ··· 168 168 } 169 169 } 170 170 171 - of_node_put(ep); 171 + fwnode_handle_put(ep); 172 172 return ret; 173 173 } 174 174 ··· 230 230 dma->video.name); 231 231 232 232 /* Find the remote entity. */ 233 - ent = xvip_graph_find_entity(xdev, 234 - to_of_node(link.remote_node)); 233 + ent = xvip_graph_find_entity(xdev, link.remote_node); 235 234 if (ent == NULL) { 236 235 dev_err(xdev->dev, "no entity found for %pOF\n", 237 236 to_of_node(link.remote_node)); ··· 288 289 struct xvip_composite_device *xdev = 289 290 container_of(notifier, struct xvip_composite_device, notifier); 290 291 struct xvip_graph_entity *entity; 292 + struct v4l2_async_subdev *asd; 291 293 int ret; 292 294 293 295 dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); 294 296 295 297 /* Create links for every entity. */ 296 - list_for_each_entry(entity, &xdev->entities, list) { 298 + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { 299 + entity = to_xvip_entity(asd); 297 300 ret = xvip_graph_build_one(xdev, entity); 298 301 if (ret < 0) 299 302 return ret; ··· 315 314 316 315 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, 317 316 struct v4l2_subdev *subdev, 318 - struct v4l2_async_subdev *asd) 317 + struct v4l2_async_subdev *unused) 319 318 { 320 319 struct xvip_composite_device *xdev = 321 320 container_of(notifier, struct xvip_composite_device, notifier); 322 321 struct xvip_graph_entity *entity; 322 + struct v4l2_async_subdev *asd; 323 323 324 324 /* Locate the entity corresponding to the bound subdev and store the 325 325 * subdev pointer. 326 326 */ 327 - list_for_each_entry(entity, &xdev->entities, list) { 328 - if (entity->node != subdev->dev->of_node) 327 + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { 328 + entity = to_xvip_entity(asd); 329 + 330 + if (entity->asd.match.fwnode != subdev->fwnode) 329 331 continue; 330 332 331 333 if (entity->subdev) { 332 - dev_err(xdev->dev, "duplicate subdev for node %pOF\n", 333 - entity->node); 334 + dev_err(xdev->dev, "duplicate subdev for node %p\n", 335 + entity->asd.match.fwnode); 334 336 return -EINVAL; 335 337 } 336 338 ··· 353 349 }; 354 350 355 351 static int xvip_graph_parse_one(struct xvip_composite_device *xdev, 356 - struct device_node *node) 352 + struct fwnode_handle *fwnode) 357 353 { 358 - struct xvip_graph_entity *entity; 359 - struct device_node *remote; 360 - struct device_node *ep = NULL; 354 + struct fwnode_handle *remote; 355 + struct fwnode_handle *ep = NULL; 361 356 int ret = 0; 362 357 363 - dev_dbg(xdev->dev, "parsing node %pOF\n", node); 358 + dev_dbg(xdev->dev, "parsing node %p\n", fwnode); 364 359 365 360 while (1) { 366 - ep = of_graph_get_next_endpoint(node, ep); 361 + struct v4l2_async_subdev *asd; 362 + 363 + ep = fwnode_graph_get_next_endpoint(fwnode, ep); 367 364 if (ep == NULL) 368 365 break; 369 366 370 - dev_dbg(xdev->dev, "handling endpoint %pOF\n", ep); 367 + dev_dbg(xdev->dev, "handling endpoint %p\n", ep); 371 368 372 - remote = of_graph_get_remote_port_parent(ep); 369 + remote = fwnode_graph_get_remote_port_parent(ep); 373 370 if (remote == NULL) { 374 371 ret = -EINVAL; 375 - break; 372 + goto err_notifier_cleanup; 376 373 } 377 374 375 + fwnode_handle_put(ep); 376 + 378 377 /* Skip entities that we have already processed. */ 379 - if (remote == xdev->dev->of_node || 378 + if (remote == of_fwnode_handle(xdev->dev->of_node) || 380 379 xvip_graph_find_entity(xdev, remote)) { 381 - of_node_put(remote); 380 + fwnode_handle_put(remote); 382 381 continue; 383 382 } 384 383 385 - entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL); 386 - if (entity == NULL) { 387 - of_node_put(remote); 388 - ret = -ENOMEM; 389 - break; 384 + asd = v4l2_async_notifier_add_fwnode_subdev( 385 + &xdev->notifier, remote, 386 + sizeof(struct xvip_graph_entity)); 387 + if (IS_ERR(asd)) { 388 + ret = PTR_ERR(asd); 389 + fwnode_handle_put(remote); 390 + goto err_notifier_cleanup; 390 391 } 391 - 392 - entity->node = remote; 393 - entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 394 - entity->asd.match.fwnode = of_fwnode_handle(remote); 395 - list_add_tail(&entity->list, &xdev->entities); 396 - xdev->num_subdevs++; 397 392 } 398 393 399 - of_node_put(ep); 394 + return 0; 395 + 396 + err_notifier_cleanup: 397 + v4l2_async_notifier_cleanup(&xdev->notifier); 398 + fwnode_handle_put(ep); 400 399 return ret; 401 400 } 402 401 403 402 static int xvip_graph_parse(struct xvip_composite_device *xdev) 404 403 { 405 404 struct xvip_graph_entity *entity; 405 + struct v4l2_async_subdev *asd; 406 406 int ret; 407 407 408 408 /* ··· 415 407 * loop will handle entities added at the end of the list while walking 416 408 * the links. 417 409 */ 418 - ret = xvip_graph_parse_one(xdev, xdev->dev->of_node); 410 + ret = xvip_graph_parse_one(xdev, of_fwnode_handle(xdev->dev->of_node)); 419 411 if (ret < 0) 420 412 return 0; 421 413 422 - list_for_each_entry(entity, &xdev->entities, list) { 423 - ret = xvip_graph_parse_one(xdev, entity->node); 424 - if (ret < 0) 414 + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { 415 + entity = to_xvip_entity(asd); 416 + ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode); 417 + if (ret < 0) { 418 + v4l2_async_notifier_cleanup(&xdev->notifier); 425 419 break; 420 + } 426 421 } 427 422 428 423 return ret; ··· 496 485 497 486 static void xvip_graph_cleanup(struct xvip_composite_device *xdev) 498 487 { 499 - struct xvip_graph_entity *entityp; 500 - struct xvip_graph_entity *entity; 501 488 struct xvip_dma *dmap; 502 489 struct xvip_dma *dma; 503 490 504 491 v4l2_async_notifier_unregister(&xdev->notifier); 505 - 506 - list_for_each_entry_safe(entity, entityp, &xdev->entities, list) { 507 - of_node_put(entity->node); 508 - list_del(&entity->list); 509 - } 492 + v4l2_async_notifier_cleanup(&xdev->notifier); 510 493 511 494 list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) { 512 495 xvip_dma_cleanup(dma); ··· 510 505 511 506 static int xvip_graph_init(struct xvip_composite_device *xdev) 512 507 { 513 - struct xvip_graph_entity *entity; 514 - struct v4l2_async_subdev **subdevs = NULL; 515 - unsigned int num_subdevs; 516 - unsigned int i; 517 508 int ret; 518 509 519 510 /* Init the DMA channels. */ ··· 526 525 goto done; 527 526 } 528 527 529 - if (!xdev->num_subdevs) { 528 + if (list_empty(&xdev->notifier.asd_list)) { 530 529 dev_err(xdev->dev, "no subdev found in graph\n"); 531 530 goto done; 532 531 } 533 532 534 533 /* Register the subdevices notifier. */ 535 - num_subdevs = xdev->num_subdevs; 536 - subdevs = devm_kcalloc(xdev->dev, num_subdevs, sizeof(*subdevs), 537 - GFP_KERNEL); 538 - if (subdevs == NULL) { 539 - ret = -ENOMEM; 540 - goto done; 541 - } 542 - 543 - i = 0; 544 - list_for_each_entry(entity, &xdev->entities, list) 545 - subdevs[i++] = &entity->asd; 546 - 547 - xdev->notifier.subdevs = subdevs; 548 - xdev->notifier.num_subdevs = num_subdevs; 549 534 xdev->notifier.ops = &xvip_graph_notify_ops; 550 535 551 536 ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier); ··· 597 610 return -ENOMEM; 598 611 599 612 xdev->dev = &pdev->dev; 600 - INIT_LIST_HEAD(&xdev->entities); 601 613 INIT_LIST_HEAD(&xdev->dmas); 614 + v4l2_async_notifier_init(&xdev->notifier); 602 615 603 616 ret = xvip_composite_v4l2_init(xdev); 604 617 if (ret < 0)
-4
drivers/media/platform/xilinx/xilinx-vipp.h
··· 28 28 * @media_dev: media device 29 29 * @dev: (OF) device 30 30 * @notifier: V4L2 asynchronous subdevs notifier 31 - * @entities: entities in the graph as a list of xvip_graph_entity 32 - * @num_subdevs: number of subdevs in the pipeline 33 31 * @dmas: list of DMA channels at the pipeline output and input 34 32 * @v4l2_caps: V4L2 capabilities of the whole device (see VIDIOC_QUERYCAP) 35 33 */ ··· 37 39 struct device *dev; 38 40 39 41 struct v4l2_async_notifier notifier; 40 - struct list_head entities; 41 - unsigned int num_subdevs; 42 42 43 43 struct list_head dmas; 44 44 u32 v4l2_caps;