Merge tag 'trace-seq-buf-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/roste...
[cascardo/linux.git] / drivers / mmc / core / core.c
index f26a5f1..9584bff 100644 (file)
@@ -149,6 +149,14 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 
                led_trigger_event(host->led, LED_OFF);
 
+               if (mrq->sbc) {
+                       pr_debug("%s: req done <CMD%u>: %d: %08x %08x %08x %08x\n",
+                               mmc_hostname(host), mrq->sbc->opcode,
+                               mrq->sbc->error,
+                               mrq->sbc->resp[0], mrq->sbc->resp[1],
+                               mrq->sbc->resp[2], mrq->sbc->resp[3]);
+               }
+
                pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
                        mmc_hostname(host), cmd->opcode, err,
                        cmd->resp[0], cmd->resp[1],
@@ -214,6 +222,10 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
        mrq->cmd->error = 0;
        mrq->cmd->mrq = mrq;
+       if (mrq->sbc) {
+               mrq->sbc->error = 0;
+               mrq->sbc->mrq = mrq;
+       }
        if (mrq->data) {
                BUG_ON(mrq->data->blksz > host->max_blk_size);
                BUG_ON(mrq->data->blocks > host->max_blk_count);
@@ -538,8 +550,18 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
                if (host->card && mmc_card_mmc(host->card) &&
                    ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) ||
                     (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) &&
-                   (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT))
+                   (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) {
+
+                       /* Cancel the prepared request */
+                       if (areq)
+                               mmc_post_req(host, areq->mrq, -EINVAL);
+
                        mmc_start_bkops(host->card, true);
+
+                       /* prepare the request again */
+                       if (areq)
+                               mmc_pre_req(host, areq->mrq, !host->areq);
+               }
        }
 
        if (!err && areq)
@@ -709,27 +731,16 @@ int mmc_read_bkops_status(struct mmc_card *card)
        int err;
        u8 *ext_csd;
 
-       /*
-        * In future work, we should consider storing the entire ext_csd.
-        */
-       ext_csd = kmalloc(512, GFP_KERNEL);
-       if (!ext_csd) {
-               pr_err("%s: could not allocate buffer to receive the ext_csd.\n",
-                      mmc_hostname(card->host));
-               return -ENOMEM;
-       }
-
        mmc_claim_host(card->host);
-       err = mmc_send_ext_csd(card, ext_csd);
+       err = mmc_get_ext_csd(card, &ext_csd);
        mmc_release_host(card->host);
        if (err)
-               goto out;
+               return err;
 
        card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
        card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
-out:
        kfree(ext_csd);
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL(mmc_read_bkops_status);
 
@@ -1088,6 +1099,22 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
        mmc_host_clk_release(host);
 }
 
+/*
+ * Set initial state after a power cycle or a hw_reset.
+ */
+void mmc_set_initial_state(struct mmc_host *host)
+{
+       if (mmc_host_is_spi(host))
+               host->ios.chip_select = MMC_CS_HIGH;
+       else
+               host->ios.chip_select = MMC_CS_DONTCARE;
+       host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
+
+       mmc_set_ios(host);
+}
+
 /**
  * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
  * @vdd:       voltage (mV)
@@ -1420,18 +1447,20 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
                pr_warn("%s: cannot verify signal voltage switch\n",
                        mmc_hostname(host));
 
+       mmc_host_clk_hold(host);
+
        cmd.opcode = SD_SWITCH_VOLTAGE;
        cmd.arg = 0;
        cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
        err = mmc_wait_for_cmd(host, &cmd, 0);
        if (err)
-               return err;
+               goto err_command;
 
-       if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
-               return -EIO;
-
-       mmc_host_clk_hold(host);
+       if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) {
+               err = -EIO;
+               goto err_command;
+       }
        /*
         * The card should drive cmd and dat[0:3] low immediately
         * after the response of cmd11, but wait 1 ms to be sure
@@ -1480,6 +1509,7 @@ power_cycle:
                mmc_power_cycle(host, ocr);
        }
 
+err_command:
        mmc_host_clk_release(host);
 
        return err;
@@ -1526,15 +1556,9 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
        mmc_host_clk_hold(host);
 
        host->ios.vdd = fls(ocr) - 1;
-       if (mmc_host_is_spi(host))
-               host->ios.chip_select = MMC_CS_HIGH;
-       else
-               host->ios.chip_select = MMC_CS_DONTCARE;
-       host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
        host->ios.power_mode = MMC_POWER_UP;
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
+       /* Set initial state and call mmc_set_ios */
+       mmc_set_initial_state(host);
 
        /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */
        if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0)
@@ -1574,14 +1598,9 @@ void mmc_power_off(struct mmc_host *host)
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
-       if (!mmc_host_is_spi(host)) {
-               host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-               host->ios.chip_select = MMC_CS_DONTCARE;
-       }
        host->ios.power_mode = MMC_POWER_OFF;
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
+       /* Set initial state and call mmc_set_ios */
+       mmc_set_initial_state(host);
 
        /*
         * Some configurations, such as the 802.11 SDIO card in the OLPC
@@ -2259,30 +2278,16 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 
        /* If the reset has happened, then a status command will fail */
        if (check) {
-               struct mmc_command cmd = {0};
-               int err;
+               u32 status;
 
-               cmd.opcode = MMC_SEND_STATUS;
-               if (!mmc_host_is_spi(card->host))
-                       cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-               err = mmc_wait_for_cmd(card->host, &cmd, 0);
-               if (!err) {
+               if (!mmc_send_status(card, &status)) {
                        mmc_host_clk_release(host);
                        return -ENOSYS;
                }
        }
 
-       if (mmc_host_is_spi(host)) {
-               host->ios.chip_select = MMC_CS_HIGH;
-               host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-       } else {
-               host->ios.chip_select = MMC_CS_DONTCARE;
-               host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-       }
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
+       /* Set initial state and call mmc_set_ios */
+       mmc_set_initial_state(host);
 
        mmc_host_clk_release(host);