[V2] mmc: sdhci-pci-gli: Improve Random 4K Read Performance of GL9763E

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

 



This patch is based on patch [1] and adopt Adrian's comment.

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.

[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




[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux