Commit 6bfea141 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-5.12-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 updates from Heiko Carstens:

 - disable preemption when accessing local per-cpu variables in the new
   counter set driver

 - fix by a factor of four increased steal time due to missing
   cputime_to_nsecs() conversion

 - fix PCI device structure leak

* tag 's390-5.12-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/pci: fix leak of PCI device structure
  s390/vtime: fix increased steal time accounting
  s390/cpumf: disable preemption when accessing per-cpu variable
parents 278924cb 0b13525c
...@@ -202,7 +202,7 @@ extern unsigned int s390_pci_no_rid; ...@@ -202,7 +202,7 @@ extern unsigned int s390_pci_no_rid;
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */
/* Base stuff */ /* Base stuff */
int zpci_create_device(u32 fid, u32 fh, enum zpci_state state); int zpci_create_device(u32 fid, u32 fh, enum zpci_state state);
void zpci_remove_device(struct zpci_dev *zdev); void zpci_remove_device(struct zpci_dev *zdev, bool set_error);
int zpci_enable_device(struct zpci_dev *); int zpci_enable_device(struct zpci_dev *);
int zpci_disable_device(struct zpci_dev *); int zpci_disable_device(struct zpci_dev *);
int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64); int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
......
...@@ -968,7 +968,7 @@ static int cf_diag_all_start(void) ...@@ -968,7 +968,7 @@ static int cf_diag_all_start(void)
*/ */
static size_t cf_diag_needspace(unsigned int sets) static size_t cf_diag_needspace(unsigned int sets)
{ {
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); struct cpu_cf_events *cpuhw = get_cpu_ptr(&cpu_cf_events);
size_t bytes = 0; size_t bytes = 0;
int i; int i;
...@@ -984,6 +984,7 @@ static size_t cf_diag_needspace(unsigned int sets) ...@@ -984,6 +984,7 @@ static size_t cf_diag_needspace(unsigned int sets)
sizeof(((struct s390_ctrset_cpudata *)0)->no_sets)); sizeof(((struct s390_ctrset_cpudata *)0)->no_sets));
debug_sprintf_event(cf_diag_dbg, 5, "%s bytes %ld\n", __func__, debug_sprintf_event(cf_diag_dbg, 5, "%s bytes %ld\n", __func__,
bytes); bytes);
put_cpu_ptr(&cpu_cf_events);
return bytes; return bytes;
} }
......
...@@ -214,7 +214,7 @@ void vtime_flush(struct task_struct *tsk) ...@@ -214,7 +214,7 @@ void vtime_flush(struct task_struct *tsk)
avg_steal = S390_lowcore.avg_steal_timer / 2; avg_steal = S390_lowcore.avg_steal_timer / 2;
if ((s64) steal > 0) { if ((s64) steal > 0) {
S390_lowcore.steal_timer = 0; S390_lowcore.steal_timer = 0;
account_steal_time(steal); account_steal_time(cputime_to_nsecs(steal));
avg_steal += steal; avg_steal += steal;
} }
S390_lowcore.avg_steal_timer = avg_steal; S390_lowcore.avg_steal_timer = avg_steal;
......
...@@ -682,16 +682,36 @@ int zpci_disable_device(struct zpci_dev *zdev) ...@@ -682,16 +682,36 @@ int zpci_disable_device(struct zpci_dev *zdev)
} }
EXPORT_SYMBOL_GPL(zpci_disable_device); EXPORT_SYMBOL_GPL(zpci_disable_device);
void zpci_remove_device(struct zpci_dev *zdev) /* zpci_remove_device - Removes the given zdev from the PCI core
* @zdev: the zdev to be removed from the PCI core
* @set_error: if true the device's error state is set to permanent failure
*
* Sets a zPCI device to a configured but offline state; the zPCI
* device is still accessible through its hotplug slot and the zPCI
* API but is removed from the common code PCI bus, making it
* no longer available to drivers.
*/
void zpci_remove_device(struct zpci_dev *zdev, bool set_error)
{ {
struct zpci_bus *zbus = zdev->zbus; struct zpci_bus *zbus = zdev->zbus;
struct pci_dev *pdev; struct pci_dev *pdev;
if (!zdev->zbus->bus)
return;
pdev = pci_get_slot(zbus->bus, zdev->devfn); pdev = pci_get_slot(zbus->bus, zdev->devfn);
if (pdev) { if (pdev) {
if (pdev->is_virtfn) if (set_error)
return zpci_iov_remove_virtfn(pdev, zdev->vfn); pdev->error_state = pci_channel_io_perm_failure;
if (pdev->is_virtfn) {
zpci_iov_remove_virtfn(pdev, zdev->vfn);
/* balance pci_get_slot */
pci_dev_put(pdev);
return;
}
pci_stop_and_remove_bus_device_locked(pdev); pci_stop_and_remove_bus_device_locked(pdev);
/* balance pci_get_slot */
pci_dev_put(pdev);
} }
} }
...@@ -765,7 +785,7 @@ void zpci_release_device(struct kref *kref) ...@@ -765,7 +785,7 @@ void zpci_release_device(struct kref *kref)
struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref); struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
if (zdev->zbus->bus) if (zdev->zbus->bus)
zpci_remove_device(zdev); zpci_remove_device(zdev, false);
switch (zdev->state) { switch (zdev->state) {
case ZPCI_FN_STATE_ONLINE: case ZPCI_FN_STATE_ONLINE:
......
...@@ -76,13 +76,10 @@ void zpci_event_error(void *data) ...@@ -76,13 +76,10 @@ void zpci_event_error(void *data)
static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
{ {
struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
struct pci_dev *pdev = NULL;
enum zpci_state state; enum zpci_state state;
struct pci_dev *pdev;
int ret; int ret;
if (zdev && zdev->zbus->bus)
pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
zpci_err("avail CCDF:\n"); zpci_err("avail CCDF:\n");
zpci_err_hex(ccdf, sizeof(*ccdf)); zpci_err_hex(ccdf, sizeof(*ccdf));
...@@ -124,8 +121,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) ...@@ -124,8 +121,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
case 0x0303: /* Deconfiguration requested */ case 0x0303: /* Deconfiguration requested */
if (!zdev) if (!zdev)
break; break;
if (pdev) zpci_remove_device(zdev, false);
zpci_remove_device(zdev);
ret = zpci_disable_device(zdev); ret = zpci_disable_device(zdev);
if (ret) if (ret)
...@@ -140,12 +136,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) ...@@ -140,12 +136,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
case 0x0304: /* Configured -> Standby|Reserved */ case 0x0304: /* Configured -> Standby|Reserved */
if (!zdev) if (!zdev)
break; break;
if (pdev) {
/* Give the driver a hint that the function is /* Give the driver a hint that the function is
* already unusable. */ * already unusable.
pdev->error_state = pci_channel_io_perm_failure; */
zpci_remove_device(zdev); zpci_remove_device(zdev, true);
}
zdev->fh = ccdf->fh; zdev->fh = ccdf->fh;
zpci_disable_device(zdev); zpci_disable_device(zdev);
......
...@@ -93,8 +93,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) ...@@ -93,8 +93,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
pci_dev_put(pdev); pci_dev_put(pdev);
return -EBUSY; return -EBUSY;
} }
pci_dev_put(pdev);
zpci_remove_device(zdev); zpci_remove_device(zdev, false);
rc = zpci_disable_device(zdev); rc = zpci_disable_device(zdev);
if (rc) if (rc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment