| .. | .. |
|---|
| 166 | 166 | dw_edma_free_desc(vd2dw_edma_desc(vdesc)); |
|---|
| 167 | 167 | } |
|---|
| 168 | 168 | |
|---|
| 169 | | -static void dw_edma_start_transfer(struct dw_edma_chan *chan) |
|---|
| 169 | +static int dw_edma_start_transfer(struct dw_edma_chan *chan) |
|---|
| 170 | 170 | { |
|---|
| 171 | 171 | struct dw_edma_chunk *child; |
|---|
| 172 | 172 | struct dw_edma_desc *desc; |
|---|
| .. | .. |
|---|
| 174 | 174 | |
|---|
| 175 | 175 | vd = vchan_next_desc(&chan->vc); |
|---|
| 176 | 176 | if (!vd) |
|---|
| 177 | | - return; |
|---|
| 177 | + return 0; |
|---|
| 178 | 178 | |
|---|
| 179 | 179 | desc = vd2dw_edma_desc(vd); |
|---|
| 180 | 180 | if (!desc) |
|---|
| 181 | | - return; |
|---|
| 181 | + return 0; |
|---|
| 182 | 182 | |
|---|
| 183 | 183 | child = list_first_entry_or_null(&desc->chunk->list, |
|---|
| 184 | 184 | struct dw_edma_chunk, list); |
|---|
| 185 | 185 | if (!child) |
|---|
| 186 | | - return; |
|---|
| 186 | + return 0; |
|---|
| 187 | 187 | |
|---|
| 188 | 188 | dw_edma_v0_core_start(child, !desc->xfer_sz); |
|---|
| 189 | 189 | desc->xfer_sz += child->ll_region.sz; |
|---|
| .. | .. |
|---|
| 191 | 191 | list_del(&child->list); |
|---|
| 192 | 192 | kfree(child); |
|---|
| 193 | 193 | desc->chunks_alloc--; |
|---|
| 194 | + |
|---|
| 195 | + return 1; |
|---|
| 194 | 196 | } |
|---|
| 195 | 197 | |
|---|
| 196 | 198 | static int dw_edma_device_config(struct dma_chan *dchan, |
|---|
| .. | .. |
|---|
| 274 | 276 | struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); |
|---|
| 275 | 277 | unsigned long flags; |
|---|
| 276 | 278 | |
|---|
| 279 | + if (!chan->configured) |
|---|
| 280 | + return; |
|---|
| 281 | + |
|---|
| 277 | 282 | spin_lock_irqsave(&chan->vc.lock, flags); |
|---|
| 278 | | - if (chan->configured && chan->request == EDMA_REQ_NONE && |
|---|
| 279 | | - chan->status == EDMA_ST_IDLE && vchan_issue_pending(&chan->vc)) { |
|---|
| 283 | + if (vchan_issue_pending(&chan->vc) && chan->request == EDMA_REQ_NONE && |
|---|
| 284 | + chan->status == EDMA_ST_IDLE) { |
|---|
| 280 | 285 | chan->status = EDMA_ST_BUSY; |
|---|
| 281 | 286 | dw_edma_start_transfer(chan); |
|---|
| 282 | 287 | } |
|---|
| .. | .. |
|---|
| 497 | 502 | switch (chan->request) { |
|---|
| 498 | 503 | case EDMA_REQ_NONE: |
|---|
| 499 | 504 | desc = vd2dw_edma_desc(vd); |
|---|
| 500 | | - if (desc->chunks_alloc) { |
|---|
| 501 | | - chan->status = EDMA_ST_BUSY; |
|---|
| 502 | | - dw_edma_start_transfer(chan); |
|---|
| 503 | | - } else { |
|---|
| 505 | + if (!desc->chunks_alloc) { |
|---|
| 504 | 506 | list_del(&vd->node); |
|---|
| 505 | 507 | vchan_cookie_complete(vd); |
|---|
| 506 | | - chan->status = EDMA_ST_IDLE; |
|---|
| 507 | 508 | } |
|---|
| 509 | + |
|---|
| 510 | + /* Continue transferring if there are remaining chunks or issued requests. |
|---|
| 511 | + */ |
|---|
| 512 | + chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE; |
|---|
| 508 | 513 | break; |
|---|
| 509 | 514 | |
|---|
| 510 | 515 | case EDMA_REQ_STOP: |
|---|