Message ID | 20220129043837.172126-2-marek.vasut@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Lorenzo Pieralisi |
Headers | show |
Series | [v4,1/2] PCI: rcar: Finish transition to L1 state in rcar_pcie_config_access() | expand |
Hi, I love your patch! Yet something to improve: [auto build test ERROR on helgaas-pci/next] [also build test ERROR on v5.17-rc2 next-20220131] [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] url: https://github.com/0day-ci/linux/commits/marek-vasut-gmail-com/PCI-rcar-Finish-transition-to-L1-state-in-rcar_pcie_config_access/20220129-124033 base: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next config: arm-randconfig-c002-20220201 (https://download.01.org/0day-ci/archive/20220201/202202012118.qgdNW3Ra-lkp@intel.com/config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 6b1e844b69f15bb7dffaf9365cd2b355d2eb7579) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install arm cross compiling tool for clang build # apt-get install binutils-arm-linux-gnueabi # https://github.com/0day-ci/linux/commit/88177fcc2d6d4acbea59c90839882f70b7b774a1 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review marek-vasut-gmail-com/PCI-rcar-Finish-transition-to-L1-state-in-rcar_pcie_config_access/20220129-124033 git checkout 88177fcc2d6d4acbea59c90839882f70b7b774a1 # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash drivers/pci/controller/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/pci/controller/pcie-rcar-host.c:133:5: warning: no previous prototype for function 'rcar_pci_write_reg_workaround' [-Wmissing-prototypes] int rcar_pci_write_reg_workaround(struct rcar_pcie *pcie, u32 val, unsigned int reg) ^ drivers/pci/controller/pcie-rcar-host.c:133:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int rcar_pci_write_reg_workaround(struct rcar_pcie *pcie, u32 val, unsigned int reg) ^ static drivers/pci/controller/pcie-rcar-host.c:146:5: warning: no previous prototype for function 'rcar_pci_read_reg_workaround' [-Wmissing-prototypes] int rcar_pci_read_reg_workaround(struct rcar_pcie *pcie, u32 *val, unsigned int reg) ^ drivers/pci/controller/pcie-rcar-host.c:146:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int rcar_pci_read_reg_workaround(struct rcar_pcie *pcie, u32 *val, unsigned int reg) ^ static >> drivers/pci/controller/pcie-rcar-host.c:138:3: error: instruction requires: data-barriers __rcar_pci_rw_reg_workaround("str") ^ drivers/pci/controller/pcie-rcar-host.c:120:4: note: expanded from macro '__rcar_pci_rw_reg_workaround' "2: isb\n" \ ^ <inline asm>:2:4: note: instantiated into assembly here 2: isb ^ drivers/pci/controller/pcie-rcar-host.c:151:3: error: instruction requires: data-barriers __rcar_pci_rw_reg_workaround("ldr") ^ drivers/pci/controller/pcie-rcar-host.c:120:4: note: expanded from macro '__rcar_pci_rw_reg_workaround' "2: isb\n" \ ^ <inline asm>:2:4: note: instantiated into assembly here 2: isb ^ >> drivers/pci/controller/pcie-rcar-host.c:138:3: error: instruction requires: data-barriers __rcar_pci_rw_reg_workaround("str") ^ drivers/pci/controller/pcie-rcar-host.c:120:4: note: expanded from macro '__rcar_pci_rw_reg_workaround' "2: isb\n" \ ^ <inline asm>:2:4: note: instantiated into assembly here 2: isb ^ drivers/pci/controller/pcie-rcar-host.c:151:3: error: instruction requires: data-barriers __rcar_pci_rw_reg_workaround("ldr") ^ drivers/pci/controller/pcie-rcar-host.c:120:4: note: expanded from macro '__rcar_pci_rw_reg_workaround' "2: isb\n" \ ^ <inline asm>:2:4: note: instantiated into assembly here 2: isb ^ 2 warnings and 4 errors generated. vim +138 drivers/pci/controller/pcie-rcar-host.c 132 133 int rcar_pci_write_reg_workaround(struct rcar_pcie *pcie, u32 val, unsigned int reg) 134 { 135 int error = PCIBIOS_SUCCESSFUL; 136 #ifdef CONFIG_ARM 137 asm volatile( > 138 __rcar_pci_rw_reg_workaround("str") 139 : "+r"(error):"r"(val), "r"(pcie->base + reg) : "memory"); 140 #else 141 rcar_pci_write_reg(pcie, val, reg); 142 #endif 143 return error; 144 } 145 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Sat, Jan 29, 2022 at 05:38:37AM +0100, marek.vasut@gmail.com wrote: > From: Marek Vasut <marek.vasut+renesas@gmail.com> > > In case the controller is transitioning to L1 in rcar_pcie_config_access(), > any read/write access to PCIECDR triggers asynchronous external abort. This > is because the transition to L1 link state must be manually finished by the > driver. The PCIe IP can transition back from L1 state to L0 on its own. > > The current asynchronous external abort hook implementation restarts > the instruction which finally triggered the fault, which can be a > different instruction than the read/write instruction which started > the faulting access. Usually the instruction which finally triggers > the fault is one which has some data dependency on the result of the > read/write. In case of read, the read value after fixup is undefined, > while a read value of faulting read should be all Fs. Since the kernel test robot found something to fix, maybe you could replace "all Fs" with PCI_ERROR_RESPONSE at the same time. > It is possible to enforce the fault using 'isb' instruction placed > right after the read/write instruction which started the faulting > access. Add custom register accessors which perform the read/write > followed immediately by 'isb'. > > This way, the fault always happens on the 'isb' and in case of read, > which is located one instruction before the 'isb', it is now possible > to fix up the return value of the read in the asynchronous external > abort hook and make that read return all Fs. And here. Bjorn
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c index 7d38a9c50093..529259daee21 100644 --- a/drivers/pci/controller/pcie-rcar-host.c +++ b/drivers/pci/controller/pcie-rcar-host.c @@ -114,6 +114,51 @@ static u32 rcar_read_conf(struct rcar_pcie *pcie, int where) return val >> shift; } +#ifdef CONFIG_ARM +#define __rcar_pci_rw_reg_workaround(instr) \ + "1: " instr " %1, [%2]\n" \ + "2: isb\n" \ + "3: .pushsection .text.fixup,\"ax\"\n" \ + " .align 2\n" \ + "4: mov %0, #" __stringify(PCIBIOS_SET_FAILED) "\n" \ + " b 3b\n" \ + " .popsection\n" \ + " .pushsection __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 4b\n" \ + " .long 2b, 4b\n" \ + " .popsection\n" +#endif + +int rcar_pci_write_reg_workaround(struct rcar_pcie *pcie, u32 val, unsigned int reg) +{ + int error = PCIBIOS_SUCCESSFUL; +#ifdef CONFIG_ARM + asm volatile( + __rcar_pci_rw_reg_workaround("str") + : "+r"(error):"r"(val), "r"(pcie->base + reg) : "memory"); +#else + rcar_pci_write_reg(pcie, val, reg); +#endif + return error; +} + +int rcar_pci_read_reg_workaround(struct rcar_pcie *pcie, u32 *val, unsigned int reg) +{ + int error = PCIBIOS_SUCCESSFUL; +#ifdef CONFIG_ARM + asm volatile( + __rcar_pci_rw_reg_workaround("ldr") + : "+r"(error), "=r"(*val) : "r"(pcie->base + reg) : "memory"); + + if (error != PCIBIOS_SUCCESSFUL) + PCI_SET_ERROR_RESPONSE(val); +#else + *val = rcar_pci_read_reg(pcie, reg); +#endif + return error; +} + /* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ static int rcar_pcie_config_access(struct rcar_pcie_host *host, unsigned char access_type, struct pci_bus *bus, @@ -185,14 +230,14 @@ static int rcar_pcie_config_access(struct rcar_pcie_host *host, return PCIBIOS_DEVICE_NOT_FOUND; if (access_type == RCAR_PCI_ACCESS_READ) - *data = rcar_pci_read_reg(pcie, PCIECDR); + ret = rcar_pci_read_reg_workaround(pcie, data, PCIECDR); else - rcar_pci_write_reg(pcie, *data, PCIECDR); + ret = rcar_pci_write_reg_workaround(pcie, *data, PCIECDR); /* Disable the configuration access */ rcar_pci_write_reg(pcie, 0, PCIECCTLR); - return PCIBIOS_SUCCESSFUL; + return ret; } static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, @@ -1097,7 +1142,7 @@ static struct platform_driver rcar_pcie_driver = { static int rcar_pcie_aarch32_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { - return !!rcar_pcie_wakeup(pcie_dev, pcie_base); + return !fixup_exception(regs); } static const struct of_device_id rcar_pcie_abort_handler_of_match[] __initconst = {