mbox series

[v2,0/3] Add Gen4 equalization and margining settings

Message ID 20240320071527.13443-1-quic_schintav@quicinc.com
Headers show
Series Add Gen4 equalization and margining settings | expand

Message

Shashank Babu Chinta Venkata March 20, 2024, 7:14 a.m. UTC
Add Gen4 specific equalization and rx margining settings. These
settings are inline with respective PHY settings for Gen4
operation. 

In addition, current QCOM EP and RC drivers do not share common
codebase which would result in code duplication. Hence, adding
common files for code reusability among RC and EP drivers.

v1 -> v2:
- Capitilized commit message to be inline with history 
- Dropped stubs from header file.
- Moved Designware specific register offsets and masks to
  pcie-designware.h header file.
- Applied settings based on bus data rate rather than link generation.
- Addressed review comments from Bjorn and Frank.

Shashank Babu Chinta Venkata (3):
  PCI: qcom: Refactor common code
  PCI: qcom: Add equalization settings for gen4
  PCI: qcom: Add rx margining settings for gen4

 drivers/pci/controller/dwc/Kconfig           |   5 +
 drivers/pci/controller/dwc/Makefile          |   1 +
 drivers/pci/controller/dwc/pcie-designware.h |  38 +++++
 drivers/pci/controller/dwc/pcie-qcom-cmn.c   | 152 +++++++++++++++++++
 drivers/pci/controller/dwc/pcie-qcom-cmn.h   |  28 ++++
 drivers/pci/controller/dwc/pcie-qcom-ep.c    |  44 ++----
 drivers/pci/controller/dwc/pcie-qcom.c       |  72 ++-------
 7 files changed, 246 insertions(+), 94 deletions(-)
 create mode 100644 drivers/pci/controller/dwc/pcie-qcom-cmn.c
 create mode 100644 drivers/pci/controller/dwc/pcie-qcom-cmn.h

Comments

Konrad Dybcio March 23, 2024, 12:24 a.m. UTC | #1
On 20.03.2024 08:14, Shashank Babu Chinta Venkata wrote:
> Add rx margining settings for gen4 operation.

Why are these necessary? What do they change?

> 
> Signed-off-by: Shashank Babu Chinta Venkata <quic_schintav@quicinc.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware.h | 23 +++++++++++++
>  drivers/pci/controller/dwc/pcie-qcom-cmn.c   | 35 ++++++++++++++++++++
>  drivers/pci/controller/dwc/pcie-qcom-cmn.h   | 11 +++++-
>  drivers/pci/controller/dwc/pcie-qcom-ep.c    |  4 ++-
>  drivers/pci/controller/dwc/pcie-qcom.c       |  4 ++-
>  5 files changed, 74 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 064744bfe35a..ce1c5f9c406a 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -206,6 +206,29 @@
>  
>  #define PCIE_PL_CHK_REG_ERR_ADDR			0xB28
>  
> +/*
> + * GEN4 lane margining register definitions
> + */
> +#define GEN4_LANE_MARGINING_1_OFF		0xb80
> +#define MARGINING_MAX_VOLTAGE_OFFSET_MASK	GENMASK(29, 24)
> +#define MARGINING_NUM_VOLTAGE_STEPS_MASK	GENMASK(22, 16)
> +#define MARGINING_MAX_TIMING_OFFSET_MASK	GENMASK(13, 8)
> +#define MARGINING_NUM_TIMING_STEPS_MASK		GENMASK(5, 0)
> +#define MARGINING_MAX_VOLTAGE_OFFSET_SHIFT	24
> +#define MARGINING_NUM_VOLTAGE_STEPS_SHIFT	16
> +#define MARGINING_MAX_TIMING_OFFSET_SHIFT	8
> +
> +#define GEN4_LANE_MARGINING_2_OFF		0xb84

The file

drivers/accel/habanalabs/include/gaudi2/asic_reg/pcie_dbi_regs.h

defines registers with exactly the same names at exacly the same offsets.

If this is a DWC-common thing, it should go to DWC-common code.

Konrad
Johan Hovold July 12, 2024, 8:12 a.m. UTC | #2
On Wed, Mar 20, 2024 at 12:14:45AM -0700, Shashank Babu Chinta Venkata wrote:
> Refactor common code from RC(Root Complex) and EP(End Point)

Please add a space before the open parentheses above, these are not
function calls.

> drivers and move them to a common repository. This acts as placeholder
> for common source code for both drivers avoiding duplication.
> 
> Signed-off-by: Shashank Babu Chinta Venkata <quic_schintav@quicinc.com>

> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-qcom-cmn.c
> @@ -0,0 +1,81 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2014-2015, 2020 The Linux Foundation. All rights reserved.
> + * Copyright 2015, 2021 Linaro Limited.
> + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + *
> + */
> +
> +#include <linux/debugfs.h>

Not needed.

> +#include <linux/pci.h>
> +#include <linux/interconnect.h>
> +
> +#include "../../pci.h"
> +#include "pcie-designware.h"
> +#include "pcie-qcom-cmn.h"
> +
> +#define QCOM_PCIE_LINK_SPEED_TO_BW(speed) \
> +		Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_link_speed[speed]))
> +
> +int qcom_pcie_cmn_icc_get_resource(struct dw_pcie *pci, struct icc_path *icc_mem)
> +{
> +	if (IS_ERR(pci))
> +		return PTR_ERR(pci);

Not needed.

> +
> +	icc_mem = devm_of_icc_get(pci->dev, "pcie-mem");
> +	if (IS_ERR(icc_mem))
> +		return PTR_ERR(icc_mem);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pcie_cmn_icc_get_resource);

So this series was clearly never tested properly as the above function
will leave the driver's icc_mem path uninitialised. You're passing in a
NULL pointer by value and then update your local variable, which
obviously has no effect for the caller.

This means that all later icc operation become no-ops, which crashes
machine like the Lenovo ThinkPad X13s and the x1e80100 CRD that depends
on having a non-zero vote before enabling clocks at probe.

How did this go unnoticed? I can only assume you did not test this
series (in isolation) before posting?

> +int qcom_pcie_cmn_icc_init(struct dw_pcie *pci, struct icc_path *icc_mem)
> +{
> +	int ret;
> +
> +	if (IS_ERR(pci))
> +		return PTR_ERR(pci);
> +
> +	if (IS_ERR(icc_mem))
> +		return PTR_ERR(icc_mem);

Neither is needed.

> +
> +	/*
> +	 * Some Qualcomm platforms require interconnect bandwidth constraints
> +	 * to be set before enabling interconnect clocks.
> +	 *
> +	 * Set an initial peak bandwidth corresponding to single-lane Gen 1
> +	 * for the pcie-mem path.
> +	 */

I'm not sure about hiding this away in a separate compilation unit. The
above comments makes sense in the driver, where it's easy to see that
the icc is initialised and the vote added before enabling clocks.

Also these helpers are so small it may not even be worth trying to
refactor them (all).

> +	ret = icc_set_bw(icc_mem, 0, QCOM_PCIE_LINK_SPEED_TO_BW(1));
> +	if (ret) {
> +		dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pcie_cmn_icc_init);

> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-qcom-cmn.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2014-2015, 2020 The Linux Foundation. All rights reserved.
> + * Copyright 2015, 2021 Linaro Limited.
> + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/pci.h>
> +#include "../../pci.h"
> +#include "pcie-designware.h"
> +

Compile guards missing.

> +int qcom_pcie_cmn_icc_get_resource(struct dw_pcie *pci, struct icc_path *icc_mem);
> +int qcom_pcie_cmn_icc_init(struct dw_pcie *pci, struct icc_path *icc_mem);
> +void qcom_pcie_cmn_icc_update(struct dw_pcie *pci, struct icc_path *icc_mem);

Johan