v4l2_subdev_init_finalize

/**
 * v4l2_subdev_init_finalize() - Finalize the initialization of the subdevice
 * @sd: The subdev
 *
 * This finalizes the initialization of the subdev, including allocation of
 * the active state for the subdev.
 *
 * This must be called by the subdev drivers that use the centralized active
 * state, after the subdev struct has been initialized and
 * media_entity_pads_init() has been called.
 *
 * Must call v4l2_subdev_cleanup() when the subdev is being removed.
 */
#define v4l2_subdev_init_finalize(sd)                                          \
    ({                                                                     \
        static struct lock_class_key __key;                            \
        const char *name = KBUILD_BASENAME                             \
            ":" __stringify(__LINE__) ":subdev->state->lock";      \
        __v4l2_subdev_init_finalize(sd, name, &__key);                 \
    })

int __v4l2_subdev_init_finalize(struct v4l2_subdev *sd, const char *name,
                struct lock_class_key *key)
{
    struct v4l2_subdev_state *state;

    state = __v4l2_subdev_state_alloc(sd, name, key);
    if (IS_ERR(state))
        return PTR_ERR(state);

    sd->state = state;

    return 0;
}

struct v4l2_subdev_state *
__v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name,
              struct lock_class_key *lock_key)
{
    struct v4l2_subdev_state *state;
    int ret;

    state = kzalloc(sizeof(*state), GFP_KERNEL);
    if (!state)
        return ERR_PTR(-ENOMEM);

    __mutex_init(&state->lock, lock_name, lock_key);

    /* Drivers that support streams do not need the legacy pad config */
    if (!(sd->flags & V4L2_SUBDEV_FL_MULTIPLEXED) && sd->entity.num_pads) {
        state->pads = kvmalloc_array(sd->entity.num_pads,
                         sizeof(*state->pads),
                         GFP_KERNEL | __GFP_ZERO);
        if (!state->pads) {
            ret = -ENOMEM;
            goto err;
        }
    }

    ret = v4l2_subdev_call(sd, pad, init_cfg, state);
    if (ret < 0 && ret != -ENOIOCTLCMD)
        goto err;

    return state;

err:
    if (state && state->pads)
        kvfree(state->pads);

    kfree(state);

    return ERR_PTR(ret);
}

你可能感兴趣的:(linux,driver,func,linux)