Ejemplo n.º 1
0
/* Mutex must be held for p2m_id before calling this!! */
int solo_p2m_dma_desc(struct solo6010_dev *solo_dev,
		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
		      int desc_cnt)
{
	struct solo_p2m_dev *p2m_dev;
	unsigned int timeout = 0;
	unsigned int config = 0;
	int ret = 0;
        int p2m_id;

	/* Get next ID */
	p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
	if (p2m_id < 0)
		p2m_id = 0 - p2m_id;

	p2m_dev = &solo_dev->p2m_dev[p2m_id];

	if (mutex_lock_interruptible(&p2m_dev->mutex))
		return -EINTR;

	INIT_COMPLETION(p2m_dev->completion);
	p2m_dev->error = 0;

	if (desc_cnt > 1) {
		/* We only need to do this when we have more than one
		 * descriptor. */
		config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id));

		solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma);
		solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt);
		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config |
			       SOLO_P2M_DESC_MODE);
	} else {
		solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id), desc[1].dma_addr);
		solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id), desc[1].ext_addr);
		solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id), desc[1].cfg);
		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), desc[1].ctrl);
	}

	timeout = wait_for_completion_timeout(&p2m_dev->completion,
					      msecs_to_jiffies(solo_dev->p2m_msecs));

	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0);

	if (desc_cnt > 1)
		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config);

	if (WARN_ON_ONCE(p2m_dev->error))
		ret = -EIO;
	else if (timeout == 0)
		ret = -EAGAIN;

	mutex_unlock(&p2m_dev->mutex);

	return ret;
}
Ejemplo n.º 2
0
int solo_p2m_init(struct solo6010_dev *solo_dev)
{
    struct solo_p2m_dev *p2m_dev;
    int i;

    for (i = 0; i < SOLO_NR_P2M; i++) {
        p2m_dev = &solo_dev->p2m_dev[i];

        sema_init(&p2m_dev->sem, 1);
        init_completion(&p2m_dev->completion);

        solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(i),
                       __pa(p2m_dev->desc));

        solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
        solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
                       SOLO_P2M_CSC_16BIT_565 |
                       SOLO_P2M_DMA_INTERVAL(0) |
                       SOLO_P2M_PCI_MASTER_MODE);
        solo6010_irq_on(solo_dev, SOLO_IRQ_P2M(i));
    }

    run_p2m_test(solo_dev);

    return 0;
}