Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bddabeb7 authored by Cornelia Huck's avatar Cornelia Huck Committed by Greg Kroah-Hartman
Browse files

vfio: ccw: process ssch with interrupts disabled



commit 3368e547c52b96586f0edf9657ca12b94d8e61a7 upstream.

When we call ssch, an interrupt might already be pending once we
return from the START SUBCHANNEL instruction. Therefore we need to
make sure interrupts are disabled while holding the subchannel lock
until after we're done with our processing.

Cc: stable@vger.kernel.org #v4.12+
Reviewed-by: default avatarDong Jia Shi <bjsdjshi@linux.ibm.com>
Acked-by: default avatarHalil Pasic <pasic@linux.vnet.ibm.com>
Acked-by: default avatarPierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: default avatarCornelia Huck <cohuck@redhat.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent be10336a
Loading
Loading
Loading
Loading
+12 −7
Original line number Original line Diff line number Diff line
@@ -20,12 +20,12 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
	int ccode;
	int ccode;
	__u8 lpm;
	__u8 lpm;
	unsigned long flags;
	unsigned long flags;
	int ret;


	sch = private->sch;
	sch = private->sch;


	spin_lock_irqsave(sch->lock, flags);
	spin_lock_irqsave(sch->lock, flags);
	private->state = VFIO_CCW_STATE_BUSY;
	private->state = VFIO_CCW_STATE_BUSY;
	spin_unlock_irqrestore(sch->lock, flags);


	orb = cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm);
	orb = cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm);


@@ -38,10 +38,12 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
		 * Initialize device status information
		 * Initialize device status information
		 */
		 */
		sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
		sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
		return 0;
		ret = 0;
		break;
	case 1:		/* Status pending */
	case 1:		/* Status pending */
	case 2:		/* Busy */
	case 2:		/* Busy */
		return -EBUSY;
		ret = -EBUSY;
		break;
	case 3:		/* Device/path not operational */
	case 3:		/* Device/path not operational */
	{
	{
		lpm = orb->cmd.lpm;
		lpm = orb->cmd.lpm;
@@ -51,13 +53,16 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
			sch->lpm = 0;
			sch->lpm = 0;


		if (cio_update_schib(sch))
		if (cio_update_schib(sch))
			return -ENODEV;
			ret = -ENODEV;

		else
		return sch->lpm ? -EACCES : -ENODEV;
			ret = sch->lpm ? -EACCES : -ENODEV;
		break;
	}
	}
	default:
	default:
		return ccode;
		ret = ccode;
	}
	}
	spin_unlock_irqrestore(sch->lock, flags);
	return ret;
}
}


static void fsm_notoper(struct vfio_ccw_private *private,
static void fsm_notoper(struct vfio_ccw_private *private,