Commit 2a8ed7ef authored by Alex Williamson's avatar Alex Williamson

Merge branches 'v5.20/vfio/spapr_tce-unused-arg-v1',...

Merge branches 'v5.20/vfio/spapr_tce-unused-arg-v1', 'v5.20/vfio/comment-typo-v1' and 'v5.20/vfio/vfio-ccw-rework-v4' into v5.20/vfio/next
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
*/ */
#include <linux/vfio.h> #include <linux/vfio.h>
#include <linux/mdev.h>
#include "vfio_ccw_private.h" #include "vfio_ccw_private.h"
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mdev.h> #include <linux/mdev.h>
#include <asm/isc.h> #include <asm/isc.h>
...@@ -42,13 +41,6 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch) ...@@ -42,13 +41,6 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch)
DECLARE_COMPLETION_ONSTACK(completion); DECLARE_COMPLETION_ONSTACK(completion);
int iretry, ret = 0; int iretry, ret = 0;
spin_lock_irq(sch->lock);
if (!sch->schib.pmcw.ena)
goto out_unlock;
ret = cio_disable_subchannel(sch);
if (ret != -EBUSY)
goto out_unlock;
iretry = 255; iretry = 255;
do { do {
...@@ -75,9 +67,7 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch) ...@@ -75,9 +67,7 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch)
spin_lock_irq(sch->lock); spin_lock_irq(sch->lock);
ret = cio_disable_subchannel(sch); ret = cio_disable_subchannel(sch);
} while (ret == -EBUSY); } while (ret == -EBUSY);
out_unlock:
private->state = VFIO_CCW_STATE_NOT_OPER;
spin_unlock_irq(sch->lock);
return ret; return ret;
} }
...@@ -107,9 +97,10 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work) ...@@ -107,9 +97,10 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
/* /*
* Reset to IDLE only if processing of a channel program * Reset to IDLE only if processing of a channel program
* has finished. Do not overwrite a possible processing * has finished. Do not overwrite a possible processing
* state if the final interrupt was for HSCH or CSCH. * state if the interrupt was unsolicited, or if the final
* interrupt was for HSCH or CSCH.
*/ */
if (private->mdev && cp_is_finished) if (cp_is_finished)
private->state = VFIO_CCW_STATE_IDLE; private->state = VFIO_CCW_STATE_IDLE;
if (private->io_trigger) if (private->io_trigger)
...@@ -147,7 +138,7 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) ...@@ -147,7 +138,7 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch)
private->sch = sch; private->sch = sch;
mutex_init(&private->io_mutex); mutex_init(&private->io_mutex);
private->state = VFIO_CCW_STATE_NOT_OPER; private->state = VFIO_CCW_STATE_STANDBY;
INIT_LIST_HEAD(&private->crw); INIT_LIST_HEAD(&private->crw);
INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
...@@ -231,26 +222,15 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) ...@@ -231,26 +222,15 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
dev_set_drvdata(&sch->dev, private); dev_set_drvdata(&sch->dev, private);
spin_lock_irq(sch->lock); ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
sch->isc = VFIO_CCW_ISC;
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
spin_unlock_irq(sch->lock);
if (ret) if (ret)
goto out_free; goto out_free;
private->state = VFIO_CCW_STATE_STANDBY;
ret = vfio_ccw_mdev_reg(sch);
if (ret)
goto out_disable;
VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n", VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n",
sch->schid.cssid, sch->schid.ssid, sch->schid.cssid, sch->schid.ssid,
sch->schid.sch_no); sch->schid.sch_no);
return 0; return 0;
out_disable:
cio_disable_subchannel(sch);
out_free: out_free:
dev_set_drvdata(&sch->dev, NULL); dev_set_drvdata(&sch->dev, NULL);
vfio_ccw_free_private(private); vfio_ccw_free_private(private);
...@@ -261,8 +241,8 @@ static void vfio_ccw_sch_remove(struct subchannel *sch) ...@@ -261,8 +241,8 @@ static void vfio_ccw_sch_remove(struct subchannel *sch)
{ {
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
vfio_ccw_sch_quiesce(sch); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
vfio_ccw_mdev_unreg(sch); mdev_unregister_device(&sch->dev);
dev_set_drvdata(&sch->dev, NULL); dev_set_drvdata(&sch->dev, NULL);
...@@ -275,7 +255,10 @@ static void vfio_ccw_sch_remove(struct subchannel *sch) ...@@ -275,7 +255,10 @@ static void vfio_ccw_sch_remove(struct subchannel *sch)
static void vfio_ccw_sch_shutdown(struct subchannel *sch) static void vfio_ccw_sch_shutdown(struct subchannel *sch)
{ {
vfio_ccw_sch_quiesce(sch); struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
} }
/** /**
...@@ -301,19 +284,11 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process) ...@@ -301,19 +284,11 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
if (work_pending(&sch->todo_work)) if (work_pending(&sch->todo_work))
goto out_unlock; goto out_unlock;
if (cio_update_schib(sch)) {
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
rc = 0;
goto out_unlock;
}
private = dev_get_drvdata(&sch->dev);
if (private->state == VFIO_CCW_STATE_NOT_OPER) {
private->state = private->mdev ? VFIO_CCW_STATE_IDLE :
VFIO_CCW_STATE_STANDBY;
}
rc = 0; rc = 0;
if (cio_update_schib(sch))
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
out_unlock: out_unlock:
spin_unlock_irqrestore(sch->lock, flags); spin_unlock_irqrestore(sch->lock, flags);
...@@ -358,8 +333,8 @@ static int vfio_ccw_chp_event(struct subchannel *sch, ...@@ -358,8 +333,8 @@ static int vfio_ccw_chp_event(struct subchannel *sch,
return 0; return 0;
trace_vfio_ccw_chp_event(private->sch->schid, mask, event); trace_vfio_ccw_chp_event(private->sch->schid, mask, event);
VFIO_CCW_MSG_EVENT(2, "%pUl (%x.%x.%04x): mask=0x%x event=%d\n", VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: mask=0x%x event=%d\n",
mdev_uuid(private->mdev), sch->schid.cssid, sch->schid.cssid,
sch->schid.ssid, sch->schid.sch_no, sch->schid.ssid, sch->schid.sch_no,
mask, event); mask, event);
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
*/ */
#include <linux/vfio.h> #include <linux/vfio.h>
#include <linux/mdev.h>
#include <asm/isc.h>
#include "ioasm.h" #include "ioasm.h"
#include "vfio_ccw_private.h" #include "vfio_ccw_private.h"
...@@ -161,8 +162,12 @@ static void fsm_notoper(struct vfio_ccw_private *private, ...@@ -161,8 +162,12 @@ static void fsm_notoper(struct vfio_ccw_private *private,
{ {
struct subchannel *sch = private->sch; struct subchannel *sch = private->sch;
VFIO_CCW_TRACE_EVENT(2, "notoper"); VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: notoper event %x state %x\n",
VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev)); sch->schid.cssid,
sch->schid.ssid,
sch->schid.sch_no,
event,
private->state);
/* /*
* TODO: * TODO:
...@@ -170,6 +175,9 @@ static void fsm_notoper(struct vfio_ccw_private *private, ...@@ -170,6 +175,9 @@ static void fsm_notoper(struct vfio_ccw_private *private,
*/ */
css_sched_sch_todo(sch, SCH_TODO_UNREG); css_sched_sch_todo(sch, SCH_TODO_UNREG);
private->state = VFIO_CCW_STATE_NOT_OPER; private->state = VFIO_CCW_STATE_NOT_OPER;
/* This is usually handled during CLOSE event */
cp_free(&private->cp);
} }
/* /*
...@@ -242,7 +250,6 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -242,7 +250,6 @@ static void fsm_io_request(struct vfio_ccw_private *private,
union orb *orb; union orb *orb;
union scsw *scsw = &private->scsw; union scsw *scsw = &private->scsw;
struct ccw_io_region *io_region = private->io_region; struct ccw_io_region *io_region = private->io_region;
struct mdev_device *mdev = private->mdev;
char *errstr = "request"; char *errstr = "request";
struct subchannel_id schid = get_schid(private); struct subchannel_id schid = get_schid(private);
...@@ -256,8 +263,8 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -256,8 +263,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
if (orb->tm.b) { if (orb->tm.b) {
io_region->ret_code = -EOPNOTSUPP; io_region->ret_code = -EOPNOTSUPP;
VFIO_CCW_MSG_EVENT(2, VFIO_CCW_MSG_EVENT(2,
"%pUl (%x.%x.%04x): transport mode\n", "sch %x.%x.%04x: transport mode\n",
mdev_uuid(mdev), schid.cssid, schid.cssid,
schid.ssid, schid.sch_no); schid.ssid, schid.sch_no);
errstr = "transport mode"; errstr = "transport mode";
goto err_out; goto err_out;
...@@ -265,8 +272,8 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -265,8 +272,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
io_region->ret_code = cp_init(&private->cp, orb); io_region->ret_code = cp_init(&private->cp, orb);
if (io_region->ret_code) { if (io_region->ret_code) {
VFIO_CCW_MSG_EVENT(2, VFIO_CCW_MSG_EVENT(2,
"%pUl (%x.%x.%04x): cp_init=%d\n", "sch %x.%x.%04x: cp_init=%d\n",
mdev_uuid(mdev), schid.cssid, schid.cssid,
schid.ssid, schid.sch_no, schid.ssid, schid.sch_no,
io_region->ret_code); io_region->ret_code);
errstr = "cp init"; errstr = "cp init";
...@@ -276,8 +283,8 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -276,8 +283,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
io_region->ret_code = cp_prefetch(&private->cp); io_region->ret_code = cp_prefetch(&private->cp);
if (io_region->ret_code) { if (io_region->ret_code) {
VFIO_CCW_MSG_EVENT(2, VFIO_CCW_MSG_EVENT(2,
"%pUl (%x.%x.%04x): cp_prefetch=%d\n", "sch %x.%x.%04x: cp_prefetch=%d\n",
mdev_uuid(mdev), schid.cssid, schid.cssid,
schid.ssid, schid.sch_no, schid.ssid, schid.sch_no,
io_region->ret_code); io_region->ret_code);
errstr = "cp prefetch"; errstr = "cp prefetch";
...@@ -289,8 +296,8 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -289,8 +296,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
io_region->ret_code = fsm_io_helper(private); io_region->ret_code = fsm_io_helper(private);
if (io_region->ret_code) { if (io_region->ret_code) {
VFIO_CCW_MSG_EVENT(2, VFIO_CCW_MSG_EVENT(2,
"%pUl (%x.%x.%04x): fsm_io_helper=%d\n", "sch %x.%x.%04x: fsm_io_helper=%d\n",
mdev_uuid(mdev), schid.cssid, schid.cssid,
schid.ssid, schid.sch_no, schid.ssid, schid.sch_no,
io_region->ret_code); io_region->ret_code);
errstr = "cp fsm_io_helper"; errstr = "cp fsm_io_helper";
...@@ -300,16 +307,16 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -300,16 +307,16 @@ static void fsm_io_request(struct vfio_ccw_private *private,
return; return;
} else if (scsw->cmd.fctl & SCSW_FCTL_HALT_FUNC) { } else if (scsw->cmd.fctl & SCSW_FCTL_HALT_FUNC) {
VFIO_CCW_MSG_EVENT(2, VFIO_CCW_MSG_EVENT(2,
"%pUl (%x.%x.%04x): halt on io_region\n", "sch %x.%x.%04x: halt on io_region\n",
mdev_uuid(mdev), schid.cssid, schid.cssid,
schid.ssid, schid.sch_no); schid.ssid, schid.sch_no);
/* halt is handled via the async cmd region */ /* halt is handled via the async cmd region */
io_region->ret_code = -EOPNOTSUPP; io_region->ret_code = -EOPNOTSUPP;
goto err_out; goto err_out;
} else if (scsw->cmd.fctl & SCSW_FCTL_CLEAR_FUNC) { } else if (scsw->cmd.fctl & SCSW_FCTL_CLEAR_FUNC) {
VFIO_CCW_MSG_EVENT(2, VFIO_CCW_MSG_EVENT(2,
"%pUl (%x.%x.%04x): clear on io_region\n", "sch %x.%x.%04x: clear on io_region\n",
mdev_uuid(mdev), schid.cssid, schid.cssid,
schid.ssid, schid.sch_no); schid.ssid, schid.sch_no);
/* clear is handled via the async cmd region */ /* clear is handled via the async cmd region */
io_region->ret_code = -EOPNOTSUPP; io_region->ret_code = -EOPNOTSUPP;
...@@ -366,6 +373,54 @@ static void fsm_irq(struct vfio_ccw_private *private, ...@@ -366,6 +373,54 @@ static void fsm_irq(struct vfio_ccw_private *private,
complete(private->completion); complete(private->completion);
} }
static void fsm_open(struct vfio_ccw_private *private,
enum vfio_ccw_event event)
{
struct subchannel *sch = private->sch;
int ret;
spin_lock_irq(sch->lock);
sch->isc = VFIO_CCW_ISC;
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
if (ret)
goto err_unlock;
private->state = VFIO_CCW_STATE_IDLE;
spin_unlock_irq(sch->lock);
return;
err_unlock:
spin_unlock_irq(sch->lock);
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
}
static void fsm_close(struct vfio_ccw_private *private,
enum vfio_ccw_event event)
{
struct subchannel *sch = private->sch;
int ret;
spin_lock_irq(sch->lock);
if (!sch->schib.pmcw.ena)
goto err_unlock;
ret = cio_disable_subchannel(sch);
if (ret == -EBUSY)
vfio_ccw_sch_quiesce(sch);
if (ret)
goto err_unlock;
private->state = VFIO_CCW_STATE_STANDBY;
spin_unlock_irq(sch->lock);
cp_free(&private->cp);
return;
err_unlock:
spin_unlock_irq(sch->lock);
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
}
/* /*
* Device statemachine * Device statemachine
*/ */
...@@ -375,29 +430,39 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = { ...@@ -375,29 +430,39 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error, [VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error,
[VFIO_CCW_EVENT_INTERRUPT] = fsm_disabled_irq, [VFIO_CCW_EVENT_INTERRUPT] = fsm_disabled_irq,
[VFIO_CCW_EVENT_OPEN] = fsm_nop,
[VFIO_CCW_EVENT_CLOSE] = fsm_nop,
}, },
[VFIO_CCW_STATE_STANDBY] = { [VFIO_CCW_STATE_STANDBY] = {
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error, [VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error,
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, [VFIO_CCW_EVENT_INTERRUPT] = fsm_disabled_irq,
[VFIO_CCW_EVENT_OPEN] = fsm_open,
[VFIO_CCW_EVENT_CLOSE] = fsm_notoper,
}, },
[VFIO_CCW_STATE_IDLE] = { [VFIO_CCW_STATE_IDLE] = {
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_request, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_request,
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_request, [VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_request,
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, [VFIO_CCW_EVENT_INTERRUPT] = fsm_irq,
[VFIO_CCW_EVENT_OPEN] = fsm_notoper,
[VFIO_CCW_EVENT_CLOSE] = fsm_close,
}, },
[VFIO_CCW_STATE_CP_PROCESSING] = { [VFIO_CCW_STATE_CP_PROCESSING] = {
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_retry, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_retry,
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_retry, [VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_retry,
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, [VFIO_CCW_EVENT_INTERRUPT] = fsm_irq,
[VFIO_CCW_EVENT_OPEN] = fsm_notoper,
[VFIO_CCW_EVENT_CLOSE] = fsm_close,
}, },
[VFIO_CCW_STATE_CP_PENDING] = { [VFIO_CCW_STATE_CP_PENDING] = {
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy,
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_request, [VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_request,
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, [VFIO_CCW_EVENT_INTERRUPT] = fsm_irq,
[VFIO_CCW_EVENT_OPEN] = fsm_notoper,
[VFIO_CCW_EVENT_CLOSE] = fsm_close,
}, },
}; };
...@@ -21,27 +21,16 @@ static const struct vfio_device_ops vfio_ccw_dev_ops; ...@@ -21,27 +21,16 @@ static const struct vfio_device_ops vfio_ccw_dev_ops;
static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private) static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private)
{ {
struct subchannel *sch;
int ret;
sch = private->sch;
/* /*
* TODO: * If the FSM state is seen as Not Operational after closing
* In the cureent stage, some things like "no I/O running" and "no * and re-opening the mdev, return an error.
* interrupt pending" are clear, but we are not sure what other state
* we need to care about.
* There are still a lot more instructions need to be handled. We
* should come back here later.
*/ */
ret = vfio_ccw_sch_quiesce(sch); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
if (ret) vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_OPEN);
return ret; if (private->state == VFIO_CCW_STATE_NOT_OPER)
return -EINVAL;
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
if (!ret)
private->state = VFIO_CCW_STATE_IDLE;
return ret; return 0;
} }
static int vfio_ccw_mdev_notifier(struct notifier_block *nb, static int vfio_ccw_mdev_notifier(struct notifier_block *nb,
...@@ -64,7 +53,6 @@ static int vfio_ccw_mdev_notifier(struct notifier_block *nb, ...@@ -64,7 +53,6 @@ static int vfio_ccw_mdev_notifier(struct notifier_block *nb,
if (vfio_ccw_mdev_reset(private)) if (vfio_ccw_mdev_reset(private))
return NOTIFY_BAD; return NOTIFY_BAD;
cp_free(&private->cp);
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -128,11 +116,8 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) ...@@ -128,11 +116,8 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
vfio_init_group_dev(&private->vdev, &mdev->dev, vfio_init_group_dev(&private->vdev, &mdev->dev,
&vfio_ccw_dev_ops); &vfio_ccw_dev_ops);
private->mdev = mdev; VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: create\n",
private->state = VFIO_CCW_STATE_IDLE; private->sch->schid.cssid,
VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: create\n",
mdev_uuid(mdev), private->sch->schid.cssid,
private->sch->schid.ssid, private->sch->schid.ssid,
private->sch->schid.sch_no); private->sch->schid.sch_no);
...@@ -145,8 +130,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) ...@@ -145,8 +130,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
err_atomic: err_atomic:
vfio_uninit_group_dev(&private->vdev); vfio_uninit_group_dev(&private->vdev);
atomic_inc(&private->avail); atomic_inc(&private->avail);
private->mdev = NULL;
private->state = VFIO_CCW_STATE_IDLE;
return ret; return ret;
} }
...@@ -154,23 +137,16 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev) ...@@ -154,23 +137,16 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
{ {
struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent); struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent);
VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: remove\n", VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: remove\n",
mdev_uuid(mdev), private->sch->schid.cssid, private->sch->schid.cssid,
private->sch->schid.ssid, private->sch->schid.ssid,
private->sch->schid.sch_no); private->sch->schid.sch_no);
vfio_unregister_group_dev(&private->vdev); vfio_unregister_group_dev(&private->vdev);
if ((private->state != VFIO_CCW_STATE_NOT_OPER) && vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
(private->state != VFIO_CCW_STATE_STANDBY)) {
if (!vfio_ccw_sch_quiesce(private->sch))
private->state = VFIO_CCW_STATE_STANDBY;
/* The state will be NOT_OPER on error. */
}
vfio_uninit_group_dev(&private->vdev); vfio_uninit_group_dev(&private->vdev);
cp_free(&private->cp);
private->mdev = NULL;
atomic_inc(&private->avail); atomic_inc(&private->avail);
} }
...@@ -181,6 +157,10 @@ static int vfio_ccw_mdev_open_device(struct vfio_device *vdev) ...@@ -181,6 +157,10 @@ static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP; unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
int ret; int ret;
/* Device cannot simply be opened again from this state */
if (private->state == VFIO_CCW_STATE_NOT_OPER)
return -EINVAL;
private->nb.notifier_call = vfio_ccw_mdev_notifier; private->nb.notifier_call = vfio_ccw_mdev_notifier;
ret = vfio_register_notifier(vdev, VFIO_IOMMU_NOTIFY, ret = vfio_register_notifier(vdev, VFIO_IOMMU_NOTIFY,
...@@ -200,6 +180,12 @@ static int vfio_ccw_mdev_open_device(struct vfio_device *vdev) ...@@ -200,6 +180,12 @@ static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
if (ret) if (ret)
goto out_unregister; goto out_unregister;
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_OPEN);
if (private->state == VFIO_CCW_STATE_NOT_OPER) {
ret = -EINVAL;
goto out_unregister;
}
return ret; return ret;
out_unregister: out_unregister:
...@@ -213,14 +199,7 @@ static void vfio_ccw_mdev_close_device(struct vfio_device *vdev) ...@@ -213,14 +199,7 @@ static void vfio_ccw_mdev_close_device(struct vfio_device *vdev)
struct vfio_ccw_private *private = struct vfio_ccw_private *private =
container_of(vdev, struct vfio_ccw_private, vdev); container_of(vdev, struct vfio_ccw_private, vdev);
if ((private->state != VFIO_CCW_STATE_NOT_OPER) && vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
(private->state != VFIO_CCW_STATE_STANDBY)) {
if (!vfio_ccw_mdev_reset(private))
private->state = VFIO_CCW_STATE_STANDBY;
/* The state will be NOT_OPER on error. */
}
cp_free(&private->cp);
vfio_ccw_unregister_dev_regions(private); vfio_ccw_unregister_dev_regions(private);
vfio_unregister_notifier(vdev, VFIO_IOMMU_NOTIFY, &private->nb); vfio_unregister_notifier(vdev, VFIO_IOMMU_NOTIFY, &private->nb);
} }
...@@ -657,13 +636,3 @@ struct mdev_driver vfio_ccw_mdev_driver = { ...@@ -657,13 +636,3 @@ struct mdev_driver vfio_ccw_mdev_driver = {
.remove = vfio_ccw_mdev_remove, .remove = vfio_ccw_mdev_remove,
.supported_type_groups = mdev_type_groups, .supported_type_groups = mdev_type_groups,
}; };
int vfio_ccw_mdev_reg(struct subchannel *sch)
{
return mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
}
void vfio_ccw_mdev_unreg(struct subchannel *sch)
{
mdev_unregister_device(&sch->dev);
}
...@@ -73,7 +73,6 @@ struct vfio_ccw_crw { ...@@ -73,7 +73,6 @@ struct vfio_ccw_crw {
* @state: internal state of the device * @state: internal state of the device
* @completion: synchronization helper of the I/O completion * @completion: synchronization helper of the I/O completion
* @avail: available for creating a mediated device * @avail: available for creating a mediated device
* @mdev: pointer to the mediated device
* @nb: notifier for vfio events * @nb: notifier for vfio events
* @io_region: MMIO region to input/output I/O arguments/results * @io_region: MMIO region to input/output I/O arguments/results
* @io_mutex: protect against concurrent update of I/O regions * @io_mutex: protect against concurrent update of I/O regions
...@@ -97,7 +96,6 @@ struct vfio_ccw_private { ...@@ -97,7 +96,6 @@ struct vfio_ccw_private {
int state; int state;
struct completion *completion; struct completion *completion;
atomic_t avail; atomic_t avail;
struct mdev_device *mdev;
struct notifier_block nb; struct notifier_block nb;
struct ccw_io_region *io_region; struct ccw_io_region *io_region;
struct mutex io_mutex; struct mutex io_mutex;
...@@ -119,9 +117,6 @@ struct vfio_ccw_private { ...@@ -119,9 +117,6 @@ struct vfio_ccw_private {
struct work_struct crw_work; struct work_struct crw_work;
} __aligned(8); } __aligned(8);
int vfio_ccw_mdev_reg(struct subchannel *sch);
void vfio_ccw_mdev_unreg(struct subchannel *sch);
int vfio_ccw_sch_quiesce(struct subchannel *sch); int vfio_ccw_sch_quiesce(struct subchannel *sch);
extern struct mdev_driver vfio_ccw_mdev_driver; extern struct mdev_driver vfio_ccw_mdev_driver;
...@@ -147,6 +142,8 @@ enum vfio_ccw_event { ...@@ -147,6 +142,8 @@ enum vfio_ccw_event {
VFIO_CCW_EVENT_IO_REQ, VFIO_CCW_EVENT_IO_REQ,
VFIO_CCW_EVENT_INTERRUPT, VFIO_CCW_EVENT_INTERRUPT,
VFIO_CCW_EVENT_ASYNC_REQ, VFIO_CCW_EVENT_ASYNC_REQ,
VFIO_CCW_EVENT_OPEN,
VFIO_CCW_EVENT_CLOSE,
/* last element! */ /* last element! */
NR_VFIO_CCW_EVENTS NR_VFIO_CCW_EVENTS
}; };
...@@ -158,7 +155,7 @@ typedef void (fsm_func_t)(struct vfio_ccw_private *, enum vfio_ccw_event); ...@@ -158,7 +155,7 @@ typedef void (fsm_func_t)(struct vfio_ccw_private *, enum vfio_ccw_event);
extern fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS]; extern fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS];
static inline void vfio_ccw_fsm_event(struct vfio_ccw_private *private, static inline void vfio_ccw_fsm_event(struct vfio_ccw_private *private,
int event) enum vfio_ccw_event event)
{ {
trace_vfio_ccw_fsm_event(private->sch->schid, private->state, event); trace_vfio_ccw_fsm_event(private->sch->schid, private->state, event);
vfio_ccw_jumptable[private->state][event](private, event); vfio_ccw_jumptable[private->state][event](private, event);
......
...@@ -1728,7 +1728,7 @@ int vfio_config_init(struct vfio_pci_core_device *vdev) ...@@ -1728,7 +1728,7 @@ int vfio_config_init(struct vfio_pci_core_device *vdev)
/* /*
* Config space, caps and ecaps are all dword aligned, so we could * Config space, caps and ecaps are all dword aligned, so we could
* use one byte per dword to record the type. However, there are * use one byte per dword to record the type. However, there are
* no requiremenst on the length of a capability, so the gap between * no requirements on the length of a capability, so the gap between
* capabilities needs byte granularity. * capabilities needs byte granularity.
*/ */
map = kmalloc(pdev->cfg_size, GFP_KERNEL); map = kmalloc(pdev->cfg_size, GFP_KERNEL);
......
...@@ -65,11 +65,6 @@ struct mdev_driver { ...@@ -65,11 +65,6 @@ struct mdev_driver {
struct device_driver driver; struct device_driver driver;
}; };
static inline const guid_t *mdev_uuid(struct mdev_device *mdev)
{
return &mdev->uuid;
}
extern struct bus_type mdev_bus_type; extern struct bus_type mdev_bus_type;
int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver); int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment