/** * crystalhd_user_close - Close application handle. * @ctx: Command layer contextx. * @uc: User ID context. * * Return: * status * * Closer application handle and release app specific * resources. */ enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc) { uint32_t mode = uc->mode; ctx->user[uc->uid].mode = DTS_MODE_INV; ctx->user[uc->uid].in_use = 0; ctx->cin_wait_exit = 1; ctx->pwr_state_change = 0; BCMLOG(BCMLOG_INFO, "Closing user[%x] handle\n", uc->uid); if ((mode == DTS_DIAG_MODE) || (mode == DTS_PLAYBACK_MODE)) { crystalhd_hw_free_dma_rings(&ctx->hw_ctx); crystalhd_destroy_dio_pool(ctx->adp); } else if (bc_cproc_get_user_count(ctx)) { return BC_STS_SUCCESS; } crystalhd_hw_close(&ctx->hw_ctx); ctx->state = BC_LINK_INVALID; return BC_STS_SUCCESS; }
static int chd_dec_close(struct inode *in, struct file *fd) { struct crystalhd_adp *adp = chd_get_adp(); struct device *dev = &adp->pdev->dev; struct crystalhd_cmd *ctx = &adp->cmds; struct crystalhd_user *uc; uint32_t mode; dev_dbg(dev, "Entering %s\n", __func__); if (!adp) { dev_err(dev, "Invalid adp\n"); return -EINVAL; } uc = fd->private_data; if (!uc) { dev_err(dev, "Failed to get uc\n"); return -ENODATA; } /* Check and close only if we have not flush/closed before */ /* This is needed because release is not guarenteed to be called immediately on close, * if duplicate file handles exist due to fork etc. This causes problems with close and re-open of the device immediately */ if(uc->in_use) { mode = uc->mode; ctx->user[uc->uid].mode = DTS_MODE_INV; ctx->user[uc->uid].in_use = 0; dev_info(chddev(), "Closing user[%x] handle with mode %x\n", uc->uid, mode); if (((mode & 0xFF) == DTS_DIAG_MODE) || ((mode & 0xFF) == DTS_PLAYBACK_MODE) || ((bc_get_userhandle_count(ctx) == 0) && (ctx->hw_ctx != NULL))) { ctx->cin_wait_exit = 1; ctx->pwr_state_change = BC_HW_RUNNING; /* Stop the HW Capture just in case flush did not get called before stop */ /* And only if we had actually started it */ if(ctx->hw_ctx->rx_freeq != NULL) { crystalhd_hw_stop_capture(ctx->hw_ctx, true); crystalhd_hw_free_dma_rings(ctx->hw_ctx); } if(ctx->adp->fill_byte_pool) crystalhd_destroy_dio_pool(ctx->adp); if(ctx->adp->elem_pool_head) crystalhd_delete_elem_pool(ctx->adp); ctx->state = BC_LINK_INVALID; crystalhd_hw_close(ctx->hw_ctx, ctx->adp); kfree(ctx->hw_ctx); ctx->hw_ctx = NULL; } uc->in_use = 0; if(adp->cfg_users > 0) adp->cfg_users--; } return 0; }