s390 fixes for 5.9-rc2
- Couple of fixes for storage key handling relevant for debugging. - Add cond_resched into potentially slow subchannels scanning loop. - Fixes for PF/VF linking and to ignore stale PCI configuration request events. -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE3QHqV+H2a8xAv27vjYWKoQLXFBgFAl9BDkAACgkQjYWKoQLX FBhF3gf+KmVa7/Eb9Z0jE6dS1op5mggBASIMk7wr/enwSBQ7bLa42iGQPP9b7lWu 5FTLifmrelVIAadDjFU7+vfBYY4CtTg+KvaajlJeAe4QScND+KN3G7LkT+kRnqxy n6evcW19yKKos2I+cVlqL0QxOXQBsQFM7wmpOrf373OBRqDyJAkV1DjcLopPZr8I eMaKyhlLMoyxaoXkddk+RC417aIkuL900WaUMmdEkREIhawWbuyKoWqypk76CXih Jtxgi1nSCX7nSVUnrLHLl4xPdpBziQ3iqccliddysNEbLsaqrdWbiP8XAPBrI8na WxbFFOmHXTcTzhqpUDgyMv10fQtkBg== =bgLc -----END PGP SIGNATURE----- Merge tag 's390-5.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux Pull s390 fixes from Vasily Gorbik: - a couple of fixes for storage key handling relevant for debugging - add cond_resched into potentially slow subchannels scanning loop - fixes for PF/VF linking and to ignore stale PCI configuration request events * tag 's390-5.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/pci: fix PF/VF linking on hot plug s390/pci: re-introduce zpci_remove_device() s390/pci: fix zpci_bus_link_virtfn() s390/ptrace: fix storage key handling s390/runtime_instrumentation: fix storage key handling s390/pci: ignore stale configuration request event s390/cio: add cond_resched() in the slow_eval_known_fn() loop
This commit is contained in:
commit
d57ce84004
|
@ -1268,7 +1268,6 @@ static bool is_ri_cb_valid(struct runtime_instr_cb *cb)
|
|||
cb->pc == 1 &&
|
||||
cb->qc == 0 &&
|
||||
cb->reserved2 == 0 &&
|
||||
cb->key == PAGE_DEFAULT_KEY &&
|
||||
cb->reserved3 == 0 &&
|
||||
cb->reserved4 == 0 &&
|
||||
cb->reserved5 == 0 &&
|
||||
|
@ -1330,7 +1329,11 @@ static int s390_runtime_instr_set(struct task_struct *target,
|
|||
kfree(data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override access key in any case, since user space should
|
||||
* not be able to set it, nor should it care about it.
|
||||
*/
|
||||
ri_cb.key = PAGE_DEFAULT_KEY >> 4;
|
||||
preempt_disable();
|
||||
if (!target->thread.ri_cb)
|
||||
target->thread.ri_cb = data;
|
||||
|
|
|
@ -57,7 +57,7 @@ static void init_runtime_instr_cb(struct runtime_instr_cb *cb)
|
|||
cb->k = 1;
|
||||
cb->ps = 1;
|
||||
cb->pc = 1;
|
||||
cb->key = PAGE_DEFAULT_KEY;
|
||||
cb->key = PAGE_DEFAULT_KEY >> 4;
|
||||
cb->v = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -672,6 +672,19 @@ int zpci_disable_device(struct zpci_dev *zdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(zpci_disable_device);
|
||||
|
||||
void zpci_remove_device(struct zpci_dev *zdev)
|
||||
{
|
||||
struct zpci_bus *zbus = zdev->zbus;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
pdev = pci_get_slot(zbus->bus, zdev->devfn);
|
||||
if (pdev) {
|
||||
if (pdev->is_virtfn)
|
||||
return zpci_remove_virtfn(pdev, zdev->vfn);
|
||||
pci_stop_and_remove_bus_device_locked(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
int zpci_create_device(struct zpci_dev *zdev)
|
||||
{
|
||||
int rc;
|
||||
|
@ -716,13 +729,8 @@ void zpci_release_device(struct kref *kref)
|
|||
{
|
||||
struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
|
||||
|
||||
if (zdev->zbus->bus) {
|
||||
struct pci_dev *pdev;
|
||||
|
||||
pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
|
||||
if (pdev)
|
||||
pci_stop_and_remove_bus_device_locked(pdev);
|
||||
}
|
||||
if (zdev->zbus->bus)
|
||||
zpci_remove_device(zdev);
|
||||
|
||||
switch (zdev->state) {
|
||||
case ZPCI_FN_STATE_ONLINE:
|
||||
|
|
|
@ -132,13 +132,14 @@ static int zpci_bus_link_virtfn(struct pci_dev *pdev,
|
|||
{
|
||||
int rc;
|
||||
|
||||
virtfn->physfn = pci_dev_get(pdev);
|
||||
rc = pci_iov_sysfs_link(pdev, virtfn, vfid);
|
||||
if (rc) {
|
||||
pci_dev_put(pdev);
|
||||
virtfn->physfn = NULL;
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
virtfn->is_virtfn = 1;
|
||||
virtfn->multifunction = 0;
|
||||
virtfn->physfn = pci_dev_get(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -151,9 +152,9 @@ static int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
|
|||
int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/
|
||||
int rc = 0;
|
||||
|
||||
virtfn->is_virtfn = 1;
|
||||
virtfn->multifunction = 0;
|
||||
WARN_ON(vfid < 0);
|
||||
if (!zbus->multifunction)
|
||||
return 0;
|
||||
|
||||
/* If the parent PF for the given VF is also configured in the
|
||||
* instance, it must be on the same zbus.
|
||||
* We can then identify the parent PF by checking what
|
||||
|
@ -165,11 +166,17 @@ static int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
|
|||
zdev = zbus->function[i];
|
||||
if (zdev && zdev->is_physfn) {
|
||||
pdev = pci_get_slot(zbus->bus, zdev->devfn);
|
||||
if (!pdev)
|
||||
continue;
|
||||
cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
|
||||
if (cand_devfn == virtfn->devfn) {
|
||||
rc = zpci_bus_link_virtfn(pdev, virtfn, vfid);
|
||||
/* balance pci_get_slot() */
|
||||
pci_dev_put(pdev);
|
||||
break;
|
||||
}
|
||||
/* balance pci_get_slot() */
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
@ -178,12 +185,23 @@ static int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
|
|||
static inline int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
|
||||
struct pci_dev *virtfn, int vfn)
|
||||
{
|
||||
virtfn->is_virtfn = 1;
|
||||
virtfn->multifunction = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void pcibios_bus_add_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
|
||||
/*
|
||||
* With pdev->no_vf_scan the common PCI probing code does not
|
||||
* perform PF/VF linking.
|
||||
*/
|
||||
if (zdev->vfn)
|
||||
zpci_bus_setup_virtfn(zdev->zbus, pdev, zdev->vfn);
|
||||
|
||||
}
|
||||
|
||||
static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
|
@ -214,20 +232,10 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
|
|||
}
|
||||
|
||||
pdev = pci_scan_single_device(bus, zdev->devfn);
|
||||
if (pdev) {
|
||||
if (!zdev->is_physfn) {
|
||||
rc = zpci_bus_setup_virtfn(zbus, pdev, zdev->vfn);
|
||||
if (rc)
|
||||
goto failed_with_pdev;
|
||||
}
|
||||
if (pdev)
|
||||
pci_bus_add_device(pdev);
|
||||
}
|
||||
return 0;
|
||||
|
||||
failed_with_pdev:
|
||||
pci_stop_and_remove_bus_device(pdev);
|
||||
pci_dev_put(pdev);
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zpci_bus_add_devices(struct zpci_bus *zbus)
|
||||
|
|
|
@ -29,3 +29,16 @@ static inline struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus,
|
|||
|
||||
return (devfn >= ZPCI_FUNCTIONS_PER_BUS) ? NULL : zbus->function[devfn];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static inline void zpci_remove_virtfn(struct pci_dev *pdev, int vfn)
|
||||
{
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
/* Linux' vfid's start at 0 vfn at 1 */
|
||||
pci_iov_remove_virtfn(pdev->physfn, vfn - 1);
|
||||
pci_unlock_rescan_remove();
|
||||
}
|
||||
#else /* CONFIG_PCI_IOV */
|
||||
static inline void zpci_remove_virtfn(struct pci_dev *pdev, int vfn) {}
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
|
|
@ -92,6 +92,9 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
|
|||
ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 1);
|
||||
break;
|
||||
}
|
||||
/* the configuration request may be stale */
|
||||
if (zdev->state != ZPCI_FN_STATE_STANDBY)
|
||||
break;
|
||||
zdev->fh = ccdf->fh;
|
||||
zdev->state = ZPCI_FN_STATE_CONFIGURED;
|
||||
ret = zpci_enable_device(zdev);
|
||||
|
@ -118,7 +121,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
|
|||
if (!zdev)
|
||||
break;
|
||||
if (pdev)
|
||||
pci_stop_and_remove_bus_device_locked(pdev);
|
||||
zpci_remove_device(zdev);
|
||||
|
||||
ret = zpci_disable_device(zdev);
|
||||
if (ret)
|
||||
|
@ -137,7 +140,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
|
|||
/* Give the driver a hint that the function is
|
||||
* already unusable. */
|
||||
pdev->error_state = pci_channel_io_perm_failure;
|
||||
pci_stop_and_remove_bus_device_locked(pdev);
|
||||
zpci_remove_device(zdev);
|
||||
}
|
||||
|
||||
zdev->state = ZPCI_FN_STATE_STANDBY;
|
||||
|
|
|
@ -83,21 +83,19 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
|
|||
struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
|
||||
hotplug_slot);
|
||||
struct pci_dev *pdev;
|
||||
struct zpci_bus *zbus = zdev->zbus;
|
||||
int rc;
|
||||
|
||||
if (!zpci_fn_configured(zdev->state))
|
||||
return -EIO;
|
||||
|
||||
pdev = pci_get_slot(zbus->bus, zdev->devfn);
|
||||
if (pdev) {
|
||||
if (pci_num_vf(pdev))
|
||||
return -EBUSY;
|
||||
|
||||
pci_stop_and_remove_bus_device_locked(pdev);
|
||||
pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
|
||||
if (pdev && pci_num_vf(pdev)) {
|
||||
pci_dev_put(pdev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
zpci_remove_device(zdev);
|
||||
|
||||
rc = zpci_disable_device(zdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
|
|
@ -677,6 +677,11 @@ static int slow_eval_known_fn(struct subchannel *sch, void *data)
|
|||
rc = css_evaluate_known_subchannel(sch, 1);
|
||||
if (rc == -EAGAIN)
|
||||
css_schedule_eval(sch->schid);
|
||||
/*
|
||||
* The loop might take long time for platforms with lots of
|
||||
* known devices. Allow scheduling here.
|
||||
*/
|
||||
cond_resched();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue