[PATCH v5 00/13] PCI: dwc: Refactor register access with dw_pcie_*_dword helper

Hans Zhang posted 13 patches 3 months, 2 weeks ago
drivers/pci/controller/dwc/pci-dra7xx.c       |  10 +-
drivers/pci/controller/dwc/pci-imx6.c         |  26 ++--
drivers/pci/controller/dwc/pci-meson.c        |  22 ++--
drivers/pci/controller/dwc/pcie-armada8k.c    |  43 +++---
drivers/pci/controller/dwc/pcie-bt1.c         |   5 +-
.../controller/dwc/pcie-designware-debugfs.c  |  48 +++----
.../pci/controller/dwc/pcie-designware-ep.c   |  19 ++-
.../pci/controller/dwc/pcie-designware-host.c |  26 ++--
drivers/pci/controller/dwc/pcie-designware.c  |  75 +++++------
drivers/pci/controller/dwc/pcie-designware.h  |  37 ++++--
drivers/pci/controller/dwc/pcie-dw-rockchip.c |   7 +-
drivers/pci/controller/dwc/pcie-fu740.c       |   5 +-
drivers/pci/controller/dwc/pcie-qcom-common.c |  62 +++++----
drivers/pci/controller/dwc/pcie-qcom-ep.c     |  14 +-
drivers/pci/controller/dwc/pcie-rcar-gen4.c   |  23 ++--
drivers/pci/controller/dwc/pcie-tegra194.c    | 122 +++++++-----------
16 files changed, 223 insertions(+), 321 deletions(-)
[PATCH v5 00/13] PCI: dwc: Refactor register access with dw_pcie_*_dword helper
Posted by Hans Zhang 3 months, 2 weeks ago
From: Hans Zhang <hans.zhang@cixtech.com>

Register bit manipulation in DesignWare PCIe controllers currently
uses repetitive read-modify-write sequences across multiple drivers.
This pattern leads to code duplication and increases maintenance
complexity as each driver implements similar logic with minor variations.

This series introduces dw_pcie_*_dword() to centralize atomic
register modification. The helper performs read-clear-set-write operations
in a single function, replacing open-coded implementations. Subsequent
patches refactor individual drivers to use this helper, eliminating
redundant code and ensuring consistent bit handling.

The change reduces overall code size by ~350 lines while improving
maintainability. Each controller driver is updated in a separate
patch to preserve bisectability and simplify review.

---
Hi all,

At the beginning, two patches were made, 0001*.patch, and the others were
one patch. After consideration, I still split the patches. If splitting
is not necessary, I will recombine them into two patches in future
versions.


Changes for v5:
https://patchwork.kernel.org/project/linux-pci/patch/20250813044531.180411-1-18255117159@163.com/

- According to Mani's reminder, following Lukas' previous suggestion for
  another patch, add the dw_pcie_clear/set_dword API.
- Fix the error pointed out by Mani.
- Use the dw_pcie_clear/set_dword API for some of the calls in other patches.

Changes for v4:
https://patchwork.kernel.org/project/linux-pci/cover/20250626145040.14180-1-18255117159@163.com/

- Rebase to v6.17-rc1

Changes for v3:
https://patchwork.kernel.org/project/linux-pci/patch/20250618152112.1010147-1-18255117159@163.com/

- patch 0002: s/u32 val = 0;/u32 val; (pcie-designware-debugfs.c -> set_event_number())
- patch 0013: Remove several val = 0. (Mani)
- patch 0013: s/PCIE_PL_CHK_REG_CONTROL_STATUS/0. (Error in copying the code.) (Mani)

Changes for v2:
- Re-send it in the company environment so that the entire patch series is in the 00/13 cover letter. (Bjorn)
- Modify the subject. (Bjorn and Frank)
---

Hans Zhang (13):
  PCI: dwc: Add dw_pcie_*_dword() for register bit manipulation
  PCI: dwc: Refactor code by using dw_pcie_*_dword()
  PCI: dra7xx: Refactor code by using dw_pcie_*_dword()
  PCI: imx6: Refactor code by using dw_pcie_*_dword()
  PCI: meson: Refactor code by using dw_pcie_*_dword()
  PCI: armada8k: Refactor code by using dw_pcie_*_dword()
  PCI: bt1: Refactor code by using dw_pcie_*_dword()
  PCI: dw-rockchip: Refactor code by using dw_pcie_*_dword()
  PCI: fu740: Refactor code by using dw_pcie_*_dword()
  PCI: qcom: Refactor code by using dw_pcie_*_dword()
  PCI: qcom-ep: Refactor code by using dw_pcie_*_dword()
  PCI: rcar-gen4: Refactor code by using dw_pcie_*_dword()
  PCI: tegra194: Refactor code by using dw_pcie_*_dword()

 drivers/pci/controller/dwc/pci-dra7xx.c       |  10 +-
 drivers/pci/controller/dwc/pci-imx6.c         |  26 ++--
 drivers/pci/controller/dwc/pci-meson.c        |  22 ++--
 drivers/pci/controller/dwc/pcie-armada8k.c    |  43 +++---
 drivers/pci/controller/dwc/pcie-bt1.c         |   5 +-
 .../controller/dwc/pcie-designware-debugfs.c  |  48 +++----
 .../pci/controller/dwc/pcie-designware-ep.c   |  19 ++-
 .../pci/controller/dwc/pcie-designware-host.c |  26 ++--
 drivers/pci/controller/dwc/pcie-designware.c  |  75 +++++------
 drivers/pci/controller/dwc/pcie-designware.h  |  37 ++++--
 drivers/pci/controller/dwc/pcie-dw-rockchip.c |   7 +-
 drivers/pci/controller/dwc/pcie-fu740.c       |   5 +-
 drivers/pci/controller/dwc/pcie-qcom-common.c |  62 +++++----
 drivers/pci/controller/dwc/pcie-qcom-ep.c     |  14 +-
 drivers/pci/controller/dwc/pcie-rcar-gen4.c   |  23 ++--
 drivers/pci/controller/dwc/pcie-tegra194.c    | 122 +++++++-----------
 16 files changed, 223 insertions(+), 321 deletions(-)

-- 
2.49.0
Re: [PATCH v5 00/13] PCI: dwc: Refactor register access with dw_pcie_*_dword helper
Posted by Rob Herring 3 months, 2 weeks ago
On Thu, Aug 28, 2025 at 9:00 AM Hans Zhang <18255117159@163.com> wrote:
>
> From: Hans Zhang <hans.zhang@cixtech.com>
>
> Register bit manipulation in DesignWare PCIe controllers currently
> uses repetitive read-modify-write sequences across multiple drivers.
> This pattern leads to code duplication and increases maintenance
> complexity as each driver implements similar logic with minor variations.
>
> This series introduces dw_pcie_*_dword() to centralize atomic
> register modification. The helper performs read-clear-set-write operations
> in a single function, replacing open-coded implementations. Subsequent
> patches refactor individual drivers to use this helper, eliminating
> redundant code and ensuring consistent bit handling.
>
> The change reduces overall code size by ~350 lines while improving
> maintainability. Each controller driver is updated in a separate
> patch to preserve bisectability and simplify review.

If RMW functions are an improvement, then they should go in io.h. I
don't think they are because they obfuscate the exact register
modifications and the possible need for locking. With common API,
anyone that understands kernel APIs will know what's going on. With a
driver specific API, then you have to go lookup what the API does
exactly. So I don't think this is an improvement.

Rob
Re: [PATCH v5 00/13] PCI: dwc: Refactor register access with dw_pcie_*_dword helper
Posted by Hans Zhang 3 months, 1 week ago

On 2025/8/29 04:44, Rob Herring wrote:
> On Thu, Aug 28, 2025 at 9:00 AM Hans Zhang <18255117159@163.com> wrote:
>>
>> From: Hans Zhang <hans.zhang@cixtech.com>
>>
>> Register bit manipulation in DesignWare PCIe controllers currently
>> uses repetitive read-modify-write sequences across multiple drivers.
>> This pattern leads to code duplication and increases maintenance
>> complexity as each driver implements similar logic with minor variations.
>>
>> This series introduces dw_pcie_*_dword() to centralize atomic
>> register modification. The helper performs read-clear-set-write operations
>> in a single function, replacing open-coded implementations. Subsequent
>> patches refactor individual drivers to use this helper, eliminating
>> redundant code and ensuring consistent bit handling.
>>
>> The change reduces overall code size by ~350 lines while improving
>> maintainability. Each controller driver is updated in a separate
>> patch to preserve bisectability and simplify review.
> 
> If RMW functions are an improvement, then they should go in io.h. I
> don't think they are because they obfuscate the exact register
> modifications and the possible need for locking. With common API,
> anyone that understands kernel APIs will know what's going on. With a
> driver specific API, then you have to go lookup what the API does
> exactly. So I don't think this is an improvement.
> 
> Rob

Dear Rob,

Thank you very much for your reply.

My initial idea was to simplify the logic we wrote a lot of RMW under 
the DWC driver. Then I saw that there were similar well-handled codes in 
the linux kernel, so I came to do some cleaning work.


drivers/pci/access.c
int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
					u32 clear, u32 set)
{
	int ret;
	u32 val;

	ret = pcie_capability_read_dword(dev, pos, &val);
	if (ret)
		return ret;

	val &= ~clear;
	val |= set;
	return pcie_capability_write_dword(dev, pos, val);
}
EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);


include/linux/pci.h
static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos,
					    u32 set)
{
	return pcie_capability_clear_and_set_dword(dev, pos, 0, set);
}

static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos,
					      u32 clear)
{
	return pcie_capability_clear_and_set_dword(dev, pos, clear, 0);
}



And the subsequent introduced API: Personally, I think they are very 
valuable for reference. Of course, it depends on the final opinions of 
the maintainer and all of you.

drivers/pci/access.c
void pci_clear_and_set_config_dword(const struct pci_dev *dev, int pos,
				    u32 clear, u32 set)
{
	u32 val;

	pci_read_config_dword(dev, pos, &val);
	val &= ~clear;
	val |= set;
	pci_write_config_dword(dev, pos, val);
}
EXPORT_SYMBOL(pci_clear_and_set_config_dword);



Best regards,
Hans