dma: at_xdmac: fix a missing check on list iterator
authorXiaomeng Tong <xiam0nd.tong@gmail.com>
Sun, 27 Mar 2022 06:11:54 +0000 (14:11 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 27 Apr 2022 12:38:58 +0000 (14:38 +0200)
commit 206680c4e46b62fd8909385e0874a36952595b85 upstream.

The bug is here:
__func__, desc, &desc->tx_dma_desc.phys, ret, cookie, residue);

The list iterator 'desc' will point to a bogus position containing
HEAD if the list is empty or no element is found. To avoid dev_dbg()
prints a invalid address, use a new variable 'iter' as the list
iterator, while use the origin variable 'desc' as a dedicated
pointer to point to the found element.

Cc: stable@vger.kernel.org
Fixes: 82e2424635f4c ("dmaengine: xdmac: fix print warning on dma_addr_t variable")
Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com>
Link: https://lore.kernel.org/r/20220327061154.4867-1-xiam0nd.tong@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/dma/at_xdmac.c

index 8177aed..177a537 100644 (file)
@@ -1450,7 +1450,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 {
        struct at_xdmac_chan    *atchan = to_at_xdmac_chan(chan);
        struct at_xdmac         *atxdmac = to_at_xdmac(atchan->chan.device);
-       struct at_xdmac_desc    *desc, *_desc;
+       struct at_xdmac_desc    *desc, *_desc, *iter;
        struct list_head        *descs_list;
        enum dma_status         ret;
        int                     residue, retry;
@@ -1565,11 +1565,13 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
         * microblock.
         */
        descs_list = &desc->descs_list;
-       list_for_each_entry_safe(desc, _desc, descs_list, desc_node) {
-               dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
-               residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth;
-               if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
+       list_for_each_entry_safe(iter, _desc, descs_list, desc_node) {
+               dwidth = at_xdmac_get_dwidth(iter->lld.mbr_cfg);
+               residue -= (iter->lld.mbr_ubc & 0xffffff) << dwidth;
+               if ((iter->lld.mbr_nda & 0xfffffffc) == cur_nda) {
+                       desc = iter;
                        break;
+               }
        }
        residue += cur_ubc << dwidth;