On Mon, 30 May 2022 at 10:47, Jason Lai <jasonlai.genesyslogic@xxxxxxxxx> wrote: > > This patch is based on patch [1] and adopt Adrian's comment. Please squash $subject patch into [1], rather than making a new patch on top. > > Due to flaws in hardware design, GL9763E takes long time to exit from L1 > state. The I/O performance will suffer severe impact if it often enter > and exit L1 state. > > Unfortunately, entering and exiting L1 state is signal handshake in > physical layer, software knows nothiong about it. The only way to stop > entering L1 state is to disable hardware LPM negotiation on GL9763E. > > To improve read performance and take battery life into account, we reject > L1 negotiation while executing MMC_READ_MULTIPLE_BLOCK command and enable > L1 negotiation again when receiving non-MMC_READ_MULTIPLE_BLOCK command. I am not sure how the HW decides to enter L1. That said, I wonder if it would be a better option to turn on/off the LPM from the ->runtime_suspend|resume() callbacks instead? Kind regards Uffe > > [1] https://patchwork.kernel.org/project/linux-mmc/list/?series=645165 > > Signed-off-by: Renius Chen <reniuschengl@xxxxxxxxx> > Signed-off-by: Jason Lai <jason.lai@xxxxxxxxxxxxxxxxxxx> > --- > drivers/mmc/host/sdhci-pci-gli.c | 31 ++++++++++++++++++++----------- > 1 file changed, 20 insertions(+), 11 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c > index 86200b73c0b0..13c09202da9c 100644 > --- a/drivers/mmc/host/sdhci-pci-gli.c > +++ b/drivers/mmc/host/sdhci-pci-gli.c > @@ -850,24 +850,29 @@ static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool > pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); > } > > +static void gl9763e_set_lpm_negotiation(struct sdhci_pci_slot *slot, bool enable) > +{ > + struct gli_host *gli_host = sdhci_pci_priv(slot); > + > + if (gli_host->lpm_negotiation_enabled == enable) > + return; > + > + gli_host->lpm_negotiation_enabled = enable; > + > + gl9763e_set_low_power_negotiation(slot, enable); > +} > + > static void gl9763e_request(struct mmc_host *mmc, struct mmc_request *mrq) > { > struct sdhci_host *host = mmc_priv(mmc); > struct mmc_command *cmd; > struct sdhci_pci_slot *slot = sdhci_priv(host); > - struct gli_host *gli_host = sdhci_pci_priv(slot); > > cmd = mrq->cmd; > - > - if (cmd && (cmd->opcode == MMC_READ_MULTIPLE_BLOCK) && gli_host->lpm_negotiation_enabled) { > - gl9763e_set_low_power_negotiation(slot, false); > - gli_host->lpm_negotiation_enabled = false; > - } else { > - if (gli_host->lpm_negotiation_enabled == false) { > - gl9763e_set_low_power_negotiation(slot, true); > - gli_host->lpm_negotiation_enabled = true; > - } > - } > + if (cmd && (cmd->opcode == MMC_READ_MULTIPLE_BLOCK)) > + gl9763e_set_lpm_negotiation(slot, false); > + else > + gl9763e_set_lpm_negotiation(slot, true); > > sdhci_request(mmc, mrq); > } > @@ -975,6 +980,7 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) > { > struct pci_dev *pdev = slot->chip->pdev; > u32 value; > + struct gli_host *gli_host = sdhci_pci_priv(slot); > > pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); > value &= ~GLI_9763E_VHS_REV; > @@ -995,6 +1001,9 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) > value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); > pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); > > + /* Default setting of LPM negotiation is enabled. */ > + gli_host->lpm_negotiation_enabled = true; > + > pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, &value); > value &= ~GLI_9763E_HS400_RXDLY; > value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); > -- > 2.36.1 >