提交 93d16d81 编写于 作者: Y Yi Min Zhao 提交者: Cornelia Huck

s390x/pci: make hot-unplug handler smoother

The current implementation of hot-unplug handler is abrupt. Any pci
operation will be just rejected if pci device is unconfigured. Thus a
pci device can not be reset or destroyed in a right, smooth and safe
way.

Improve this as follows:
- Notify the guest via a HP_EVENT_DECONFIGURE_REQUEST(0x303) event in
  the unplug handler, giving it a chance to deconfigure the device via
  sclp and allowing us to continue hot-unplug afterwards.
- Set up a timer that will generate the HP_EVENT_CONFIGURE_TO_STBRES
  (0x304) event as before if the guest did not react after an adequate
  time.
Signed-off-by: NYi Min Zhao <zyimin@linux.vnet.ibm.com>
Reviewed-by: NPierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: NCornelia Huck <cornelia.huck@de.ibm.com>
上级 cdd85eb2
...@@ -192,6 +192,10 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) ...@@ -192,6 +192,10 @@ void s390_pci_sclp_deconfigure(SCCB *sccb)
} }
pbdev->state = ZPCI_FS_STANDBY; pbdev->state = ZPCI_FS_STANDBY;
rc = SCLP_RC_NORMAL_COMPLETION; rc = SCLP_RC_NORMAL_COMPLETION;
if (pbdev->release_timer) {
qdev_unplug(DEVICE(pbdev->pdev), NULL);
}
} }
out: out:
psccb->header.response_code = cpu_to_be16(rc); psccb->header.response_code = cpu_to_be16(rc);
...@@ -679,6 +683,23 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, ...@@ -679,6 +683,23 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
} }
} }
static void s390_pcihost_timer_cb(void *opaque)
{
S390PCIBusDevice *pbdev = opaque;
if (pbdev->summary_ind) {
pci_dereg_irqs(pbdev);
}
if (pbdev->iommu_enabled) {
pci_dereg_ioat(pbdev);
}
pbdev->state = ZPCI_FS_STANDBY;
s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES,
pbdev->fh, pbdev->fid);
qdev_unplug(DEVICE(pbdev), NULL);
}
static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
...@@ -712,8 +733,20 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, ...@@ -712,8 +733,20 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
case ZPCI_FS_STANDBY: case ZPCI_FS_STANDBY:
break; break;
default: default:
s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES, s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST,
pbdev->fh, pbdev->fid); pbdev->fh, pbdev->fid);
pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
s390_pcihost_timer_cb,
pbdev);
timer_mod(pbdev->release_timer,
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT);
return;
}
if (pbdev->release_timer && timer_pending(pbdev->release_timer)) {
timer_del(pbdev->release_timer);
timer_free(pbdev->release_timer);
pbdev->release_timer = NULL;
} }
s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define ZPCI_MAX_UID 0xffff #define ZPCI_MAX_UID 0xffff
#define UID_UNDEFINED 0 #define UID_UNDEFINED 0
#define UID_CHECKING_ENABLED 0x01 #define UID_CHECKING_ENABLED 0x01
#define HOT_UNPLUG_TIMEOUT (NANOSECONDS_PER_SECOND * 60 * 5)
#define S390_PCI_HOST_BRIDGE(obj) \ #define S390_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE) OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE)
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
#define HP_EVENT_TO_CONFIGURED 0x0301 #define HP_EVENT_TO_CONFIGURED 0x0301
#define HP_EVENT_RESERVED_TO_STANDBY 0x0302 #define HP_EVENT_RESERVED_TO_STANDBY 0x0302
#define HP_EVENT_DECONFIGURE_REQUEST 0x0303
#define HP_EVENT_CONFIGURED_TO_STBRES 0x0304 #define HP_EVENT_CONFIGURED_TO_STBRES 0x0304
#define HP_EVENT_STANDBY_TO_RESERVED 0x0308 #define HP_EVENT_STANDBY_TO_RESERVED 0x0308
...@@ -283,6 +285,7 @@ typedef struct S390PCIBusDevice { ...@@ -283,6 +285,7 @@ typedef struct S390PCIBusDevice {
MemoryRegion iommu_mr; MemoryRegion iommu_mr;
IndAddr *summary_ind; IndAddr *summary_ind;
IndAddr *indicator; IndAddr *indicator;
QEMUTimer *release_timer;
} S390PCIBusDevice; } S390PCIBusDevice;
typedef struct S390PCIBus { typedef struct S390PCIBus {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册