bam_txn_buf += sizeof(*bam_txn);
 
        bam_txn->bam_ce = bam_txn_buf;
-       bam_txn_buf +=
-               sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw;
+       bam_txn->bam_ce_nitems = QPIC_PER_CW_CMD_ELEMENTS * num_cw;
+       bam_txn_buf += sizeof(*bam_txn->bam_ce) * bam_txn->bam_ce_nitems;
 
        bam_txn->cmd_sgl = bam_txn_buf;
-       bam_txn_buf +=
-               sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw;
+       bam_txn->cmd_sgl_nitems = QPIC_PER_CW_CMD_SGL * num_cw;
+       bam_txn_buf += sizeof(*bam_txn->cmd_sgl) * bam_txn->cmd_sgl_nitems;
 
        bam_txn->data_sgl = bam_txn_buf;
+       bam_txn->data_sgl_nitems = QPIC_PER_CW_DATA_SGL * num_cw;
 
        init_completion(&bam_txn->txn_done);
 
        struct bam_transaction *bam_txn = nandc->bam_txn;
        u32 offset;
 
+       if (bam_txn->bam_ce_pos + size > bam_txn->bam_ce_nitems) {
+               dev_err(nandc->dev, "BAM %s array is full\n", "CE");
+               return -EINVAL;
+       }
+
        bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
 
        /* fill the command desc */
 
        /* use the separate sgl after this command */
        if (flags & NAND_BAM_NEXT_SGL) {
+               if (bam_txn->cmd_sgl_pos >= bam_txn->cmd_sgl_nitems) {
+                       dev_err(nandc->dev, "BAM %s array is full\n",
+                               "CMD sgl");
+                       return -EINVAL;
+               }
+
                bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
                bam_ce_size = (bam_txn->bam_ce_pos -
                                bam_txn->bam_ce_start) *
        struct bam_transaction *bam_txn = nandc->bam_txn;
 
        if (read) {
+               if (bam_txn->rx_sgl_pos >= bam_txn->data_sgl_nitems) {
+                       dev_err(nandc->dev, "BAM %s array is full\n", "RX sgl");
+                       return -EINVAL;
+               }
+
                sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos],
                           vaddr, size);
                bam_txn->rx_sgl_pos++;
        } else {
+               if (bam_txn->tx_sgl_pos >= bam_txn->data_sgl_nitems) {
+                       dev_err(nandc->dev, "BAM %s array is full\n", "TX sgl");
+                       return -EINVAL;
+               }
+
                sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos],
                           vaddr, size);
                bam_txn->tx_sgl_pos++;
 
  * @last_data_desc - last DMA desc in data channel (tx/rx).
  * @last_cmd_desc - last DMA desc in command channel.
  * @txn_done - completion for NAND transfer.
+ * @bam_ce_nitems - the number of elements in the @bam_ce array
+ * @cmd_sgl_nitems - the number of elements in the @cmd_sgl array
+ * @data_sgl_nitems - the number of elements in the @data_sgl array
  * @bam_ce_pos - the index in bam_ce which is available for next sgl
  * @bam_ce_start - the index in bam_ce which marks the start position ce
  *                for current sgl. It will be used for size calculation
        struct dma_async_tx_descriptor *last_data_desc;
        struct dma_async_tx_descriptor *last_cmd_desc;
        struct completion txn_done;
+
+       unsigned int bam_ce_nitems;
+       unsigned int cmd_sgl_nitems;
+       unsigned int data_sgl_nitems;
+
        struct_group(bam_positions,
                u32 bam_ce_pos;
                u32 bam_ce_start;