OSDN Git Service

Merge branch 'fixes' into next
authorUlf Hansson <ulf.hansson@linaro.org>
Thu, 28 May 2020 09:22:22 +0000 (11:22 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 28 May 2020 09:22:22 +0000 (11:22 +0200)
1  2 
drivers/mmc/host/sdhci.c

diff --combined drivers/mmc/host/sdhci.c
  static unsigned int debug_quirks = 0;
  static unsigned int debug_quirks2;
  
 -static void sdhci_finish_data(struct sdhci_host *);
 -
  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
  
 +static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd);
 +
  void sdhci_dumpregs(struct sdhci_host *host)
  {
        SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n");
                }
        }
  
 +      if (host->ops->dump_vendor_regs)
 +              host->ops->dump_vendor_regs(host);
 +
        SDHCI_DUMP("============================================\n");
  }
  EXPORT_SYMBOL_GPL(sdhci_dumpregs);
@@@ -320,7 -317,6 +320,7 @@@ out
  static void sdhci_init(struct sdhci_host *host, int soft)
  {
        struct mmc_host *mmc = host->mmc;
 +      unsigned long flags;
  
        if (soft)
                sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
        if (host->v4_mode)
                sdhci_do_enable_v4_mode(host);
  
 +      spin_lock_irqsave(&host->lock, flags);
        sdhci_set_default_irqs(host);
 +      spin_unlock_irqrestore(&host->lock, flags);
  
        host->cqe_on = false;
  
@@@ -640,13 -634,9 +640,13 @@@ static int sdhci_pre_dma_transfer(struc
                }
                if (mmc_get_dma_dir(data) == DMA_TO_DEVICE) {
                        /* Copy the data to the bounce buffer */
 -                      sg_copy_to_buffer(data->sg, data->sg_len,
 -                                        host->bounce_buffer,
 -                                        length);
 +                      if (host->ops->copy_to_bounce_buffer) {
 +                              host->ops->copy_to_bounce_buffer(host,
 +                                                               data, length);
 +                      } else {
 +                              sg_copy_to_buffer(data->sg, data->sg_len,
 +                                                host->bounce_buffer, length);
 +                      }
                }
                /* Switch ownership to the DMA */
                dma_sync_single_for_device(host->mmc->parent,
@@@ -1360,25 -1350,13 +1360,25 @@@ static inline bool sdhci_auto_cmd12(str
               !mrq->cap_cmd_during_tfr;
  }
  
 +static inline bool sdhci_auto_cmd23(struct sdhci_host *host,
 +                                  struct mmc_request *mrq)
 +{
 +      return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);
 +}
 +
 +static inline bool sdhci_manual_cmd23(struct sdhci_host *host,
 +                                    struct mmc_request *mrq)
 +{
 +      return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23);
 +}
 +
  static inline void sdhci_auto_cmd_select(struct sdhci_host *host,
                                         struct mmc_command *cmd,
                                         u16 *mode)
  {
        bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&
                         (cmd->opcode != SD_IO_RW_EXTENDED);
 -      bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);
 +      bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq);
        u16 ctrl2;
  
        /*
@@@ -1438,7 -1416,7 +1438,7 @@@ static void sdhci_set_transfer_mode(str
        if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {
                mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;
                sdhci_auto_cmd_select(host, cmd, &mode);
 -              if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23))
 +              if (sdhci_auto_cmd23(host, cmd->mrq))
                        sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);
        }
  
@@@ -1488,9 -1466,6 +1488,9 @@@ static void __sdhci_finish_mrq(struct s
        if (host->data_cmd && host->data_cmd->mrq == mrq)
                host->data_cmd = NULL;
  
 +      if (host->deferred_cmd && host->deferred_cmd->mrq == mrq)
 +              host->deferred_cmd = NULL;
 +
        if (host->data && host->data->mrq == mrq)
                host->data = NULL;
  
@@@ -1512,7 -1487,7 +1512,7 @@@ static void sdhci_finish_mrq(struct sdh
        queue_work(host->complete_wq, &host->complete_work);
  }
  
 -static void sdhci_finish_data(struct sdhci_host *host)
 +static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
  {
        struct mmc_command *data_cmd = host->data_cmd;
        struct mmc_data *data = host->data;
                } else {
                        /* Avoid triggering warning in sdhci_send_command() */
                        host->cmd = NULL;
 -                      sdhci_send_command(host, data->stop);
 +                      if (!sdhci_send_command(host, data->stop)) {
 +                              if (sw_data_timeout) {
 +                                      /*
 +                                       * This is anyway a sw data timeout, so
 +                                       * give up now.
 +                                       */
 +                                      data->stop->error = -EIO;
 +                                      __sdhci_finish_mrq(host, data->mrq);
 +                              } else {
 +                                      WARN_ON(host->deferred_cmd);
 +                                      host->deferred_cmd = data->stop;
 +                              }
 +                      }
                }
        } else {
                __sdhci_finish_mrq(host, data->mrq);
        }
  }
  
 -void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 +static void sdhci_finish_data(struct sdhci_host *host)
 +{
 +      __sdhci_finish_data(host, false);
 +}
 +
 +static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
  {
        int flags;
        u32 mask;
            cmd->opcode == MMC_STOP_TRANSMISSION)
                cmd->flags |= MMC_RSP_BUSY;
  
 -      /* Wait max 10 ms */
 -      timeout = 10;
 -
        mask = SDHCI_CMD_INHIBIT;
        if (sdhci_data_line_cmd(cmd))
                mask |= SDHCI_DATA_INHIBIT;
        if (cmd->mrq->data && (cmd == cmd->mrq->data->stop))
                mask &= ~SDHCI_DATA_INHIBIT;
  
 -      while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
 -              if (timeout == 0) {
 -                      pr_err("%s: Controller never released inhibit bit(s).\n",
 -                             mmc_hostname(host->mmc));
 -                      sdhci_dumpregs(host);
 -                      cmd->error = -EIO;
 -                      sdhci_finish_mrq(host, cmd->mrq);
 -                      return;
 -              }
 -              timeout--;
 -              mdelay(1);
 -      }
 +      if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
 +              return false;
  
        host->cmd = cmd;
        host->data_timeout = 0;
        sdhci_set_transfer_mode(host, cmd);
  
        if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
 -              pr_err("%s: Unsupported response type!\n",
 -                      mmc_hostname(host->mmc));
 -              cmd->error = -EINVAL;
 -              sdhci_finish_mrq(host, cmd->mrq);
 -              return;
 +              WARN_ONCE(1, "Unsupported response type!\n");
 +              /*
 +               * This does not happen in practice because 136-bit response
 +               * commands never have busy waiting, so rather than complicate
 +               * the error path, just remove busy waiting and continue.
 +               */
 +              cmd->flags &= ~MMC_RSP_BUSY;
        }
  
        if (!(cmd->flags & MMC_RSP_PRESENT))
                sdhci_external_dma_pre_transfer(host, cmd);
  
        sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
 +
 +      return true;
 +}
 +
 +static bool sdhci_present_error(struct sdhci_host *host,
 +                              struct mmc_command *cmd, bool present)
 +{
 +      if (!present || host->flags & SDHCI_DEVICE_DEAD) {
 +              cmd->error = -ENOMEDIUM;
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
 +static bool sdhci_send_command_retry(struct sdhci_host *host,
 +                                   struct mmc_command *cmd,
 +                                   unsigned long flags)
 +      __releases(host->lock)
 +      __acquires(host->lock)
 +{
 +      struct mmc_command *deferred_cmd = host->deferred_cmd;
 +      int timeout = 10; /* Approx. 10 ms */
 +      bool present;
 +
 +      while (!sdhci_send_command(host, cmd)) {
 +              if (!timeout--) {
 +                      pr_err("%s: Controller never released inhibit bit(s).\n",
 +                             mmc_hostname(host->mmc));
 +                      sdhci_dumpregs(host);
 +                      cmd->error = -EIO;
 +                      return false;
 +              }
 +
 +              spin_unlock_irqrestore(&host->lock, flags);
 +
 +              usleep_range(1000, 1250);
 +
 +              present = host->mmc->ops->get_cd(host->mmc);
 +
 +              spin_lock_irqsave(&host->lock, flags);
 +
 +              /* A deferred command might disappear, handle that */
 +              if (cmd == deferred_cmd && cmd != host->deferred_cmd)
 +                      return true;
 +
 +              if (sdhci_present_error(host, cmd, present))
 +                      return false;
 +      }
 +
 +      if (cmd == host->deferred_cmd)
 +              host->deferred_cmd = NULL;
 +
 +      return true;
  }
 -EXPORT_SYMBOL_GPL(sdhci_send_command);
  
  static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd)
  {
@@@ -1791,10 -1707,7 +1791,10 @@@ static void sdhci_finish_command(struc
  
        /* Finished CMD23, now send actual command. */
        if (cmd == cmd->mrq->sbc) {
 -              sdhci_send_command(host, cmd->mrq->cmd);
 +              if (!sdhci_send_command(host, cmd->mrq->cmd)) {
 +                      WARN_ON(host->deferred_cmd);
 +                      host->deferred_cmd = cmd->mrq->cmd;
 +              }
        } else {
  
                /* Processed actual command. */
@@@ -2124,10 -2037,11 +2124,10 @@@ EXPORT_SYMBOL_GPL(sdhci_set_power_and_b
  
  void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
  {
 -      struct sdhci_host *host;
 -      int present;
 +      struct sdhci_host *host = mmc_priv(mmc);
 +      struct mmc_command *cmd;
        unsigned long flags;
 -
 -      host = mmc_priv(mmc);
 +      bool present;
  
        /* Firstly check card presence */
        present = mmc->ops->get_cd(mmc);
  
        sdhci_led_activate(host);
  
 -      if (!present || host->flags & SDHCI_DEVICE_DEAD) {
 -              mrq->cmd->error = -ENOMEDIUM;
 +      if (sdhci_present_error(host, mrq->cmd, present))
 +              goto out_finish;
 +
 +      cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd;
 +
 +      if (!sdhci_send_command_retry(host, cmd, flags))
 +              goto out_finish;
 +
 +      spin_unlock_irqrestore(&host->lock, flags);
 +
 +      return;
 +
 +out_finish:
 +      sdhci_finish_mrq(host, mrq);
 +      spin_unlock_irqrestore(&host->lock, flags);
 +}
 +EXPORT_SYMBOL_GPL(sdhci_request);
 +
 +int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq)
 +{
 +      struct sdhci_host *host = mmc_priv(mmc);
 +      struct mmc_command *cmd;
 +      unsigned long flags;
 +      int ret = 0;
 +
 +      spin_lock_irqsave(&host->lock, flags);
 +
 +      if (sdhci_present_error(host, mrq->cmd, true)) {
                sdhci_finish_mrq(host, mrq);
 -      } else {
 -              if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
 -                      sdhci_send_command(host, mrq->sbc);
 -              else
 -                      sdhci_send_command(host, mrq->cmd);
 +              goto out_finish;
        }
  
 +      cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd;
 +
 +      /*
 +       * The HSQ may send a command in interrupt context without polling
 +       * the busy signaling, which means we should return BUSY if controller
 +       * has not released inhibit bits to allow HSQ trying to send request
 +       * again in non-atomic context. So we should not finish this request
 +       * here.
 +       */
 +      if (!sdhci_send_command(host, cmd))
 +              ret = -EBUSY;
 +      else
 +              sdhci_led_activate(host);
 +
 +out_finish:
        spin_unlock_irqrestore(&host->lock, flags);
 +      return ret;
  }
 -EXPORT_SYMBOL_GPL(sdhci_request);
 +EXPORT_SYMBOL_GPL(sdhci_request_atomic);
  
  void sdhci_set_bus_width(struct sdhci_host *host, int width)
  {
@@@ -2535,7 -2411,7 +2535,7 @@@ int sdhci_start_signal_voltage_switch(s
  
                if (!IS_ERR(mmc->supply.vqmmc)) {
                        ret = mmc_regulator_set_vqmmc(mmc, ios);
 -                      if (ret) {
 +                      if (ret < 0) {
                                pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
                                        mmc_hostname(mmc));
                                return -EIO;
                        return -EINVAL;
                if (!IS_ERR(mmc->supply.vqmmc)) {
                        ret = mmc_regulator_set_vqmmc(mmc, ios);
 -                      if (ret) {
 +                      if (ret < 0) {
                                pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
                                        mmc_hostname(mmc));
                                return -EIO;
                        return -EINVAL;
                if (!IS_ERR(mmc->supply.vqmmc)) {
                        ret = mmc_regulator_set_vqmmc(mmc, ios);
 -                      if (ret) {
 +                      if (ret < 0) {
                                pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
                                        mmc_hostname(mmc));
                                return -EIO;
@@@ -2724,11 -2600,7 +2724,11 @@@ void sdhci_send_tuning(struct sdhci_hos
         */
        sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
  
 -      sdhci_send_command(host, &cmd);
 +      if (!sdhci_send_command_retry(host, &cmd, flags)) {
 +              spin_unlock_irqrestore(&host->lock, flags);
 +              host->tuning_done = 0;
 +              return;
 +      }
  
        host->cmd = NULL;
  
@@@ -3146,7 -3018,7 +3146,7 @@@ static void sdhci_timeout_data_timer(st
  
                if (host->data) {
                        host->data->error = -ETIMEDOUT;
 -                      sdhci_finish_data(host);
 +                      __sdhci_finish_data(host, true);
                        queue_work(host->complete_wq, &host->complete_work);
                } else if (host->data_cmd) {
                        host->data_cmd->error = -ETIMEDOUT;
@@@ -3518,9 -3390,6 +3518,9 @@@ cont
                }
        }
  out:
 +      if (host->deferred_cmd)
 +              result = IRQ_WAKE_THREAD;
 +
        spin_unlock(&host->lock);
  
        /* Process mrqs ready for immediate completion */
  static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
  {
        struct sdhci_host *host = dev_id;
 +      struct mmc_command *cmd;
        unsigned long flags;
        u32 isr;
  
                ;
  
        spin_lock_irqsave(&host->lock, flags);
 +
        isr = host->thread_isr;
        host->thread_isr = 0;
 +
 +      cmd = host->deferred_cmd;
 +      if (cmd && !sdhci_send_command_retry(host, cmd, flags))
 +              sdhci_finish_mrq(host, cmd->mrq);
 +
        spin_unlock_irqrestore(&host->lock, flags);
  
        if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
@@@ -4138,9 -4000,6 +4138,6 @@@ int sdhci_setup_host(struct sdhci_host 
                       mmc_hostname(mmc), host->version);
        }
  
-       if (host->quirks & SDHCI_QUIRK_BROKEN_CQE)
-               mmc->caps2 &= ~MMC_CAP2_CQE;
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_SDMA;
        else if (!(host->caps & SDHCI_CAN_DO_SDMA))
        }
  
        if (host->version >= SDHCI_SPEC_300)
 -              host->max_clk = (host->caps & SDHCI_CLOCK_V3_BASE_MASK)
 -                      >> SDHCI_CLOCK_BASE_SHIFT;
 +              host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps);
        else
 -              host->max_clk = (host->caps & SDHCI_CLOCK_BASE_MASK)
 -                      >> SDHCI_CLOCK_BASE_SHIFT;
 +              host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps);
  
        host->max_clk *= 1000000;
        if (host->max_clk == 0 || host->quirks &
         * In case of Host Controller v3.00, find out whether clock
         * multiplier is supported.
         */
 -      host->clk_mul = (host->caps1 & SDHCI_CLOCK_MUL_MASK) >>
 -                      SDHCI_CLOCK_MUL_SHIFT;
 +      host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1);
  
        /*
         * In case the value in Clock Multiplier is 0, then programmable
                mmc->f_max = max_clk;
  
        if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
 -              host->timeout_clk = (host->caps & SDHCI_TIMEOUT_CLK_MASK) >>
 -                                      SDHCI_TIMEOUT_CLK_SHIFT;
 +              host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps);
  
                if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
                        host->timeout_clk *= 1000;
            !host->ops->get_max_timeout_count)
                mmc->max_busy_timeout = 0;
  
 -      mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 +      mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23;
        mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
  
        if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
                mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
  
        /* Initial value for re-tuning timer count */
 -      host->tuning_count = (host->caps1 & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
 -                           SDHCI_RETUNING_TIMER_COUNT_SHIFT;
 +      host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK,
 +                                     host->caps1);
  
        /*
         * In case Re-tuning Timer is not disabled, the actual value of
                host->tuning_count = 1 << (host->tuning_count - 1);
  
        /* Re-tuning mode supported by the Host Controller */
 -      host->tuning_mode = (host->caps1 & SDHCI_RETUNING_MODE_MASK) >>
 -                           SDHCI_RETUNING_MODE_SHIFT;
 +      host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1);
  
        ocr_avail = 0;
  
  
                        curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
                        max_current_caps =
 -                              (curr << SDHCI_MAX_CURRENT_330_SHIFT) |
 -                              (curr << SDHCI_MAX_CURRENT_300_SHIFT) |
 -                              (curr << SDHCI_MAX_CURRENT_180_SHIFT);
 +                              FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) |
 +                              FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) |
 +                              FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr);
                }
        }
  
        if (host->caps & SDHCI_CAN_VDD_330) {
                ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
  
 -              mmc->max_current_330 = ((max_current_caps &
 -                                 SDHCI_MAX_CURRENT_330_MASK) >>
 -                                 SDHCI_MAX_CURRENT_330_SHIFT) *
 -                                 SDHCI_MAX_CURRENT_MULTIPLIER;
 +              mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK,
 +                                               max_current_caps) *
 +                                              SDHCI_MAX_CURRENT_MULTIPLIER;
        }
        if (host->caps & SDHCI_CAN_VDD_300) {
                ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
  
 -              mmc->max_current_300 = ((max_current_caps &
 -                                 SDHCI_MAX_CURRENT_300_MASK) >>
 -                                 SDHCI_MAX_CURRENT_300_SHIFT) *
 -                                 SDHCI_MAX_CURRENT_MULTIPLIER;
 +              mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK,
 +                                               max_current_caps) *
 +                                              SDHCI_MAX_CURRENT_MULTIPLIER;
        }
        if (host->caps & SDHCI_CAN_VDD_180) {
                ocr_avail |= MMC_VDD_165_195;
  
 -              mmc->max_current_180 = ((max_current_caps &
 -                                 SDHCI_MAX_CURRENT_180_MASK) >>
 -                                 SDHCI_MAX_CURRENT_180_SHIFT) *
 -                                 SDHCI_MAX_CURRENT_MULTIPLIER;
 +              mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK,
 +                                               max_current_caps) *
 +                                              SDHCI_MAX_CURRENT_MULTIPLIER;
        }
  
        /* If OCR set by host, use it instead. */
@@@ -4669,6 -4536,12 +4666,12 @@@ int __sdhci_add_host(struct sdhci_host 
        struct mmc_host *mmc = host->mmc;
        int ret;
  
+       if ((mmc->caps2 & MMC_CAP2_CQE) &&
+           (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) {
+               mmc->caps2 &= ~MMC_CAP2_CQE;
+               mmc->cqe_ops = NULL;
+       }
        host->complete_wq = alloc_workqueue("sdhci", flags, 0);
        if (!host->complete_wq)
                return -ENOMEM;