From 137abc553c0a303e2de7e9864c80bc21583def89 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Fri, 4 Dec 2020 18:27:17 -0800 Subject: [PATCH 1/2] cnss2: Avoid trying DRV suspend if PCIe link speed is Gen 3 Commit baa52351d248 ("cnss2: change for fixed link speed") has a side effect that driver may try to enter DRV suspend with Gen 3 link speed which is currently not supported. This change will fix the original issue and side effect properly. Change-Id: Ia7dbee86554be7ddcec0fc1a91ad6ffbc7d6b2e5 Signed-off-by: Yue Ma --- drivers/net/wireless/cnss2/pci.c | 19 ++++++++++++++----- drivers/net/wireless/cnss2/pci.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 464eaa89101f..8ba72ef7d096 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -684,6 +684,7 @@ static int cnss_pci_get_link_status(struct cnss_pci_data *pci_priv) pci_priv->def_link_speed = link_status & PCI_EXP_LNKSTA_CLS; pci_priv->def_link_width = (link_status & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT; + pci_priv->cur_link_speed = pci_priv->def_link_speed; cnss_pr_dbg("Default PCI link speed is 0x%x, link width is 0x%x\n", pci_priv->def_link_speed, pci_priv->def_link_width); @@ -695,6 +696,7 @@ static int cnss_set_pci_link_status(struct cnss_pci_data *pci_priv, enum pci_link_status status) { u16 link_speed, link_width; + int ret; cnss_pr_vdbg("Set PCI link status to: %u\n", status); @@ -720,8 +722,12 @@ static int cnss_set_pci_link_status(struct cnss_pci_data *pci_priv, return -EINVAL; } - return msm_pcie_set_link_bandwidth(pci_priv->pci_dev, - link_speed, link_width); + ret = msm_pcie_set_link_bandwidth(pci_priv->pci_dev, + link_speed, link_width); + if (!ret) + pci_priv->cur_link_speed = link_speed; + + return ret; } static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up) @@ -740,9 +746,12 @@ static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up) if (pci_priv->drv_connected_last) { cnss_pr_vdbg("Use PCIe DRV suspend\n"); pm_ops = MSM_PCIE_DRV_SUSPEND; - if (pci_priv->device_id != QCA6390_DEVICE_ID && - pci_priv->device_id != QCA6490_DEVICE_ID) - cnss_set_pci_link_status(pci_priv, PCI_GEN1); + /* Since DRV suspend cannot be done in Gen 3, set it to + * Gen 2 if current link speed is larger than Gen 2. + */ + if (pci_priv->cur_link_speed > + PCI_EXP_LNKSTA_CLS_5_0GB) + cnss_set_pci_link_status(pci_priv, PCI_GEN2); } else { pm_ops = MSM_PCIE_SUSPEND; } diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index 1b5195a9655b..b3de0754369d 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -93,6 +93,7 @@ struct cnss_pci_data { u32 qmi_send_usage_count; u16 def_link_speed; u16 def_link_width; + u16 cur_link_speed; struct completion wake_event; u8 monitor_wake_intr; struct iommu_domain *iommu_domain; From fdf90263880db19c0d5f9fed885962b14e90d940 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Wed, 9 Dec 2020 18:45:31 -0800 Subject: [PATCH 2/2] cnss2: Use proper DMA mask based on device ID Refactor the code to set proper DMA mask based on device ID. Also set MHI IOVA address range based on the same DMA mask since it will be more easier to port the driver to non-MSM platforms where there is no SMMU or IOMMU. Change-Id: I2daef00b9cb96b81433ed1338b1caf37b4002d80 Signed-off-by: Yue Ma --- drivers/net/wireless/cnss2/pci.c | 35 +++++++++++++++++++++----------- drivers/net/wireless/cnss2/pci.h | 1 + 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 8ba72ef7d096..2cf30e2054f4 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -31,8 +31,9 @@ #define PCI_BAR_NUM 0 -#define PCI_DMA_MASK_32_BIT 32 -#define PCI_DMA_MASK_64_BIT 64 +#define PCI_DMA_MASK_32_BIT DMA_BIT_MASK(32) +#define PCI_DMA_MASK_36_BIT DMA_BIT_MASK(36) +#define PCI_DMA_MASK_64_BIT DMA_BIT_MASK(64) #define MHI_NODE_NAME "qcom,mhi" #define MHI_MSI_NAME "MHI" @@ -4057,7 +4058,6 @@ static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv) int ret = 0; struct pci_dev *pci_dev = pci_priv->pci_dev; u16 device_id; - u32 pci_dma_mask = PCI_DMA_MASK_64_BIT; pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id); if (device_id != pci_priv->pci_device_id->device) { @@ -4085,20 +4085,31 @@ static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv) goto disable_device; } - if (device_id == QCA6174_DEVICE_ID) - pci_dma_mask = PCI_DMA_MASK_32_BIT; + switch (device_id) { + case QCA6174_DEVICE_ID: + pci_priv->dma_bit_mask = PCI_DMA_MASK_32_BIT; + break; + case QCA6390_DEVICE_ID: + case QCA6490_DEVICE_ID: + pci_priv->dma_bit_mask = PCI_DMA_MASK_36_BIT; + break; + default: + pci_priv->dma_bit_mask = PCI_DMA_MASK_64_BIT; + break; + } - ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(pci_dma_mask)); + cnss_pr_dbg("Set PCI DMA MASK (0x%llx)\n", pci_priv->dma_bit_mask); + + ret = pci_set_dma_mask(pci_dev, pci_priv->dma_bit_mask); if (ret) { - cnss_pr_err("Failed to set PCI DMA mask (%d), err = %d\n", - ret, pci_dma_mask); + cnss_pr_err("Failed to set PCI DMA mask, err = %d\n", ret); goto release_region; } - ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(pci_dma_mask)); + ret = pci_set_consistent_dma_mask(pci_dev, pci_priv->dma_bit_mask); if (ret) { - cnss_pr_err("Failed to set PCI consistent DMA mask (%d), err = %d\n", - ret, pci_dma_mask); + cnss_pr_err("Failed to set PCI consistent DMA mask, err = %d\n", + ret); goto release_region; } @@ -4865,7 +4876,7 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv) pci_priv->smmu_iova_len; } else { mhi_ctrl->iova_start = 0; - mhi_ctrl->iova_stop = UINT_MAX; + mhi_ctrl->iova_stop = pci_priv->dma_bit_mask; } mhi_ctrl->link_status = cnss_mhi_link_status; diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index b3de0754369d..e44e1b298d7e 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -80,6 +80,7 @@ struct cnss_pci_data { const struct pci_device_id *pci_device_id; u32 device_id; u16 revision_id; + u64 dma_bit_mask; struct cnss_wlan_driver *driver_ops; u8 pci_link_state; u8 pci_link_down_ind;