Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 623bd44d authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

s390/pci: improve pci hotplug



PCI hotplug events basically notify about the new state of a
function. Unfortunately some hypervisors implement hotplug
events in a way where it is not clear what the new state of
the function should be.

Use clp_get_state to find the current state of the function
and handle accordingly.

Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 783684f1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ extern const struct attribute_group *zpci_attr_groups[];
----------------------------------------------------------------------------- */
/* Base stuff */
int zpci_create_device(struct zpci_dev *);
void zpci_remove_device(struct zpci_dev *zdev);
int zpci_enable_device(struct zpci_dev *);
int zpci_disable_device(struct zpci_dev *);
void zpci_stop_device(struct zpci_dev *);
+9 −0
Original line number Diff line number Diff line
@@ -855,6 +855,15 @@ void zpci_stop_device(struct zpci_dev *zdev)
}
EXPORT_SYMBOL_GPL(zpci_stop_device);

void zpci_remove_device(struct zpci_dev *zdev)
{
	if (!zdev->bus)
		return;

	pci_stop_root_bus(zdev->bus);
	pci_remove_root_bus(zdev->bus);
}

int zpci_report_error(struct pci_dev *pdev,
		      struct zpci_report_error_header *report)
{
+11 −3
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
{
	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
	struct pci_dev *pdev = NULL;
	enum zpci_state state;
	int ret;

	if (zdev)
@@ -108,6 +109,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
			clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
		break;
	case 0x0303: /* Deconfiguration requested */
		if (!zdev)
			break;
		if (pdev)
			pci_stop_and_remove_bus_device_locked(pdev);

@@ -121,7 +124,9 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
			zdev->state = ZPCI_FN_STATE_STANDBY;

		break;
	case 0x0304: /* Configured -> Standby */
	case 0x0304: /* Configured -> Standby|Reserved */
		if (!zdev)
			break;
		if (pdev) {
			/* Give the driver a hint that the function is
			 * already unusable. */
@@ -132,6 +137,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
		zdev->fh = ccdf->fh;
		zpci_disable_device(zdev);
		zdev->state = ZPCI_FN_STATE_STANDBY;
		if (!clp_get_state(ccdf->fid, &state) &&
		    state == ZPCI_FN_STATE_RESERVED) {
			zpci_remove_device(zdev);
		}
		break;
	case 0x0306: /* 0x308 or 0x302 for multiple devices */
		clp_rescan_pci_devices();
@@ -139,8 +148,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
	case 0x0308: /* Standby -> Reserved */
		if (!zdev)
			break;
		pci_stop_root_bus(zdev->bus);
		pci_remove_root_bus(zdev->bus);
		zpci_remove_device(zdev);
		break;
	default:
		break;