int solo_p2m_dma_t(struct solo6010_dev *solo_dev, u8 id, int wr, dma_addr_t dma_addr, u32 ext_addr, u32 size) { struct solo_p2m_dev *p2m_dev; unsigned int timeout = 0; WARN_ON(!size); WARN_ON(id >= SOLO_NR_P2M); if (!size || id >= SOLO_NR_P2M) return -EINVAL; p2m_dev = &solo_dev->p2m_dev[id]; down(&p2m_dev->sem); start_dma: INIT_COMPLETION(p2m_dev->completion); p2m_dev->error = 0; solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), dma_addr); solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), ext_addr); solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), SOLO_P2M_COPY_SIZE(size >> 2)); solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) | (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON); timeout = wait_for_completion_timeout(&p2m_dev->completion, HZ); solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0); /* XXX Really looks to me like we will get stuck here if a * real PCI P2M error occurs */ if (p2m_dev->error) goto start_dma; up(&p2m_dev->sem); return (timeout == 0) ? -EAGAIN : 0; }
if (WARN_ON_ONCE(p2m_dev->error)) ret = -EIO; else if (timeout == 0) ret = -EAGAIN; mutex_unlock(&p2m_dev->mutex); return ret; } void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr, dma_addr_t dma_addr, u32 ext_addr, u32 size, int repeat, u32 ext_size) { desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2); desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) | (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON; if (repeat) { desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2); desc->ctrl |= SOLO_P2M_PCI_INC(size >> 2) | SOLO_P2M_REPEAT(repeat); } desc->dma_addr = dma_addr; desc->ext_addr = ext_addr; } int solo_p2m_dma_t(struct solo6010_dev *solo_dev, int wr, dma_addr_t dma_addr, u32 ext_addr, u32 size, int repeat, u32 ext_size)