summaryrefslogtreecommitdiff
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorEric Farman <farman@linux.ibm.com>2020-12-02 19:37:24 +0100
committerHeiko Carstens <hca@linux.ibm.com>2023-01-09 14:34:08 +0100
commit6a6dc14ac84733cf5864a7cf9f5b3e43f6a79be8 (patch)
tree7a9ea8fb6919d9d0414be728428ea4313dfa45c0 /drivers/s390/cio
parent667e5dbabf2bb790640525cff7d563cf88eb3e61 (diff)
vfio/ccw: calculate number of IDAWs regardless of format
The idal_nr_words() routine works well for 4K IDAWs, but lost its ability to handle the old 2K formats with the removal of 31-bit builds in commit 5a79859ae0f3 ("s390: remove 31 bit support"). Since there's nothing preventing a guest from generating this IDAW format, let's re-introduce the math for them and use both when calculating the number of IDAWs based on the bits specified in the ORB. Signed-off-by: Eric Farman <farman@linux.ibm.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index fbb46bec3174..6a2c6ee83807 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -502,6 +502,13 @@ static int ccwchain_fetch_tic(struct ccw1 *ccw,
*
* @ccw: The Channel Command Word being translated
* @cp: Channel Program being processed
+ *
+ * The ORB is examined, since it specifies what IDAWs could actually be
+ * used by any CCW in the channel program, regardless of whether or not
+ * the CCW actually does. An ORB that does not specify Format-2-IDAW
+ * Control could still contain a CCW with an IDAL, which would be
+ * Format-1 and thus only move 2K with each IDAW. Thus all CCWs within
+ * the channel program must follow the same size requirements.
*/
static int ccw_count_idaws(struct ccw1 *ccw,
struct channel_program *cp)
@@ -533,6 +540,15 @@ static int ccw_count_idaws(struct ccw1 *ccw,
iova = ccw->cda;
}
+ /* Format-1 IDAWs operate on 2K each */
+ if (!cp->orb.cmd.c64)
+ return idal_2k_nr_words((void *)iova, bytes);
+
+ /* Using the 2K variant of Format-2 IDAWs? */
+ if (cp->orb.cmd.i2k)
+ return idal_2k_nr_words((void *)iova, bytes);
+
+ /* The 'usual' case is 4K Format-2 IDAWs */
return idal_nr_words((void *)iova, bytes);
}