Message ID | 20240329090945.1097609-18-dlemoal@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Improve PCI memory mapping API | expand |
Hi Damien,
kernel test robot noticed the following build warnings:
[auto build test WARNING on pci/next]
[also build test WARNING on pci/for-linus mani-mhi/mhi-next linus/master v6.9-rc1 next-20240328]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Damien-Le-Moal/PCI-endpoint-Introduce-pci_epc_check_func/20240329-171158
base: https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next
patch link: https://lore.kernel.org/r/20240329090945.1097609-18-dlemoal%40kernel.org
patch subject: [PATCH 17/19] PCI: rockchip-ep: Improve link training
config: arc-randconfig-001-20240330 (https://download.01.org/0day-ci/archive/20240331/202403310925.C7WNNuAl-lkp@intel.com/config)
compiler: arc-elf-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240331/202403310925.C7WNNuAl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202403310925.C7WNNuAl-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/pci/controller/pcie-rockchip-ep.c:54: warning: Function parameter or struct member 'link_training' not described in 'rockchip_pcie_ep'
vim +54 drivers/pci/controller/pcie-rockchip-ep.c
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 23
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 24 /**
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 25 * struct rockchip_pcie_ep - private data for PCIe endpoint controller driver
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 26 * @rockchip: Rockchip PCIe controller
9b41d19aff4090 drivers/pci/controller/pcie-rockchip-ep.c Krzysztof Kozlowski 2020-07-29 27 * @epc: PCI EPC device
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 28 * @max_regions: maximum number of regions supported by hardware
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 29 * @ob_region_map: bitmask of mapped outbound regions
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 30 * @ob_addr: base addresses in the AXI bus where the outbound regions start
5815c2d17a7492 drivers/pci/controller/pcie-rockchip-ep.c Damien Le Moal 2023-11-22 31 * @irq_phys_addr: base address on the AXI bus where the MSI/INTX IRQ
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 32 * dedicated outbound regions is mapped.
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 33 * @irq_cpu_addr: base address in the CPU space where a write access triggers
5815c2d17a7492 drivers/pci/controller/pcie-rockchip-ep.c Damien Le Moal 2023-11-22 34 * the sending of a memory write (MSI) / normal message (INTX
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 35 * IRQ) TLP through the PCIe bus.
5815c2d17a7492 drivers/pci/controller/pcie-rockchip-ep.c Damien Le Moal 2023-11-22 36 * @irq_pci_addr: used to save the current mapping of the MSI/INTX IRQ
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 37 * dedicated outbound region.
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 38 * @irq_pci_fn: the latest PCI function that has updated the mapping of
5815c2d17a7492 drivers/pci/controller/pcie-rockchip-ep.c Damien Le Moal 2023-11-22 39 * the MSI/INTX IRQ dedicated outbound region.
5815c2d17a7492 drivers/pci/controller/pcie-rockchip-ep.c Damien Le Moal 2023-11-22 40 * @irq_pending: bitmask of asserted INTX IRQs.
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 41 */
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 42 struct rockchip_pcie_ep {
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 43 struct rockchip_pcie rockchip;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 44 struct pci_epc *epc;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 45 u32 max_regions;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 46 unsigned long ob_region_map;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 47 phys_addr_t *ob_addr;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 48 phys_addr_t irq_phys_addr;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 49 void __iomem *irq_cpu_addr;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 50 u64 irq_pci_addr;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 51 u8 irq_pci_fn;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 52 u8 irq_pending;
9bd13985625aa9 drivers/pci/controller/pcie-rockchip-ep.c Damien Le Moal 2024-03-29 53 struct delayed_work link_training;
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 @54 };
cf590b07839133 drivers/pci/host/pcie-rockchip-ep.c Shawn Lin 2018-05-09 55
diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c index c126da07bf0c..d8e56b4a5578 100644 --- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -16,6 +16,8 @@ #include <linux/platform_device.h> #include <linux/pci-epf.h> #include <linux/sizes.h> +#include <linux/workqueue.h> +#include <linux/iopoll.h> #include "pcie-rockchip.h" @@ -48,6 +50,7 @@ struct rockchip_pcie_ep { u64 irq_pci_addr; u8 irq_pci_fn; u8 irq_pending; + struct delayed_work link_training; }; static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, @@ -467,6 +470,8 @@ static int rockchip_pcie_ep_start(struct pci_epc *epc) PCIE_CLIENT_CONF_ENABLE, PCIE_CLIENT_CONFIG); + schedule_delayed_work(&ep->link_training, 0); + return 0; } @@ -475,6 +480,8 @@ static void rockchip_pcie_ep_stop(struct pci_epc *epc) struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; + cancel_delayed_work_sync(&ep->link_training); + /* Stop link training and disable configuration */ rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_DISABLE | @@ -482,8 +489,77 @@ static void rockchip_pcie_ep_stop(struct pci_epc *epc) PCIE_CLIENT_CONFIG); } +static void rockchip_pcie_ep_retrain_link(struct rockchip_pcie *rockchip) +{ + u32 status; + + status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_LCS); + status |= PCI_EXP_LNKCTL_RL; + rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_LCS); +} + +static bool rockchip_pcie_ep_link_up(struct rockchip_pcie *rockchip) +{ + u32 val = rockchip_pcie_read(rockchip, PCIE_CLIENT_BASIC_STATUS1); + + return PCIE_LINK_UP(val); +} + +static void rockchip_pcie_ep_link_training(struct work_struct *work) +{ + struct rockchip_pcie_ep *ep = + container_of(work, struct rockchip_pcie_ep, link_training.work); + struct rockchip_pcie *rockchip = &ep->rockchip; + struct device *dev = rockchip->dev; + u32 val; + int ret; + + /* Enable Gen1 training and wait for its completion */ + ret = readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL, + val, PCIE_LINK_TRAINING_DONE(val), 50, + LINK_TRAIN_TIMEOUT); + if (ret) + goto again; + + /* Make sure that the link is up */ + ret = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1, + val, PCIE_LINK_UP(val), 50, + LINK_TRAIN_TIMEOUT); + if (ret) + goto again; + + /* Check the current speed */ + val = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL); + if (!PCIE_LINK_IS_GEN2(val) && rockchip->link_gen == 2) { + /* Enable retrain for gen2 */ + rockchip_pcie_ep_retrain_link(rockchip); + readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL, + val, PCIE_LINK_IS_GEN2(val), 50, + LINK_TRAIN_TIMEOUT); + } + + /* Check again that the link is up */ + if (!rockchip_pcie_ep_link_up(rockchip)) + goto again; + + val = rockchip_pcie_read(rockchip, PCIE_CLIENT_BASIC_STATUS0); + dev_info(dev, + "Link UP (Negociated speed: %sGT/s, width: x%lu)\n", + (val & PCIE_CLIENT_NEG_LINK_SPEED) ? "5" : "2.5", + ((val & PCIE_CLIENT_NEG_LINK_WIDTH_MASK) >> + PCIE_CLIENT_NEG_LINK_WIDTH_SHIFT) << 1); + + /* Notify the function */ + pci_epc_linkup(ep->epc); + + return; + +again: + schedule_delayed_work(&ep->link_training, msecs_to_jiffies(5)); +} + static const struct pci_epc_features rockchip_pcie_epc_features = { - .linkup_notifier = false, + .linkup_notifier = true, .msi_capable = true, .msix_capable = false, .align = ROCKCHIP_PCIE_AT_SIZE_ALIGN, @@ -644,6 +720,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) rockchip = &ep->rockchip; rockchip->is_rc = false; rockchip->dev = dev; + INIT_DELAYED_WORK(&ep->link_training, rockchip_pcie_ep_link_training); epc = devm_pci_epc_create(dev, &rockchip_pcie_epc_ops); if (IS_ERR(epc)) { diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h index 0263f158ee8d..3963b7097a91 100644 --- a/drivers/pci/controller/pcie-rockchip.h +++ b/drivers/pci/controller/pcie-rockchip.h @@ -26,6 +26,7 @@ #define MAX_LANE_NUM 4 #define MAX_REGION_LIMIT 32 #define MIN_EP_APERTURE 28 +#define LINK_TRAIN_TIMEOUT (5000 * USEC_PER_MSEC) #define PCIE_CLIENT_BASE 0x0 #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) @@ -50,6 +51,10 @@ #define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0) #define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18 #define PCIE_CLIENT_DEBUG_LTSSM_L2 0x19 +#define PCIE_CLIENT_BASIC_STATUS0 (PCIE_CLIENT_BASE + 0x44) +#define PCIE_CLIENT_NEG_LINK_WIDTH_MASK GENMASK(7, 6) +#define PCIE_CLIENT_NEG_LINK_WIDTH_SHIFT 6 +#define PCIE_CLIENT_NEG_LINK_SPEED BIT(5) #define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48) #define PCIE_CLIENT_LINK_STATUS_UP 0x00300000 #define PCIE_CLIENT_LINK_STATUS_MASK 0x00300000 @@ -87,6 +92,8 @@ #define PCIE_CORE_CTRL_MGMT_BASE 0x900000 #define PCIE_CORE_CTRL (PCIE_CORE_CTRL_MGMT_BASE + 0x000) +#define PCIE_CORE_PL_CONF_LS_MASK 0x00000001 +#define PCIE_CORE_PL_CONF_LS_READY 0x00000001 #define PCIE_CORE_PL_CONF_SPEED_5G 0x00000008 #define PCIE_CORE_PL_CONF_SPEED_MASK 0x00000018 #define PCIE_CORE_PL_CONF_LANE_MASK 0x00000006 @@ -144,6 +151,7 @@ #define PCIE_RC_CONFIG_BASE 0xa00000 #define PCIE_EP_CONFIG_BASE 0xa00000 #define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) +#define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) #define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) #define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 @@ -155,6 +163,7 @@ #define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc) #define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10) #define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0) +#define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c) #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) @@ -192,6 +201,8 @@ #define ROCKCHIP_VENDOR_ID 0x1d87 #define PCIE_LINK_IS_L2(x) \ (((x) & PCIE_CLIENT_DEBUG_LTSSM_MASK) == PCIE_CLIENT_DEBUG_LTSSM_L2) +#define PCIE_LINK_TRAINING_DONE(x) \ + (((x) & PCIE_CORE_PL_CONF_LS_MASK) == PCIE_CORE_PL_CONF_LS_READY) #define PCIE_LINK_UP(x) \ (((x) & PCIE_CLIENT_LINK_STATUS_MASK) == PCIE_CLIENT_LINK_STATUS_UP) #define PCIE_LINK_IS_GEN2(x) \
The Rockchip rk339 technical reference manual describe the endpoint mode link training process clearly and states that: Insure link training completion and success by observing link_st field in PCIe Client BASIC_STATUS1 register change to 2'b11. If both side support PCIe Gen2 speed, re-train can be Initiated by asserting the Retrain Link field in Link Control and Status Register. The software should insure the BASIC_STATUS0[negotiated_speed] changes to "1", that indicates re-train to Gen2 successfully. This procedure is very similar to what is done for the root-port mode in rockchip_pcie_host_init_port(). Implement this link training procedure for the endpoint mode as well. Given that the rk3399 SoC does not have an interrupt signaling link status changes, training is implemented as a delayed work which is rescheduled until the link training completes or the endpoint controller is stopped. The link training work is first scheduled in rockchip_pcie_ep_start() when the endpoint function is started. Link training completion is signaled to the function using pci_epc_linkup(). Accordingly, the linkup_notifier field of the rockchip pci_epc_features structure is changed to true. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> --- drivers/pci/controller/pcie-rockchip-ep.c | 79 ++++++++++++++++++++++- drivers/pci/controller/pcie-rockchip.h | 11 ++++ 2 files changed, 89 insertions(+), 1 deletion(-)