/** * sysfs_chmod_file - update the modified mode value on an object attribute. * @kobj: object we're acting for. * @attr: attribute descriptor. * @mode: file permissions. * */ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct sysfs_dirent *victim_sd = NULL; struct dentry *victim = NULL; struct inode * inode; struct iattr newattrs; int rc; rc = -ENOENT; victim_sd = sysfs_get_dirent(kobj->sd, attr->name); if (!victim_sd) goto out; victim = sysfs_get_dentry(victim_sd); if (IS_ERR(victim)) { rc = PTR_ERR(victim); victim = NULL; goto out; } inode = victim->d_inode; mutex_lock(&inode->i_mutex); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; rc = notify_change(victim, &newattrs); mutex_unlock(&inode->i_mutex); out: dput(victim); sysfs_put(victim_sd); return rc; }
/** * sysfs_update_file - update the modified timestamp on an object attribute. * @kobj: object we're acting for. * @attr: attribute descriptor. */ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) { struct sysfs_dirent *victim_sd = NULL; struct dentry *victim = NULL; int rc; rc = -ENOENT; victim_sd = sysfs_get_dirent(kobj->sd, attr->name); if (!victim_sd) goto out; victim = sysfs_get_dentry(victim_sd); if (IS_ERR(victim)) { rc = PTR_ERR(victim); victim = NULL; goto out; } mutex_lock(&victim->d_inode->i_mutex); victim->d_inode->i_mtime = CURRENT_TIME; fsnotify_modify(victim); mutex_unlock(&victim->d_inode->i_mutex); rc = 0; out: dput(victim); sysfs_put(victim_sd); return rc; }
/** * sysfs_remove_link_from_group - remove a symlink from an attribute group. * @kobj: The kobject containing the group. * @group_name: The name of the group. * @link_name: The name of the symlink to remove. */ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, const char *link_name) { struct sysfs_dirent *dir_sd; dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name); if (dir_sd) { sysfs_hash_and_remove(dir_sd, NULL, link_name); sysfs_put(dir_sd); } }
/** * sysfs_remove_file_from_group - remove an attribute file from a group. * @kobj: object we're acting for. * @attr: attribute descriptor. * @group: group name. */ void sysfs_remove_file_from_group(struct kobject *kobj, const struct attribute *attr, const char *group) { struct sysfs_dirent *dir_sd; dir_sd = sysfs_get_dirent(kobj->sd, group); if (dir_sd) { sysfs_hash_and_remove(dir_sd, attr->name); sysfs_put(dir_sd); } }
/** * sysfs_unmerge_group - remove files from a pre-existing attribute group. * @kobj: The kobject containing the group. * @grp: The files to remove and the attribute group they belong to. */ void sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp) { struct sysfs_dirent *dir_sd; struct attribute *const *attr; dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); if (dir_sd) { for (attr = grp->attrs; *attr; ++attr) sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); sysfs_put(dir_sd); } }
/** * sysfs_add_link_to_group - add a symlink to an attribute group. * @kobj: The kobject containing the group. * @group_name: The name of the group. * @target: The target kobject of the symlink to create. * @link_name: The name of the symlink to create. */ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, struct kobject *target, const char *link_name) { struct sysfs_dirent *dir_sd; int error = 0; dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name); if (!dir_sd) return -ENOENT; error = sysfs_create_link_sd(dir_sd, target, link_name); sysfs_put(dir_sd); return error; }
/** * sysfs_add_file_to_group - add an attribute file to a pre-existing group. * @kobj: object we're acting for. * @attr: attribute descriptor. * @group: group name. */ int sysfs_add_file_to_group(struct kobject *kobj, const struct attribute *attr, const char *group) { struct sysfs_dirent *dir_sd; int error; dir_sd = sysfs_get_dirent(kobj->sd, group); if (!dir_sd) return -ENOENT; error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR); sysfs_put(dir_sd); return error; }
void sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) { struct sysfs_dirent *dir_sd = kobj->sd; struct sysfs_dirent *sd; if (grp->name) { sd = sysfs_get_dirent(dir_sd, grp->name); BUG_ON(!sd); } else sd = sysfs_get(dir_sd); remove_files(sd, grp); if (grp->name) sysfs_remove_subdir(sd); sysfs_put(sd); }
static struct kobject *ve_kobj_path_create(char *path) { char *e, *p = path; struct sysfs_dirent *sd, *parent_sd = get_exec_env()->_sysfs_root; struct kobject *k, *pk = NULL; if (*p == '/') p++; while (1) { e = strchr(p, '/'); if (e) *e = '\0'; sd = sysfs_get_dirent(parent_sd, p); if (sd == NULL) { new: k = kobject_create_and_add(p, pk); kobject_put(pk); if (!k) return ERR_PTR(-ENOMEM); } else { if (!(sd->s_flags & SYSFS_DIR)) {
/** * sysfs_merge_group - merge files into a pre-existing attribute group. * @kobj: The kobject containing the group. * @grp: The files to create and the attribute group they belong to. * * This function returns an error if the group doesn't exist or any of the * files already exist in that group, in which case none of the new files * are created. */ int sysfs_merge_group(struct kobject *kobj, const struct attribute_group *grp) { struct sysfs_dirent *dir_sd; int error = 0; struct attribute *const *attr; int i; dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); if (!dir_sd) return -ENOENT; for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr)) error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); if (error) { while (--i >= 0) sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name); } sysfs_put(dir_sd); return error; }
void sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) { struct sysfs_dirent *dir_sd = kobj->sd; struct sysfs_dirent *sd; if (grp->name) { sd = sysfs_get_dirent(dir_sd, NULL, grp->name); if (!sd) { WARN(!sd, KERN_WARNING "sysfs group %p not found for " "kobject '%s'\n", grp, kobject_name(kobj)); return; } } else sd = sysfs_get(dir_sd); remove_files(sd, kobj, grp); if (grp->name) sysfs_remove_subdir(sd); sysfs_put(sd); }
int mdp3_ctrl_init(struct msm_fb_data_type *mfd) { struct device *dev = mfd->fbi->dev; struct msm_mdp_interface *mdp3_interface = &mfd->mdp; struct mdp3_session_data *mdp3_session = NULL; u32 intf_type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO; int rc; int splash_mismatch = 0; pr_info("mdp3_ctrl_init\n"); rc = mdp3_parse_dt_splash(mfd); if (rc) splash_mismatch = 1; mdp3_interface->on_fnc = mdp3_ctrl_on; mdp3_interface->off_fnc = mdp3_ctrl_off; mdp3_interface->do_histogram = NULL; mdp3_interface->cursor_update = NULL; mdp3_interface->dma_fnc = mdp3_ctrl_pan_display; mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler; mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff; mdp3_interface->lut_update = mdp3_ctrl_lut_update; mdp3_interface->configure_panel = mdp3_update_panel_info; mdp3_session = kzalloc(sizeof(struct mdp3_session_data), GFP_KERNEL); if (!mdp3_session) { pr_err("fail to allocate mdp3 private data structure"); return -ENOMEM; } mutex_init(&mdp3_session->lock); INIT_WORK(&mdp3_session->clk_off_work, mdp3_dispatch_clk_off); INIT_WORK(&mdp3_session->dma_done_work, mdp3_dispatch_dma_done); atomic_set(&mdp3_session->vsync_countdown, 0); mutex_init(&mdp3_session->histo_lock); mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL); if (!mdp3_session->dma) { rc = -ENODEV; goto init_done; } rc = mdp3_dma_init(mdp3_session->dma); if (rc) { pr_err("fail to init dma\n"); goto init_done; } intf_type = mdp3_ctrl_get_intf_type(mfd); mdp3_session->intf = mdp3_get_display_intf(intf_type); if (!mdp3_session->intf) { rc = -ENODEV; goto init_done; } rc = mdp3_intf_init(mdp3_session->intf); if (rc) { pr_err("fail to init interface\n"); goto init_done; } mdp3_session->dma->output_config.out_sel = intf_type; mdp3_session->mfd = mfd; mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev); mdp3_session->status = mdp3_session->intf->active; mdp3_session->overlay.id = MSMFB_NEW_REQUEST; mdp3_bufq_init(&mdp3_session->bufq_in); mdp3_bufq_init(&mdp3_session->bufq_out); mdp3_session->histo_status = 0; mdp3_session->lut_sel = 0; BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head); init_timer(&mdp3_session->vsync_timer); mdp3_session->vsync_timer.function = mdp3_vsync_timer_func; mdp3_session->vsync_timer.data = (u32)mdp3_session; mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate; mfd->mdp.private1 = mdp3_session; init_completion(&mdp3_session->dma_completion); if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) mdp3_session->wait_for_dma_done = mdp3_wait_for_dma_done; rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group); if (rc) { pr_err("vsync sysfs group creation failed, ret=%d\n", rc); goto init_done; } mdp3_session->vsync_event_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "vsync_event"); if (!mdp3_session->vsync_event_sd) { pr_err("vsync_event sysfs lookup failed\n"); rc = -ENODEV; goto init_done; } rc = mdp3_create_sysfs_link(dev); if (rc) pr_warn("problem creating link to mdp sysfs\n"); kobject_uevent(&dev->kobj, KOBJ_ADD); pr_debug("vsync kobject_uevent(KOBJ_ADD)\n"); if (mdp3_get_cont_spash_en()) { mdp3_session->clk_on = 1; mdp3_session->in_splash_screen = 1; mdp3_ctrl_notifier_register(mdp3_session, &mdp3_session->mfd->mdp_sync_pt_data.notifier); } if (splash_mismatch) { pr_err("splash memory mismatch, stop splash\n"); mdp3_ctrl_off(mfd); } mdp3_session->vsync_before_commit = true; init_done: if (IS_ERR_VALUE(rc)) kfree(mdp3_session); return rc; }
static int mic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int brdnum = mic_data.dd_numdevs; int err = 0; bd_info_t *bd_info; mic_ctx_t *mic_ctx; #ifdef CONFIG_PCI_MSI int i=0; #endif if ((bd_info = (bd_info_t *)kzalloc(sizeof(bd_info_t), GFP_KERNEL)) == NULL) { printk("MIC: probe failed allocating memory for bd_info\n"); return -ENOSPC; } mic_ctx = &bd_info->bi_ctx; mic_ctx->bd_info = bd_info; mic_ctx->bi_id = brdnum; mic_ctx->bi_pdev = pdev; mic_ctx->msie = 0; mic_data.dd_bi[brdnum] = bd_info; if ((err = pci_enable_device(pdev))) { printk("pci_enable failed board #%d\n", brdnum); goto probe_freebd; } pci_set_master(pdev); err = pci_reenable_device(pdev); err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { printk("mic %d: ERROR DMA not available\n", brdnum); goto probe_freebd; } err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { printk("mic %d: ERROR pci_set_consistent_dma_mask(64) %d\n", brdnum, err); err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { printk("mic %d: ERROR pci_set_consistent_dma_mask(32) %d\n", brdnum, err); goto probe_freebd; } } // Allocate bar 4 for MMIO and GTT bd_info->bi_ctx.mmio.pa = pci_resource_start(pdev, DLDR_MMIO_BAR); bd_info->bi_ctx.mmio.len = pci_resource_len(pdev, DLDR_MMIO_BAR); if (request_mem_region(bd_info->bi_ctx.mmio.pa, bd_info->bi_ctx.mmio.len, "mic") == NULL) { printk("mic %d: failed to reserve mmio space\n", brdnum); goto probe_freebd; } // Allocate bar 0 for access Aperture bd_info->bi_ctx.aper.pa = pci_resource_start(pdev, DLDR_APT_BAR); bd_info->bi_ctx.aper.len = pci_resource_len(pdev, DLDR_APT_BAR); if (request_mem_region(bd_info->bi_ctx.aper.pa, bd_info->bi_ctx.aper.len, "mic") == NULL) { printk("mic %d: failed to reserve aperture space\n", brdnum); goto probe_relmmio; } #ifdef CONFIG_PCI_MSI if (mic_msi_enable){ for (i = 0; i < MIC_NUM_MSIX_ENTRIES; i ++) bd_info->bi_msix_entries[i].entry = i; err = pci_enable_msix(mic_ctx->bi_pdev, bd_info->bi_msix_entries, MIC_NUM_MSIX_ENTRIES); if (err == 0 ) { // Only support 1 MSIx for now err = request_irq(bd_info->bi_msix_entries[0].vector, mic_irq_isr, 0, "mic", mic_ctx); if (err != 0) { printk("MIC: Error in request_irq %d\n", err); goto probe_relaper; } mic_ctx->msie = 1; } } #endif // TODO: this needs to be hardened and actually return errors if ((err = adapter_init_device(mic_ctx)) != 0) { printk("MIC: Adapter init device failed %d\n", err); goto probe_relaper; } // Adding sysfs entries set_sysfs_entries(mic_ctx); bd_info->bi_sysfsdev = device_create(mic_lindata.dd_class, &pdev->dev, mic_lindata.dd_dev + 2 + mic_ctx->bd_info->bi_ctx.bi_id, NULL, "mic%d", mic_ctx->bd_info->bi_ctx.bi_id); err = sysfs_create_group(&mic_ctx->bd_info->bi_sysfsdev->kobj, &bd_attr_group); mic_ctx->sysfs_state = sysfs_get_dirent(mic_ctx->bd_info->bi_sysfsdev->kobj.sd, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)) //NULL, #endif "state"); dev_set_drvdata(mic_ctx->bd_info->bi_sysfsdev, mic_ctx); if (!mic_ctx->msie) if ((err = request_irq(mic_ctx->bi_pdev->irq, mic_irq_isr, IRQF_SHARED, "mic", mic_ctx)) != 0) { printk("MIC: Error in request_irq %d\n", err); goto probe_unmapaper; } adapter_probe(&bd_info->bi_ctx); if (mic_ctx->bi_psmi.enabled) { err = sysfs_create_group(&mic_ctx->bd_info->bi_sysfsdev->kobj, &psmi_attr_group); err = device_create_bin_file(mic_ctx->bd_info->bi_sysfsdev, &mic_psmi_ptes_attr); } adapter_wait_reset(mic_ctx); // Adding a board instance so increment the total number of MICs in the system. list_add_tail(&bd_info->bi_list, &mic_data.dd_bdlist); mic_data.dd_numdevs++; printk("mic_probe %d:%d:%d as board #%d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), brdnum); return 0; probe_unmapaper: wait_event(mic_ctx->ioremapwq, mic_ctx->aper.va || mic_ctx->state == MIC_RESETFAIL); if (mic_ctx->aper.va) iounmap((void *)bd_info->bi_ctx.aper.va); iounmap((void *)bd_info->bi_ctx.mmio.va); probe_relaper: release_mem_region(bd_info->bi_ctx.aper.pa, bd_info->bi_ctx.aper.len); probe_relmmio: release_mem_region(bd_info->bi_ctx.mmio.pa, bd_info->bi_ctx.mmio.len); probe_freebd: kfree(bd_info); return err; }
int vsp_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; struct ttm_bo_device *bdev = &dev_priv->bdev; struct vsp_private *vsp_priv; bool is_iomem; int ret; unsigned int context_size; VSP_DEBUG("init vsp private data structure\n"); vsp_priv = kmalloc(sizeof(struct vsp_private), GFP_KERNEL); if (vsp_priv == NULL) return -1; memset(vsp_priv, 0, sizeof(*vsp_priv)); /* get device --> drm_device --> drm_psb_private --> vsp_priv * for psb_vsp_pmstate_show: vsp_pmpolicy * if not pci_set_drvdata, can't get drm_device from device */ /* pci_set_drvdata(dev->pdev, dev); */ if (device_create_file(&dev->pdev->dev, &dev_attr_vsp_pmstate)) DRM_ERROR("TOPAZ: could not create sysfs file\n"); vsp_priv->sysfs_pmstate = sysfs_get_dirent( dev->pdev->dev.kobj.sd, NULL, "vsp_pmstate"); vsp_priv->vsp_cmd_num = 0; vsp_priv->fw_loaded = VSP_FW_NONE; vsp_priv->current_sequence = 0; vsp_priv->vsp_state = VSP_STATE_DOWN; vsp_priv->dev = dev; vsp_priv->coded_buf = NULL; vsp_priv->context_num = 0; atomic_set(&dev_priv->vsp_mmu_invaldc, 0); dev_priv->vsp_private = vsp_priv; vsp_priv->cmd_queue_sz = VSP_CMD_QUEUE_SIZE * sizeof(struct vss_command_t); #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) ret = ttm_buffer_object_create(bdev, vsp_priv->cmd_queue_sz, ttm_bo_type_kernel, DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT, 0, 0, 0, NULL, &vsp_priv->cmd_queue_bo); #else ret = ttm_buffer_object_create(bdev, vsp_priv->cmd_queue_sz, ttm_bo_type_kernel, DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT, 0, 0, NULL, &vsp_priv->cmd_queue_bo); #endif if (ret != 0) { DRM_ERROR("VSP: failed to allocate VSP cmd queue\n"); goto out_clean; } vsp_priv->ack_queue_sz = VSP_ACK_QUEUE_SIZE * sizeof(struct vss_response_t); #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) ret = ttm_buffer_object_create(bdev, vsp_priv->ack_queue_sz, ttm_bo_type_kernel, DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT, 0, 0, 0, NULL, &vsp_priv->ack_queue_bo); #else ret = ttm_buffer_object_create(bdev, vsp_priv->ack_queue_sz, ttm_bo_type_kernel, DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT, 0, 0, NULL, &vsp_priv->ack_queue_bo); #endif if (ret != 0) { DRM_ERROR("VSP: failed to allocate VSP cmd ack queue\n"); goto out_clean; } /* Create setting buffer */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) ret = ttm_buffer_object_create(bdev, sizeof(struct vsp_settings_t), ttm_bo_type_kernel, DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT, 0, 0, 0, NULL, &vsp_priv->setting_bo); #else ret = ttm_buffer_object_create(bdev, sizeof(struct vsp_settings_t), ttm_bo_type_kernel, DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT, 0, 0, NULL, &vsp_priv->setting_bo); #endif if (ret != 0) { DRM_ERROR("VSP: failed to allocate VSP setting buffer\n"); goto out_clean; } /* map cmd queue */ ret = ttm_bo_kmap(vsp_priv->cmd_queue_bo, 0, vsp_priv->cmd_queue_bo->num_pages, &vsp_priv->cmd_kmap); if (ret) { DRM_ERROR("drm_bo_kmap failed: %d\n", ret); ttm_bo_unref(&vsp_priv->cmd_queue_bo); ttm_bo_kunmap(&vsp_priv->cmd_kmap); goto out_clean; } vsp_priv->cmd_queue = ttm_kmap_obj_virtual(&vsp_priv->cmd_kmap, &is_iomem); /* map ack queue */ ret = ttm_bo_kmap(vsp_priv->ack_queue_bo, 0, vsp_priv->ack_queue_bo->num_pages, &vsp_priv->ack_kmap); if (ret) { DRM_ERROR("drm_bo_kmap failed: %d\n", ret); ttm_bo_unref(&vsp_priv->ack_queue_bo); ttm_bo_kunmap(&vsp_priv->ack_kmap); goto out_clean; } vsp_priv->ack_queue = ttm_kmap_obj_virtual(&vsp_priv->ack_kmap, &is_iomem); /* map vsp setting */ ret = ttm_bo_kmap(vsp_priv->setting_bo, 0, vsp_priv->setting_bo->num_pages, &vsp_priv->setting_kmap); if (ret) { DRM_ERROR("drm_bo_kmap setting_bo failed: %d\n", ret); ttm_bo_unref(&vsp_priv->setting_bo); ttm_bo_kunmap(&vsp_priv->setting_kmap); goto out_clean; } vsp_priv->setting = ttm_kmap_obj_virtual(&vsp_priv->setting_kmap, &is_iomem); vsp_priv->vp8_filp[0] = NULL; vsp_priv->vp8_filp[1] = NULL; vsp_priv->context_vp8_num = 0; vsp_priv->vp8_cmd_num = 0; spin_lock_init(&vsp_priv->lock); mutex_init(&vsp_priv->vsp_mutex); INIT_DELAYED_WORK(&vsp_priv->vsp_suspend_wq, &psb_powerdown_vsp); INIT_DELAYED_WORK(&vsp_priv->vsp_irq_wq, &vsp_irq_task); return 0; out_clean: vsp_deinit(dev); return -1; }
int mdp3_ctrl_init(struct msm_fb_data_type *mfd) { struct device *dev = mfd->fbi->dev; struct msm_mdp_interface *mdp3_interface = &mfd->mdp; struct mdp3_session_data *mdp3_session = NULL; u32 intf_type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO; int rc; pr_debug("mdp3_ctrl_init\n"); mdp3_interface->on_fnc = mdp3_ctrl_on; mdp3_interface->off_fnc = mdp3_ctrl_off; mdp3_interface->do_histogram = NULL; mdp3_interface->cursor_update = NULL; mdp3_interface->dma_fnc = mdp3_ctrl_pan_display; mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler; mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff; mdp3_interface->lut_update = mdp3_ctrl_lut_update; mdp3_session = kmalloc(sizeof(struct mdp3_session_data), GFP_KERNEL); if (!mdp3_session) { pr_err("fail to allocate mdp3 private data structure"); return -ENOMEM; } memset(mdp3_session, 0, sizeof(struct mdp3_session_data)); mutex_init(&mdp3_session->lock); mutex_init(&mdp3_session->histo_lock); mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL); if (!mdp3_session->dma) { rc = -ENODEV; goto init_done; } intf_type = mdp3_ctrl_get_intf_type(mfd); mdp3_session->intf = mdp3_get_display_intf(intf_type); if (!mdp3_session->intf) { rc = -ENODEV; goto init_done; } mdp3_session->mfd = mfd; mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev); mdp3_session->status = 0; mdp3_session->overlay.id = MSMFB_NEW_REQUEST; mdp3_bufq_init(&mdp3_session->bufq_in); mdp3_bufq_init(&mdp3_session->bufq_out); mdp3_session->histo_status = 0; mdp3_session->lut_sel = 0; init_timer(&mdp3_session->vsync_timer); mdp3_session->vsync_timer.function = mdp3_vsync_timer_func; mdp3_session->vsync_timer.data = (u32)mdp3_session; mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate; mfd->mdp.private1 = mdp3_session; rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group); if (rc) { pr_err("vsync sysfs group creation failed, ret=%d\n", rc); goto init_done; } mdp3_session->vsync_event_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "vsync_event"); if (!mdp3_session->vsync_event_sd) { pr_err("vsync_event sysfs lookup failed\n"); rc = -ENODEV; goto init_done; } kobject_uevent(&dev->kobj, KOBJ_ADD); pr_debug("vsync kobject_uevent(KOBJ_ADD)\n"); init_done: if (IS_ERR_VALUE(rc)) kfree(mdp3_session); return rc; }