mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
Fixes in vfio-ccw for older and newer issues.
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAl0u7PoSHGNvaHVja0By ZWRoYXQuY29tAAoJEN7Pa5PG8C+vFnYP/ApM5PuQyTheK3PB2sNpOwRlhkSq4jlC uO3Eym6UXxwE2CSiUJHDpvjwyVMa8W0OrGbf5b5+PbIARbV5+mlKODaYS8PVICGz y/zftL/dtCcq7NvZXu46BFnNtvf0gkkFxM2JNuQGcO6J6sq/Rc8kGOt0Mz5MCQDR 9sjgPiajfBACoLPYpLSegvF01JSEI2AqD6ZPogpwtDWF+2CByYsbw5qXcmp7vZcf IYyYidxtG5PbK9xFOs5Df04dSEwvSA1MiP8VJflWGJrsE1r58dBhG69lEq3w8xt9 pDMMcixgG1ws6ZvD94xleYJvc5GtSpusR+1avLg7nYA5dLqG663Ksj83I0kE3BC0 OnPE81nPvMCo1BrgzdHvWnQS/3u3ZcCuvWJ7pW3s192l/JVI0D9YZoASnTmqlyiO SO5RyHZs00DWPjzHllXFQE0SxehbMneC+VrL4iqpYGiMiYQOQHPYM5N8x4AqIOwL uXIW0ndqQgD0C2WGtzLObsfAo0ZT51zGpdm4nHNEwmaEpV2vPXTeYZjF+5ugo79Z 7vYjWeCytkDQWc3mPyLH1foEHqKFyH41XV5GCnvVfUp7dT2KK7Na1aFGERbg5U0S DpuVJXmqtT7EV0aGn7PKyiIsZIOuQLSVfjfuUwMy64udfhFG2CzX/T9B1QQ+vjar i4aAeKsNoqUC =u+4J -----END PGP SIGNATURE----- Merge tag 'vfio-ccw-20190717-2' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/vfio-ccw into fixes Fixes in vfio-ccw for older and newer issues.
This commit is contained in:
commit
eed3419760
@ -180,6 +180,13 @@ The process of how these work together.
|
||||
add it to an iommu_group and a vfio_group. Then we could pass through
|
||||
the mdev to a guest.
|
||||
|
||||
|
||||
VFIO-CCW Regions
|
||||
----------------
|
||||
|
||||
The vfio-ccw driver exposes MMIO regions to accept requests from and return
|
||||
results to userspace.
|
||||
|
||||
vfio-ccw I/O region
|
||||
-------------------
|
||||
|
||||
@ -205,6 +212,25 @@ irb_area stores the I/O result.
|
||||
|
||||
ret_code stores a return code for each access of the region.
|
||||
|
||||
This region is always available.
|
||||
|
||||
vfio-ccw cmd region
|
||||
-------------------
|
||||
|
||||
The vfio-ccw cmd region is used to accept asynchronous instructions
|
||||
from userspace::
|
||||
|
||||
#define VFIO_CCW_ASYNC_CMD_HSCH (1 << 0)
|
||||
#define VFIO_CCW_ASYNC_CMD_CSCH (1 << 1)
|
||||
struct ccw_cmd_region {
|
||||
__u32 command;
|
||||
__u32 ret_code;
|
||||
} __packed;
|
||||
|
||||
This region is exposed via region type VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD.
|
||||
|
||||
Currently, CLEAR SUBCHANNEL and HALT SUBCHANNEL use this region.
|
||||
|
||||
vfio-ccw operation details
|
||||
--------------------------
|
||||
|
||||
@ -306,9 +332,8 @@ Together with the corresponding work in QEMU, we can bring the passed
|
||||
through DASD/ECKD device online in a guest now and use it as a block
|
||||
device.
|
||||
|
||||
While the current code allows the guest to start channel programs via
|
||||
START SUBCHANNEL, support for HALT SUBCHANNEL or CLEAR SUBCHANNEL is
|
||||
not yet implemented.
|
||||
The current code allows the guest to start channel programs via
|
||||
START SUBCHANNEL, and to issue HALT SUBCHANNEL and CLEAR SUBCHANNEL.
|
||||
|
||||
vfio-ccw supports classic (command mode) channel I/O only. Transport
|
||||
mode (HPF) is not supported.
|
||||
|
@ -72,8 +72,10 @@ static int pfn_array_alloc(struct pfn_array *pa, u64 iova, unsigned int len)
|
||||
sizeof(*pa->pa_iova_pfn) +
|
||||
sizeof(*pa->pa_pfn),
|
||||
GFP_KERNEL);
|
||||
if (unlikely(!pa->pa_iova_pfn))
|
||||
if (unlikely(!pa->pa_iova_pfn)) {
|
||||
pa->pa_nr = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
pa->pa_pfn = pa->pa_iova_pfn + pa->pa_nr;
|
||||
|
||||
pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
|
||||
@ -421,7 +423,7 @@ static int ccwchain_loop_tic(struct ccwchain *chain,
|
||||
static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
|
||||
{
|
||||
struct ccwchain *chain;
|
||||
int len;
|
||||
int len, ret;
|
||||
|
||||
/* Copy 2K (the most we support today) of possible CCWs */
|
||||
len = copy_from_iova(cp->mdev, cp->guest_cp, cda,
|
||||
@ -448,7 +450,12 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
|
||||
memcpy(chain->ch_ccw, cp->guest_cp, len * sizeof(struct ccw1));
|
||||
|
||||
/* Loop for tics on this new chain. */
|
||||
return ccwchain_loop_tic(chain, cp);
|
||||
ret = ccwchain_loop_tic(chain, cp);
|
||||
|
||||
if (ret)
|
||||
ccwchain_free(chain);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Loop for TICs. */
|
||||
@ -642,17 +649,16 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
|
||||
|
||||
/* Build a ccwchain for the first CCW segment */
|
||||
ret = ccwchain_handle_ccw(orb->cmd.cpa, cp);
|
||||
if (ret)
|
||||
cp_free(cp);
|
||||
|
||||
/* It is safe to force: if not set but idals used
|
||||
* ccwchain_calc_length returns an error.
|
||||
*/
|
||||
cp->orb.cmd.c64 = 1;
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
cp->initialized = true;
|
||||
|
||||
/* It is safe to force: if it was not set but idals used
|
||||
* ccwchain_calc_length would have returned an error.
|
||||
*/
|
||||
cp->orb.cmd.c64 = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
|
||||
(SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
|
||||
if (scsw_is_solicited(&irb->scsw)) {
|
||||
cp_update_scsw(&private->cp, &irb->scsw);
|
||||
if (is_final)
|
||||
if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
|
||||
cp_free(&private->cp);
|
||||
}
|
||||
mutex_lock(&private->io_mutex);
|
||||
|
Loading…
Reference in New Issue
Block a user