Merge tag 'master-2014-08-14' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil...
[cascardo/linux.git] / drivers / dma / pl330.c
index b31c6c3..d5149aa 100644 (file)
@@ -245,9 +245,6 @@ enum pl330_byteswap {
  */
 #define MCODE_BUFF_PER_REQ     256
 
-/* If the _pl330_req is available to the client */
-#define IS_FREE(req)   (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
-
 /* Use this _only_ to wait on transient states */
 #define UNTIL(t, s)    while (!(_state(t) & (s))) cpu_relax();
 
@@ -332,15 +329,6 @@ enum pl330_op_err {
        PL330_ERR_FAIL,
 };
 
-enum pl330_chan_op {
-       /* Start the channel */
-       PL330_OP_START,
-       /* Abort the active xfer */
-       PL330_OP_ABORT,
-       /* Stop xfer and flush queue */
-       PL330_OP_FLUSH,
-};
-
 enum dmamov_dst {
        SAR = 0,
        CCR,
@@ -529,14 +517,12 @@ struct _xfer_spec {
 
 static inline bool _queue_empty(struct pl330_thread *thrd)
 {
-       return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
-               ? true : false;
+       return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL;
 }
 
 static inline bool _queue_full(struct pl330_thread *thrd)
 {
-       return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
-               ? false : true;
+       return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL;
 }
 
 static inline bool is_manager(struct pl330_thread *thrd)
@@ -948,21 +934,6 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
        writel(0, regs + DBGCMD);
 }
 
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-static void mark_free(struct pl330_thread *thrd, int idx)
-{
-       struct _pl330_req *req = &thrd->req[idx];
-
-       _emit_END(0, req->mc_cpu);
-
-       thrd->req_running = -1;
-}
-
 static inline u32 _state(struct pl330_thread *thrd)
 {
        void __iomem *regs = thrd->dmac->base;
@@ -1059,18 +1030,18 @@ static bool _trigger(struct pl330_thread *thrd)
                return true;
 
        idx = 1 - thrd->lstenq;
-       if (!IS_FREE(&thrd->req[idx]))
+       if (thrd->req[idx].desc != NULL) {
                req = &thrd->req[idx];
-       else {
+       else {
                idx = thrd->lstenq;
-               if (!IS_FREE(&thrd->req[idx]))
+               if (thrd->req[idx].desc != NULL)
                        req = &thrd->req[idx];
                else
                        req = NULL;
        }
 
        /* Return if no request */
-       if (!req || !req->desc)
+       if (!req)
                return true;
 
        desc = req->desc;
@@ -1438,7 +1409,7 @@ static int pl330_submit_req(struct pl330_thread *thrd,
 
        ccr = _prepare_ccr(&desc->rqcfg);
 
-       idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
+       idx = thrd->req[0].desc == NULL ? 0 : 1;
 
        xs.ccr = ccr;
        xs.desc = desc;
@@ -1470,9 +1441,14 @@ xfer_exit:
 
 static void dma_pl330_rqcb(struct dma_pl330_desc *desc, enum pl330_op_err err)
 {
-       struct dma_pl330_chan *pch = desc->pchan;
+       struct dma_pl330_chan *pch;
        unsigned long flags;
 
+       if (!desc)
+               return;
+
+       pch = desc->pchan;
+
        /* If desc aborted */
        if (!pch)
                return;
@@ -1532,8 +1508,7 @@ static void pl330_dotask(unsigned long data)
 
                        thrd->req[0].desc = NULL;
                        thrd->req[1].desc = NULL;
-                       mark_free(thrd, 0);
-                       mark_free(thrd, 1);
+                       thrd->req_running = -1;
 
                        /* Clear the reset flag */
                        pl330->dmac_tbd.reset_chan &= ~(1 << i);
@@ -1615,8 +1590,6 @@ static int pl330_update(struct pl330_dmac *pl330)
                        descdone = thrd->req[active].desc;
                        thrd->req[active].desc = NULL;
 
-                       mark_free(thrd, active);
-
                        /* Get going again ASAP */
                        _start(thrd);
 
@@ -1646,56 +1619,6 @@ updt_exit:
        return ret;
 }
 
-static int pl330_chan_ctrl(struct pl330_thread *thrd, enum pl330_chan_op op)
-{
-       struct pl330_dmac *pl330;
-       unsigned long flags;
-       int ret = 0, active;
-
-       if (!thrd || thrd->free || thrd->dmac->state == DYING)
-               return -EINVAL;
-
-       pl330 = thrd->dmac;
-       active = thrd->req_running;
-
-       spin_lock_irqsave(&pl330->lock, flags);
-
-       switch (op) {
-       case PL330_OP_FLUSH:
-               /* Make sure the channel is stopped */
-               _stop(thrd);
-
-               thrd->req[0].desc = NULL;
-               thrd->req[1].desc = NULL;
-               mark_free(thrd, 0);
-               mark_free(thrd, 1);
-               break;
-
-       case PL330_OP_ABORT:
-               /* Make sure the channel is stopped */
-               _stop(thrd);
-
-               /* ABORT is only for the active req */
-               if (active == -1)
-                       break;
-
-               thrd->req[active].desc = NULL;
-               mark_free(thrd, active);
-
-               /* Start the next */
-       case PL330_OP_START:
-               if ((active == -1) && !_start(thrd))
-                       ret = -EIO;
-               break;
-
-       default:
-               ret = -EINVAL;
-       }
-
-       spin_unlock_irqrestore(&pl330->lock, flags);
-       return ret;
-}
-
 /* Reserve an event */
 static inline int _alloc_event(struct pl330_thread *thrd)
 {
@@ -1741,9 +1664,8 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
                                thrd->free = false;
                                thrd->lstenq = 1;
                                thrd->req[0].desc = NULL;
-                               mark_free(thrd, 0);
                                thrd->req[1].desc = NULL;
-                               mark_free(thrd, 1);
+                               thrd->req_running = -1;
                                break;
                        }
                }
@@ -1841,14 +1763,14 @@ static inline void _reset_thread(struct pl330_thread *thrd)
        thrd->req[0].mc_bus = pl330->mcode_bus
                                + (thrd->id * pl330->mcbufsz);
        thrd->req[0].desc = NULL;
-       mark_free(thrd, 0);
 
        thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
                                + pl330->mcbufsz / 2;
        thrd->req[1].mc_bus = thrd->req[0].mc_bus
                                + pl330->mcbufsz / 2;
        thrd->req[1].desc = NULL;
-       mark_free(thrd, 1);
+
+       thrd->req_running = -1;
 }
 
 static int dmac_alloc_threads(struct pl330_dmac *pl330)
@@ -2058,7 +1980,9 @@ static void pl330_tasklet(unsigned long data)
        fill_queue(pch);
 
        /* Make sure the PL330 Channel thread is active */
-       pl330_chan_ctrl(pch->thread, PL330_OP_START);
+       spin_lock(&pch->thread->dmac->lock);
+       _start(pch->thread);
+       spin_unlock(&pch->thread->dmac->lock);
 
        while (!list_empty(&pch->completed_list)) {
                dma_async_tx_callback callback;
@@ -2158,8 +2082,13 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
        case DMA_TERMINATE_ALL:
                spin_lock_irqsave(&pch->lock, flags);
 
-               /* FLUSH the PL330 Channel thread */
-               pl330_chan_ctrl(pch->thread, PL330_OP_FLUSH);
+               spin_lock(&pl330->lock);
+               _stop(pch->thread);
+               spin_unlock(&pl330->lock);
+
+               pch->thread->req[0].desc = NULL;
+               pch->thread->req[1].desc = NULL;
+               pch->thread->req_running = -1;
 
                /* Mark all desc done */
                list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2433,7 +2362,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
                size_t period_len, enum dma_transfer_direction direction,
-               unsigned long flags, void *context)
+               unsigned long flags)
 {
        struct dma_pl330_desc *desc = NULL, *first = NULL;
        struct dma_pl330_chan *pch = to_pchan(chan);