staging: most: allocate only all requested memory
authorChristian Gromm <christian.gromm@microchip.com>
Tue, 8 May 2018 09:44:49 +0000 (11:44 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 8 May 2018 11:41:48 +0000 (13:41 +0200)
This prohibits the allocation of the memory for the MBOs if only the
part of the MBOs, requested by the application, may be allocated.  The
function arm_mbo_chain, if cannot allocate all requested MBO, frees all
prior allocated memory and returns 0.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/most/core.c

index 8f28335..965409e 100644 (file)
@@ -952,18 +952,17 @@ static int arm_mbo_chain(struct most_channel *c, int dir,
                         void (*compl)(struct mbo *))
 {
        unsigned int i;
-       int retval;
        struct mbo *mbo;
+       unsigned long flags;
        u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
 
        atomic_set(&c->mbo_nq_level, 0);
 
        for (i = 0; i < c->cfg.num_buffers; i++) {
                mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
-               if (!mbo) {
-                       retval = i;
-                       goto _exit;
-               }
+               if (!mbo)
+                       goto flush_fifos;
+
                mbo->context = c;
                mbo->ifp = c->iface;
                mbo->hdm_channel_id = c->channel_id;
@@ -971,26 +970,28 @@ static int arm_mbo_chain(struct most_channel *c, int dir,
                                                       coherent_buf_size,
                                                       &mbo->bus_address,
                                                       GFP_KERNEL);
-               if (!mbo->virt_address) {
-                       pr_info("WARN: No DMA coherent buffer.\n");
-                       retval = i;
-                       goto _error1;
-               }
+               if (!mbo->virt_address)
+                       goto release_mbo;
+
                mbo->complete = compl;
                mbo->num_buffers_ptr = &dummy_num_buffers;
                if (dir == MOST_CH_RX) {
                        nq_hdm_mbo(mbo);
                        atomic_inc(&c->mbo_nq_level);
                } else {
-                       arm_mbo(mbo);
+                       spin_lock_irqsave(&c->fifo_lock, flags);
+                       list_add_tail(&mbo->list, &c->fifo);
+                       spin_unlock_irqrestore(&c->fifo_lock, flags);
                }
        }
-       return i;
+       return c->cfg.num_buffers;
 
-_error1:
+release_mbo:
        kfree(mbo);
-_exit:
-       return retval;
+
+flush_fifos:
+       flush_channel_fifos(c);
+       return 0;
 }
 
 /**