コード例 #1
0
/**
 * 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;
}
コード例 #2
0
ファイル: crystalhd_hw.c プロジェクト: NTICompass/crystalhd
BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *hw)
{
	struct device *dev;
	unsigned int i;
	void *mem;
	size_t mem_len;
	dma_addr_t phy_addr;
	BC_STATUS sts = BC_STS_SUCCESS;
	struct crystalhd_rx_dma_pkt *rpkt;

	if (!hw || !hw->adp) {
		printk(KERN_ERR "%s: Invalid Arguments\n", __func__);
		return BC_STS_INV_ARG;
	}

	dev = &hw->adp->pdev->dev;

	sts = crystalhd_hw_create_ioqs(hw);
	if (sts != BC_STS_SUCCESS) {
		dev_err(dev, "Failed to create IOQs..\n");
		return sts;
	}

	mem_len = BC_LINK_MAX_SGLS * sizeof(struct dma_descriptor);

	for (i = 0; i < BC_TX_LIST_CNT; i++) {
		mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
		if (mem) {
			memset(mem, 0, mem_len);
		} else {
			dev_err(dev, "Insufficient Memory For TX\n");
			crystalhd_hw_free_dma_rings(hw);
			return BC_STS_INSUFF_RES;
		}
		/* rx_pkt_pool -- static memory allocation  */
		hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = mem;
		hw->tx_pkt_pool[i].desc_mem.phy_addr = phy_addr;
		hw->tx_pkt_pool[i].desc_mem.sz = BC_LINK_MAX_SGLS *
						 sizeof(struct dma_descriptor);
		hw->tx_pkt_pool[i].list_tag = 0;

		/* Add TX dma requests to Free Queue..*/
		sts = crystalhd_dioq_add(hw->tx_freeq,
				       &hw->tx_pkt_pool[i], false, 0);
		if (sts != BC_STS_SUCCESS) {
			crystalhd_hw_free_dma_rings(hw);
			return sts;
		}
	}

	for (i = 0; i < BC_RX_LIST_CNT; i++) {
		rpkt = kzalloc(sizeof(*rpkt), GFP_KERNEL);
		if (!rpkt) {
			dev_err(dev, "Insufficient Memory For RX\n");
			crystalhd_hw_free_dma_rings(hw);
			return BC_STS_INSUFF_RES;
		}

		mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
		if (mem) {
			memset(mem, 0, mem_len);
		} else {
			dev_err(dev, "Insufficient Memory For RX\n");
			crystalhd_hw_free_dma_rings(hw);
			return BC_STS_INSUFF_RES;
		}
		rpkt->desc_mem.pdma_desc_start = mem;
		rpkt->desc_mem.phy_addr = phy_addr;
		rpkt->desc_mem.sz  = BC_LINK_MAX_SGLS * sizeof(struct dma_descriptor);
		rpkt->pkt_tag = hw->rx_pkt_tag_seed + i;
		crystalhd_hw_free_rx_pkt(hw, rpkt);
	}

	return BC_STS_SUCCESS;
}
コード例 #3
0
ファイル: crystalhd_lnx.c プロジェクト: Ardakilic/crystalhd
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;
}