/* next channel to be assigned next incoming descriptor */
        atomic_t last_chan;
 
+       /* per-channel number of requests pending in channel h/w fifo */
+       atomic_t *submit_count;
+
        /* per-channel request fifo */
        struct talitos_request **fifo;
 
 
        spin_lock_irqsave(&priv->head_lock[ch], flags);
 
-       head = priv->head[ch];
-       request = &priv->fifo[ch][head];
-
-       if (request->desc) {
-               /* request queue is full */
+       if (!atomic_inc_not_zero(&priv->submit_count[ch])) {
+               /* h/w fifo is full */
                spin_unlock_irqrestore(&priv->head_lock[ch], flags);
                return -EAGAIN;
        }
 
+       head = priv->head[ch];
+       request = &priv->fifo[ch][head];
+
        /* map descriptor and save caller data */
        request->dma_desc = dma_map_single(dev, desc, sizeof(*desc),
                                           DMA_BIDIRECTIONAL);
                priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1);
 
                spin_unlock_irqrestore(&priv->tail_lock[ch], flags);
+
+               atomic_dec(&priv->submit_count[ch]);
+
                saved_req.callback(dev, saved_req.desc, saved_req.context,
                                   status);
                /* channel may resume processing in single desc error case */
        if (hw_supports(dev, DESC_HDR_SEL0_RNG))
                talitos_unregister_rng(dev);
 
+       kfree(priv->submit_count);
        kfree(priv->tail);
        kfree(priv->head);
 
                }
        }
 
+       priv->submit_count = kmalloc(sizeof(int) * priv->num_channels,
+                                    GFP_KERNEL);
+       if (!priv->submit_count) {
+               dev_err(dev, "failed to allocate fifo submit count space\n");
+               err = -ENOMEM;
+               goto err_out;
+       }
+       for (i = 0; i < priv->num_channels; i++)
+               atomic_set(&priv->submit_count[i], -priv->chfifo_len);
+
        priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
        priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
        if (!priv->head || !priv->tail) {