static void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { #ifdef CONFIG_MMC_DEBUG unsigned int i, sz; struct scatterlist *sg; #endif pr_debug("%s: starting CMD%u arg %08x flags %08x\n", mmc_hostname(host), mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); if (mrq->data) { pr_debug("%s: blksz %d blocks %d flags %08x " "tsac %d ms nsac %d\n", mmc_hostname(host), mrq->data->blksz, mrq->data->blocks, mrq->data->flags, mrq->data->timeout_ns / 1000000, mrq->data->timeout_clks); } if (mrq->stop) { pr_debug("%s: CMD%u arg %08x flags %08x\n", mmc_hostname(host), mrq->stop->opcode, mrq->stop->arg, mrq->stop->flags); } WARN_ON(!host->claimed); led_trigger_event(host->led, LED_FULL); mrq->cmd->error = 0; mrq->cmd->mrq = mrq; if (mrq->data) { BUG_ON(mrq->data->blksz > host->max_blk_size); BUG_ON(mrq->data->blocks > host->max_blk_count); BUG_ON(mrq->data->blocks * mrq->data->blksz > host->max_req_size); #ifdef CONFIG_MMC_DEBUG sz = 0; for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i) sz += sg->length; BUG_ON(sz != mrq->data->blocks * mrq->data->blksz); #endif mrq->cmd->data = mrq->data; mrq->data->error = 0; mrq->data->mrq = mrq; if (mrq->stop) { mrq->data->stop = mrq->stop; mrq->stop->error = 0; mrq->stop->mrq = mrq; } } host->ops->request(host, mrq); }
void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction dir, unsigned long attrs) { struct scatterlist *sg; int i; for_each_sg(sgl, sg, nents, i) dma_direct_unmap_page(dev, sg->dma_address, sg_dma_len(sg), dir, attrs); }
static void arc_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction dir) { int i; struct scatterlist *sg; for_each_sg(sglist, sg, nelems, i) _dma_cache_sync(sg_phys(sg), sg->length, dir); }
void dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction dir) { struct scatterlist *sg; int i; for_each_sg(sglist, sg, nents, i) dma_unmap_single(dev, sg_dma_address(sg), sg->length, dir); debug_dma_unmap_sg(dev, sglist, nents, dir); }
static int arc_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, unsigned long attrs) { struct scatterlist *s; int i; for_each_sg(sg, s, nents, i) s->dma_address = dma_map_page(dev, sg_page(s), s->offset, s->length, dir); return nents; }
static void iser_data_buf_dump(struct iser_data_buf *data, struct ib_device *ibdev) { struct scatterlist *sg; int i; for_each_sg(data->sg, sg, data->dma_nents, i) iser_dbg("sg[%d] dma_addr:0x%lX page:0x%p " "off:0x%x sz:0x%x dma_len:0x%x\n", i, (unsigned long)ib_sg_dma_address(ibdev, sg), sg_page(sg), sg->offset, sg->length, ib_sg_dma_len(ibdev, sg)); }
static char *isert_vmap_sg(struct page **pages, struct scatterlist *sgl, int n_ents) { unsigned int i; struct scatterlist *sg; void *vaddr; for_each_sg(sgl, sg, n_ents, i) pages[i] = sg_page(sg); vaddr = vmap(pages, n_ents, 0, PAGE_KERNEL); return vaddr; }
int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction dir) { struct scatterlist *sg; int i; for_each_sg(sglist, sg, nents, i) sg->dma_address = dma_map_single(dev, sg_virt(sg), sg->length, dir); debug_dma_map_sg(dev, sglist, nents, nents, dir); return nents; }
static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) { struct drm_i915_gem_object *obj = dma_buf->priv; struct drm_device *dev = obj->base.dev; struct scatterlist *sg; struct page **pages; int ret, i; ret = i915_mutex_lock_interruptible(dev); if (ret) return ERR_PTR(ret); if (obj->dma_buf_vmapping) { obj->vmapping_count++; goto out_unlock; } ret = i915_gem_object_get_pages(obj); if (ret) goto error; ret = -ENOMEM; pages = drm_malloc_ab(obj->pages->nents, sizeof(struct page *)); if (pages == NULL) goto error; for_each_sg(obj->pages->sgl, sg, obj->pages->nents, i) pages[i] = sg_page(sg); obj->dma_buf_vmapping = vmap(pages, obj->pages->nents, 0, PAGE_KERNEL); drm_free_large(pages); if (!obj->dma_buf_vmapping) goto error; obj->vmapping_count = 1; i915_gem_object_pin_pages(obj); out_unlock: mutex_unlock(&dev->struct_mutex); return obj->dma_buf_vmapping; error: mutex_unlock(&dev->struct_mutex); return ERR_PTR(ret); }
/** * sg_last - return the last scatterlist entry in a list * @sgl: First entry in the scatterlist * @nents: Number of entries in the scatterlist * * Description: * Should only be used casually, it (currently) scans the entire list * to get the last entry. * * Note that the @sgl@ pointer passed in need not be the first one, * the important bit is that @nents@ denotes the number of entries that * exist from @sgl@. * **/ struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) { #ifndef ARCH_HAS_SG_CHAIN struct scatterlist *ret = &sgl[nents - 1]; #else struct scatterlist *sg, *ret = NULL; unsigned int i; for_each_sg(sgl, sg, nents, i) ret = sg; #endif #ifdef CONFIG_DEBUG_SG BUG_ON(sgl[0].sg_magic != SG_MAGIC); BUG_ON(!sg_is_last(ret)); #endif return ret; }
static struct sg_table * tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction dir) { struct drm_gem_object *gem = attach->dmabuf->priv; struct tegra_bo *bo = to_tegra_bo(gem); struct sg_table *sgt; sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) return NULL; if (bo->pages) { struct scatterlist *sg; unsigned int i; if (sg_alloc_table(sgt, bo->num_pages, GFP_KERNEL)) goto free; for_each_sg(sgt->sgl, sg, bo->num_pages, i) sg_set_page(sg, bo->pages[i], PAGE_SIZE, 0); if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) goto free; } else { if (sg_alloc_table(sgt, 1, GFP_KERNEL)) goto free; sg_dma_address(sgt->sgl) = bo->paddr; sg_dma_len(sgt->sgl) = gem->size; } return sgt; free: sg_free_table(sgt); kfree(sgt); return NULL; }
/* * Prepare the sg list(s) to be handed of to the host driver */ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) { unsigned int sg_len; size_t buflen; struct scatterlist *sg; int i; if (!mqrq->bounce_buf) return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg); sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg); mqrq->bounce_sg_len = sg_len; buflen = 0; for_each_sg(mqrq->bounce_sg, sg, sg_len, i) buflen += sg->length; sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen); return 1; }
static int verify_lengths(struct scatterlist *sglist, int nents, int npages) { int sg_len, dma_len; int i, pgcount; struct scatterlist *sg; sg_len = 0; for_each_sg(sglist, sg, nents, i) sg_len += sg->length; dma_len = 0; for_each_sg(sglist, sg, nents, i) { if (!sg->dma_length) break; dma_len += sg->dma_length; } if (sg_len != dma_len) { printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", sg_len, dma_len); return -1; } pgcount = 0; for_each_sg(sglist, sg, nents, i) { unsigned long start, end; if (!sg->dma_length) break; start = sg->dma_address; start = start & IO_PAGE_MASK; end = sg->dma_address + sg->dma_length; end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; pgcount += ((end - start) >> IO_PAGE_SHIFT); }
void drm_clflush_sg(struct sg_table *st) { #if defined(CONFIG_X86) if (cpu_has_clflush) { struct scatterlist *sg; int i; mb(); for_each_sg(st->sgl, sg, st->nents, i) drm_clflush_page(sg_page(sg)); mb(); return; } if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) printk(KERN_ERR "Timed out waiting for cache flush.\n"); #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); WARN_ON_ONCE(1); #endif }
static int rockchip_gem_get_pages(struct rockchip_gem_object *rk_obj) { struct drm_device *drm = rk_obj->base.dev; int ret, i; struct scatterlist *s; rk_obj->pages = drm_gem_get_pages(&rk_obj->base); if (IS_ERR(rk_obj->pages)) return PTR_ERR(rk_obj->pages); rk_obj->num_pages = rk_obj->base.size >> PAGE_SHIFT; rk_obj->sgt = drm_prime_pages_to_sg(rk_obj->pages, rk_obj->num_pages); if (IS_ERR(rk_obj->sgt)) { ret = PTR_ERR(rk_obj->sgt); goto err_put_pages; } /* * Fake up the SG table so that dma_sync_sg_for_device() can be used * to flush the pages associated with it. * * TODO: Replace this by drm_clflush_sg() once it can be implemented * without relying on symbols that are not exported. */ for_each_sg(rk_obj->sgt->sgl, s, rk_obj->sgt->nents, i) sg_dma_address(s) = sg_phys(s); dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents, DMA_TO_DEVICE); return 0; err_put_pages: drm_gem_put_pages(&rk_obj->base, rk_obj->pages, false, false); return ret; }
dma_addr_t ispmmu_vmap(const struct scatterlist *sglist, int sglen) { int err; void *da; struct sg_table *sgt; unsigned int i; struct scatterlist *sg, *src = (struct scatterlist *)sglist; /* * convert isp sglist to iommu sgt * FIXME: should be fixed in the upper layer? */ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) return -ENOMEM; err = sg_alloc_table(sgt, sglen, GFP_KERNEL); if (err) goto err_sg_alloc; for_each_sg(sgt->sgl, sg, sgt->nents, i) sg_set_buf(sg, phys_to_virt(sg_dma_address(src + i)), sg_dma_len(src + i)); da = (void *)iommu_vmap(isp_iommu, 0, sgt, IOMMU_FLAG); if (IS_ERR(da)) goto err_vmap; return (dma_addr_t)da; err_vmap: sg_free_table(sgt); err_sg_alloc: kfree(sgt); return -ENOMEM; }
/* * Prepare the sg list(s) to be handed of to the host driver */ static unsigned int card_queue_map_sg(struct card_queue *cq) { unsigned int sg_len; size_t buflen; struct scatterlist *sg; int i; if (!cq->bounce_buf) return blk_rq_map_sg(cq->queue, cq->req, cq->sg); BUG_ON(!cq->bounce_sg); sg_len = blk_rq_map_sg(cq->queue, cq->req, cq->bounce_sg); cq->bounce_sg_len = sg_len; buflen = 0; for_each_sg(cq->bounce_sg, sg, sg_len, i) buflen += sg->length; sg_init_one(cq->sg, cq->bounce_buf, buflen); return 1; }
/* * Dump cmd state for debugging. */ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) { struct fc_exch *ep; struct fc_seq *sp; struct se_cmd *se_cmd; struct scatterlist *sg; int count; se_cmd = &cmd->se_cmd; pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n", caller, cmd, cmd->sess, cmd->seq, se_cmd); pr_debug("%s: cmd %p cdb %p\n", caller, cmd, cmd->cdb); pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun); pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n", caller, cmd, se_cmd->t_data_nents, se_cmd->data_length, se_cmd->se_cmd_flags); for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count) pr_debug("%s: cmd %p sg %p page %p " "len 0x%x off 0x%x\n", caller, cmd, sg, sg_page(sg), sg->length, sg->offset); sp = cmd->seq; if (sp) { ep = fc_seq_exch(sp); pr_debug("%s: cmd %p sid %x did %x " "ox_id %x rx_id %x seq_id %x e_stat %x\n", caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid, sp->id, ep->esb_stat); } print_hex_dump(KERN_INFO, "ft_dump_cmd ", DUMP_PREFIX_NONE, 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0); }
static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) { int res; struct sas_task *task; struct domain_device *dev = qc->ap->private_data; struct sas_ha_struct *sas_ha = dev->port->ha; struct Scsi_Host *host = sas_ha->core.shost; struct sas_internal *i = to_sas_internal(host->transportt); struct scatterlist *sg; unsigned int xfer = 0; unsigned int si; /* If the device fell off, no sense in issuing commands */ if (dev->gone) return AC_ERR_SYSTEM; task = sas_alloc_task(GFP_ATOMIC); if (!task) return AC_ERR_SYSTEM; task->dev = dev; task->task_proto = SAS_PROTOCOL_STP; task->task_done = sas_ata_task_done; if (qc->tf.command == ATA_CMD_FPDMA_WRITE || qc->tf.command == ATA_CMD_FPDMA_READ) { /* Need to zero out the tag libata assigned us */ qc->tf.nsect = 0; } ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); task->uldd_task = qc; if (ata_is_atapi(qc->tf.protocol)) { memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); task->total_xfer_len = qc->nbytes; task->num_scatter = qc->n_elem; } else { for_each_sg(qc->sg, sg, qc->n_elem, si) xfer += sg->length; task->total_xfer_len = xfer; task->num_scatter = si; } task->data_dir = qc->dma_dir; task->scatter = qc->sg; task->ata_task.retry_count = 1; task->task_state_flags = SAS_TASK_STATE_PENDING; qc->lldd_task = task; switch (qc->tf.protocol) { case ATA_PROT_NCQ: task->ata_task.use_ncq = 1; /* fall through */ case ATAPI_PROT_DMA: case ATA_PROT_DMA: task->ata_task.dma_xfer = 1; break; } if (qc->scsicmd) ASSIGN_SAS_TASK(qc->scsicmd, task); if (sas_ha->lldd_max_execute_num < 2) res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); else res = sas_queue_up(task); /* Examine */ if (res) { SAS_DPRINTK("lldd_execute_task returned: %d\n", res); if (qc->scsicmd) ASSIGN_SAS_TASK(qc->scsicmd, NULL); sas_free_task(task); return AC_ERR_SYSTEM; } return 0; }
static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd, int cmd_len, int data_direction, void *buffer, unsigned bufflen, int use_sg, int timeout, int retries) { struct request *req; struct page **pages = NULL; struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; int err = 0; int write = (data_direction == DMA_TO_DEVICE); req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL); if (!req) return DRIVER_ERROR << 24; req->cmd_type = REQ_TYPE_BLOCK_PC; req->cmd_flags |= REQ_QUIET; SRpnt->bio = NULL; if (use_sg) { struct scatterlist *sg, *sgl = (struct scatterlist *)buffer; int i; pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL); if (!pages) goto free_req; for_each_sg(sgl, sg, use_sg, i) pages[i] = sg_page(sg); mdata->null_mapped = 1; mdata->page_order = get_order(sgl[0].length); mdata->nr_entries = DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order); mdata->offset = 0; err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL); if (err) { kfree(pages); goto free_req; } SRpnt->bio = req->bio; mdata->pages = pages; } else if (bufflen) { err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL); if (err) goto free_req; } req->cmd_len = cmd_len; memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ memcpy(req->cmd, cmd, req->cmd_len); req->sense = SRpnt->sense; req->sense_len = 0; req->timeout = timeout; req->retries = retries; req->end_io_data = SRpnt; blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async); return 0; free_req: blk_put_request(req); return DRIVER_ERROR << 24; }
static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) { unsigned long flags; struct sas_task *task; struct scatterlist *sg; int ret = AC_ERR_SYSTEM; unsigned int si, xfer = 0; struct ata_port *ap = qc->ap; struct domain_device *dev = ap->private_data; struct sas_ha_struct *sas_ha = dev->port->ha; struct Scsi_Host *host = sas_ha->core.shost; struct sas_internal *i = to_sas_internal(host->transportt); /* TODO: audit callers to ensure they are ready for qc_issue to * unconditionally re-enable interrupts */ local_irq_save(flags); spin_unlock(ap->lock); /* If the device fell off, no sense in issuing commands */ if (test_bit(SAS_DEV_GONE, &dev->state)) goto out; task = sas_alloc_task(GFP_ATOMIC); if (!task) goto out; task->dev = dev; task->task_proto = SAS_PROTOCOL_STP; task->task_done = sas_ata_task_done; if (qc->tf.command == ATA_CMD_FPDMA_WRITE || qc->tf.command == ATA_CMD_FPDMA_READ) { /* Need to zero out the tag libata assigned us */ qc->tf.nsect = 0; } ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis); task->uldd_task = qc; if (ata_is_atapi(qc->tf.protocol)) { memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); task->total_xfer_len = qc->nbytes; task->num_scatter = qc->n_elem; } else { for_each_sg(qc->sg, sg, qc->n_elem, si) xfer += sg->length; task->total_xfer_len = xfer; task->num_scatter = si; } task->data_dir = qc->dma_dir; task->scatter = qc->sg; task->ata_task.retry_count = 1; task->task_state_flags = SAS_TASK_STATE_PENDING; qc->lldd_task = task; switch (qc->tf.protocol) { case ATA_PROT_NCQ: task->ata_task.use_ncq = 1; /* fall through */ case ATAPI_PROT_DMA: case ATA_PROT_DMA: task->ata_task.dma_xfer = 1; break; } if (qc->scsicmd) ASSIGN_SAS_TASK(qc->scsicmd, task); if (sas_ha->lldd_max_execute_num < 2) ret = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); else ret = sas_queue_up(task); /* Examine */ if (ret) { SAS_DPRINTK("lldd_execute_task returned: %d\n", ret); if (qc->scsicmd) ASSIGN_SAS_TASK(qc->scsicmd, NULL); sas_free_task(task); ret = AC_ERR_SYSTEM; } out: spin_lock(ap->lock); local_irq_restore(flags); return ret; }
static void mxs_mmc_adtc(struct mxs_mmc_host *host) { struct mmc_command *cmd = host->cmd; struct mmc_data *data = cmd->data; struct dma_async_tx_descriptor *desc; struct scatterlist *sgl = data->sg, *sg; unsigned int sg_len = data->sg_len; unsigned int i; unsigned short dma_data_dir, timeout; enum dma_transfer_direction slave_dirn; unsigned int data_size = 0, log2_blksz; unsigned int blocks = data->blocks; struct mxs_ssp *ssp = &host->ssp; u32 ignore_crc, get_resp, long_resp, read; u32 ctrl0, cmd0, cmd1, val; ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ? 0 : BM_SSP_CTRL0_IGNORE_CRC; get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ? BM_SSP_CTRL0_GET_RESP : 0; long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ? BM_SSP_CTRL0_LONG_RESP : 0; if (data->flags & MMC_DATA_WRITE) { dma_data_dir = DMA_TO_DEVICE; slave_dirn = DMA_MEM_TO_DEV; read = 0; } else { dma_data_dir = DMA_FROM_DEVICE; slave_dirn = DMA_DEV_TO_MEM; read = BM_SSP_CTRL0_READ; } ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) | ignore_crc | get_resp | long_resp | BM_SSP_CTRL0_DATA_XFER | read | BM_SSP_CTRL0_WAIT_FOR_IRQ | BM_SSP_CTRL0_ENABLE; cmd0 = BF_SSP(cmd->opcode, CMD0_CMD); /* get logarithm to base 2 of block size for setting register */ log2_blksz = ilog2(data->blksz); /* * take special care of the case that data size from data->sg * is not equal to blocks x blksz */ for_each_sg(sgl, sg, sg_len, i) data_size += sg->length; if (data_size != data->blocks * data->blksz) blocks = 1; /* xfer count, block size and count need to be set differently */ if (ssp_is_old(ssp)) { ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT); cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) | BF_SSP(blocks - 1, CMD0_BLOCK_COUNT); } else { writel(data_size, ssp->base + HW_SSP_XFER_SIZE); writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) | BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT), ssp->base + HW_SSP_BLOCK_SIZE); } if ((cmd->opcode == MMC_STOP_TRANSMISSION) || (cmd->opcode == SD_IO_RW_EXTENDED)) cmd0 |= BM_SSP_CMD0_APPEND_8CYC; cmd1 = cmd->arg; if (host->sdio_irq_en) { ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN; } /* set the timeout count */ timeout = mxs_ns_to_ssp_ticks(ssp->clk_rate, data->timeout_ns); val = readl(ssp->base + HW_SSP_TIMING(ssp)); val &= ~(BM_SSP_TIMING_TIMEOUT); val |= BF_SSP(timeout, TIMING_TIMEOUT); writel(val, ssp->base + HW_SSP_TIMING(ssp)); /* pio */ ssp->ssp_pio_words[0] = ctrl0; ssp->ssp_pio_words[1] = cmd0; ssp->ssp_pio_words[2] = cmd1; ssp->dma_dir = DMA_NONE; ssp->slave_dirn = DMA_TRANS_NONE; desc = mxs_mmc_prep_dma(host, 0); if (!desc) goto out; /* append data sg */ WARN_ON(host->data != NULL); host->data = data; ssp->dma_dir = dma_data_dir; ssp->slave_dirn = slave_dirn; desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) goto out; dmaengine_submit(desc); dma_async_issue_pending(ssp->dmach); return; out: dev_warn(mmc_dev(host->mmc), "%s: failed to prep dma\n", __func__); }