[bug report] spi: tegra210-quad: Fix combined sequence

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Krishna Yarlagadda,

The patch 8777dd9dff40: "spi: tegra210-quad: Fix combined sequence"
from Oct 1, 2022, leads to the following Smatch static checker
warning:

	drivers/spi/spi-tegra210-quad.c:1160 tegra_qspi_combined_seq_xfer()
	warn: iterator used outside loop: 'xfer'

drivers/spi/spi-tegra210-quad.c
    1046 static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
    1047                                         struct spi_message *msg)
    1048 {
    1049         bool is_first_msg = true;
    1050         struct spi_transfer *xfer;
    1051         struct spi_device *spi = msg->spi;
    1052         u8 transfer_phase = 0;
    1053         u32 cmd1 = 0, dma_ctl = 0;
    1054         int ret = 0;
    1055         u32 address_value = 0;
    1056         u32 cmd_config = 0, addr_config = 0;
    1057         u8 cmd_value = 0, val = 0;
    1058 
    1059         /* Enable Combined sequence mode */
    1060         val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG);
    1061         val |= QSPI_CMB_SEQ_EN;
    1062         tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG);
    1063         /* Process individual transfer list */
    1064         list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                                     ^^^^
"xfer" is the list iterator.  If we exit the loop because the list is
complete (as opposed to exiting the loop because we hit a break), then
the "xfer" pointer does not pointe to valid memory.

    1065                 switch (transfer_phase) {
    1066                 case CMD_TRANSFER:
    1067                         /* X1 SDR mode */
    1068                         cmd_config = tegra_qspi_cmd_config(false, 0,
    1069                                                            xfer->len);
    1070                         cmd_value = *((const u8 *)(xfer->tx_buf));
    1071                         break;
    1072                 case ADDR_TRANSFER:
    1073                         /* X1 SDR mode */
    1074                         addr_config = tegra_qspi_addr_config(false, 0,
    1075                                                              xfer->len);
    1076                         address_value = *((const u32 *)(xfer->tx_buf));
    1077                         break;
    1078                 case DATA_TRANSFER:
    1079                         /* Program Command, Address value in register */
    1080                         tegra_qspi_writel(tqspi, cmd_value, QSPI_CMB_SEQ_CMD);
    1081                         tegra_qspi_writel(tqspi, address_value,
    1082                                           QSPI_CMB_SEQ_ADDR);
    1083                         /* Program Command and Address config in register */
    1084                         tegra_qspi_writel(tqspi, cmd_config,
    1085                                           QSPI_CMB_SEQ_CMD_CFG);
    1086                         tegra_qspi_writel(tqspi, addr_config,
    1087                                           QSPI_CMB_SEQ_ADDR_CFG);
    1088 
    1089                         reinit_completion(&tqspi->xfer_completion);
    1090                         cmd1 = tegra_qspi_setup_transfer_one(spi, xfer,
    1091                                                              is_first_msg);
    1092                         ret = tegra_qspi_start_transfer_one(spi, xfer,
    1093                                                             cmd1);
    1094 
    1095                         if (ret < 0) {
    1096                                 dev_err(tqspi->dev, "Failed to start transfer-one: %d\n",
    1097                                         ret);
    1098                                 return ret;
    1099                         }
    1100 
    1101                         is_first_msg = false;
    1102                         ret = wait_for_completion_timeout
    1103                                         (&tqspi->xfer_completion,
    1104                                         QSPI_DMA_TIMEOUT);
    1105 
    1106                         if (WARN_ON(ret == 0)) {
    1107                                 dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n",
    1108                                         ret);
    1109                                 if (tqspi->is_curr_dma_xfer &&
    1110                                     (tqspi->cur_direction & DATA_DIR_TX))
    1111                                         dmaengine_terminate_all
    1112                                                 (tqspi->tx_dma_chan);
    1113 
    1114                                 if (tqspi->is_curr_dma_xfer &&
    1115                                     (tqspi->cur_direction & DATA_DIR_RX))
    1116                                         dmaengine_terminate_all
    1117                                                 (tqspi->rx_dma_chan);
    1118 
    1119                                 /* Abort transfer by resetting pio/dma bit */
    1120                                 if (!tqspi->is_curr_dma_xfer) {
    1121                                         cmd1 = tegra_qspi_readl
    1122                                                         (tqspi,
    1123                                                          QSPI_COMMAND1);
    1124                                         cmd1 &= ~QSPI_PIO;
    1125                                         tegra_qspi_writel
    1126                                                         (tqspi, cmd1,
    1127                                                          QSPI_COMMAND1);
    1128                                 } else {
    1129                                         dma_ctl = tegra_qspi_readl
    1130                                                         (tqspi,
    1131                                                          QSPI_DMA_CTL);
    1132                                         dma_ctl &= ~QSPI_DMA_EN;
    1133                                         tegra_qspi_writel(tqspi, dma_ctl,
    1134                                                           QSPI_DMA_CTL);
    1135                                 }
    1136 
    1137                                 /* Reset controller if timeout happens */
    1138                                 if (device_reset(tqspi->dev) < 0)
    1139                                         dev_warn_once(tqspi->dev,
    1140                                                       "device reset failed\n");
    1141                                 ret = -EIO;
    1142                                 goto exit;
    1143                         }
    1144 
    1145                         if (tqspi->tx_status ||  tqspi->rx_status) {
    1146                                 dev_err(tqspi->dev, "QSPI Transfer failed\n");
    1147                                 tqspi->tx_status = 0;
    1148                                 tqspi->rx_status = 0;
    1149                                 ret = -EIO;
    1150                                 goto exit;
    1151                         }
    1152                         break;
    1153                 default:
    1154                         ret = -EINVAL;
    1155                         goto exit;
    1156                 }
    1157                 msg->actual_length += xfer->len;
    1158                 transfer_phase++;
    1159         }
--> 1160         if (!xfer->cs_change) {
                     ^^^^^^^
list iterator used outside of loop.

    1161                 tegra_qspi_transfer_end(spi);
    1162                 spi_transfer_delay_exec(xfer);
    1163         }
    1164         ret = 0;
    1165 
    1166 exit:
    1167         msg->status = ret;
    1168 
    1169         return ret;
    1170 }

regards,
dan carpenter



[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux