.. | .. |
---|
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: |
---|