diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 5509b224c2ec..a5eec4410421 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -219,6 +219,7 @@ int clp_query_pci_fn(struct zpci_dev *zdev); int clp_enable_fh(struct zpci_dev *, u8); int clp_disable_fh(struct zpci_dev *); int clp_get_state(u32 fid, enum zpci_state *state); +int clp_refresh_fh(u32 fid); /* UID */ void update_uid_checking(bool new); diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 4eafa8160184..6be5ee320194 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -674,12 +674,25 @@ int zpci_enable_device(struct zpci_dev *zdev) int zpci_disable_device(struct zpci_dev *zdev) { + int cc, rc = 0; + zpci_dma_exit_device(zdev); /* * The zPCI function may already be disabled by the platform, this is * detected in clp_disable_fh() which becomes a no-op. */ - return clp_disable_fh(zdev) ? -EIO : 0; + cc = clp_disable_fh(zdev); + if (cc == CLP_RC_SETPCIFN_ALRDY) { + pr_info("Disabling PCI function %08x had no effect as it was already disabled\n", + zdev->fid); + /* Function is already disabled - update handle */ + rc = clp_refresh_fh(zdev->fid); + if (!rc) + rc = -EINVAL; + } else if (cc) { + rc = -EIO; + } + return rc; } /** diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 0a0e8b8293be..04147f28d159 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -212,7 +212,6 @@ int clp_query_pci_fn(struct zpci_dev *zdev) return rc; } -static int clp_refresh_fh(u32 fid); /** * clp_set_pci_fn() - Execute a command on a PCI function * @zdev: Function that will be affected @@ -251,9 +250,6 @@ static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command) if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) { zdev->fh = rrb->response.fh; - } else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY) { - /* Function is already in desired state - update handle */ - rc = clp_refresh_fh(zdev->fid); } else { zpci_err("Set PCI FN:\n"); zpci_err_clp(rrb->response.hdr.rsp, rc); @@ -409,7 +405,7 @@ static void __clp_refresh_fh(struct clp_fh_list_entry *entry, void *data) /* * Refresh the function handle of the function matching @fid */ -static int clp_refresh_fh(u32 fid) +int clp_refresh_fh(u32 fid) { struct clp_req_rsp_list_pci *rrb; int rc;