Skip to content

Commit

Permalink
s390/pci: fix misleading rc in clp_set_pci_fn()
Browse files Browse the repository at this point in the history
[ Upstream commit f7addcd ]

Currently clp_set_pci_fn() always returns 0 as long as the CLP request
itself succeeds even if the operation itself returns a response code
other than CLP_RC_OK or CLP_RC_SETPCIFN_ALRDY. This is highly misleading
because calling code assumes that a zero rc means that the operation was
successful.

Fix this by returning the response code or cc on failure with the
exception of the special handling for CLP_RC_SETPCIFN_ALRDY. Also let's
not assume that the returned function handle for CLP_RC_SETPCIFN_ALRDY
is 0, we don't need it anyway.

Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
niklas88 authored and gregkh committed Sep 15, 2021
1 parent 72d9005 commit 17c565f
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 20 deletions.
7 changes: 4 additions & 3 deletions arch/s390/pci/pci.c
Expand Up @@ -661,9 +661,10 @@ int zpci_enable_device(struct zpci_dev *zdev)
{
int rc;

rc = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES);
if (rc)
if (clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES)) {
rc = -EIO;
goto out;
}

rc = zpci_dma_init_device(zdev);
if (rc)
Expand All @@ -684,7 +685,7 @@ int zpci_disable_device(struct zpci_dev *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);
return clp_disable_fh(zdev) ? -EIO : 0;
}

/**
Expand Down
33 changes: 16 additions & 17 deletions arch/s390/pci/pci_clp.c
Expand Up @@ -213,15 +213,19 @@ int clp_query_pci_fn(struct zpci_dev *zdev)
}

static int clp_refresh_fh(u32 fid);
/*
* Enable/Disable a given PCI function and update its function handle if
* necessary
/**
* clp_set_pci_fn() - Execute a command on a PCI function
* @zdev: Function that will be affected
* @nr_dma_as: DMA address space number
* @command: The command code to execute
*
* Returns: 0 on success, < 0 for Linux errors (e.g. -ENOMEM), and
* > 0 for non-success platform responses
*/
static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
{
struct clp_req_rsp_set_pci *rrb;
int rc, retries = 100;
u32 fid = zdev->fid;

rrb = clp_alloc_block(GFP_KERNEL);
if (!rrb)
Expand All @@ -245,17 +249,16 @@ static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
}
} while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);

if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
zpci_err("Set PCI FN:\n");
zpci_err_clp(rrb->response.hdr.rsp, rc);
}

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 &&
rrb->response.fh == 0) {
} else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY) {
/* Function is already in desired state - update handle */
rc = clp_refresh_fh(fid);
rc = clp_refresh_fh(zdev->fid);
} else {
zpci_err("Set PCI FN:\n");
zpci_err_clp(rrb->response.hdr.rsp, rc);
if (!rc)
rc = rrb->response.hdr.rsp;
}
clp_free_block(rrb);
return rc;
Expand Down Expand Up @@ -301,17 +304,13 @@ int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)

rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
if (rc)
goto out;

if (zpci_use_mio(zdev)) {
if (!rc && zpci_use_mio(zdev)) {
rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_MIO);
zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n",
zdev->fid, zdev->fh, rc);
if (rc)
clp_disable_fh(zdev);
}
out:
return rc;
}

Expand Down

0 comments on commit 17c565f

Please sign in to comment.