Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

s390/pci: Handle futile config accesses of disabled devices directly

On s390 PCI busses and slots with multiple functions may have holes
because PCI functions are passed-through by the hypervisor on a per
function basis and some functions may be in standby or reserved. This
fact is indicated by returning true from the
hypervisor_isolated_pci_functions() helper and triggers common code to
scan all possible devfn values. Via pci_scan_single_device() this in
turn causes config reads for the device and vendor IDs, even for PCI
functions which are in standby and thereofore disabled.

So far these futile config reads, as well as potentially writes, which
can never succeed were handled by the PCI load/store instructions
themselves. This works as the platform just returns an error for
a disabled and thus not usable function handle. It does cause spamming
of error logs and additional overhead though.

Instead check if the used function handle is enabled in zpci_cfg_load()
and zpci_cfg_write() and if not enable directly return -ENODEV. Also
refactor zpci_cfg_load() and zpci_cfg_store() slightly to accommodate
the new logic while meeting modern kernel style guidelines.

Cc: stable@vger.kernel.org
Fixes: a50297cf8235 ("s390/pci: separate zbus creation from scanning")
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>

authored by

Niklas Schnelle and committed by
Heiko Carstens
84d875e6 86302ddf

+17 -8
+17 -8
arch/s390/pci/pci.c
··· 231 231 static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) 232 232 { 233 233 u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); 234 + int rc = -ENODEV; 234 235 u64 data; 235 - int rc; 236 + 237 + if (!zdev_enabled(zdev)) 238 + goto out_err; 236 239 237 240 rc = __zpci_load(&data, req, offset); 238 - if (!rc) { 239 - data = le64_to_cpu((__force __le64) data); 240 - data >>= (8 - len) * 8; 241 - *val = (u32) data; 242 - } else 243 - *val = 0xffffffff; 241 + if (rc) 242 + goto out_err; 243 + data = le64_to_cpu((__force __le64)data); 244 + data >>= (8 - len) * 8; 245 + *val = (u32)data; 246 + return 0; 247 + 248 + out_err: 249 + PCI_SET_ERROR_RESPONSE(val); 244 250 return rc; 245 251 } 246 252 247 253 static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len) 248 254 { 249 255 u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); 256 + int rc = -ENODEV; 250 257 u64 data = val; 251 - int rc; 258 + 259 + if (!zdev_enabled(zdev)) 260 + return rc; 252 261 253 262 data <<= (8 - len) * 8; 254 263 data = (__force u64) cpu_to_le64(data);