}
 
                        if (cmd->data && err) {
+                               /*
+                                * During UHS tuning sequence, sending the stop
+                                * command after the response CRC error would
+                                * throw the system into a confused state
+                                * causing all future tuning phases to report
+                                * failure.
+                                *
+                                * In such case controller will move into a data
+                                * transfer state after a response error or
+                                * response CRC error. Let's let that finish
+                                * before trying to send a stop, so we'll go to
+                                * STATE_SENDING_DATA.
+                                *
+                                * Although letting the data transfer take place
+                                * will waste a bit of time (we already know
+                                * the command was bad), it can't cause any
+                                * errors since it's possible it would have
+                                * taken place anyway if this tasklet got
+                                * delayed. Allowing the transfer to take place
+                                * avoids races and keeps things simple.
+                                */
+                               if ((err != -ETIMEDOUT) &&
+                                   (cmd->opcode == MMC_SEND_TUNING_BLOCK)) {
+                                       state = STATE_SENDING_DATA;
+                                       continue;
+                               }
+
                                dw_mci_stop_dma(host);
                                send_stop_abort(host, data);
                                state = STATE_SENDING_STOP;