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: Dong Jia Shi <bjsdjshi@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Acked-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
int ccode;
__u8 lpm;
unsigned long flags;
int ccode;
__u8 lpm;
unsigned long flags;
sch = private->sch;
spin_lock_irqsave(sch->lock, flags);
private->state = VFIO_CCW_STATE_BUSY;
sch = private->sch;
spin_lock_irqsave(sch->lock, flags);
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);
* Initialize device status information
*/
sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
* Initialize device status information
*/
sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
case 1: /* Status pending */
case 2: /* Busy */
case 1: /* Status pending */
case 2: /* Busy */
case 3: /* Device/path not operational */
{
lpm = orb->cmd.lpm;
case 3: /* Device/path not operational */
{
lpm = orb->cmd.lpm;
sch->lpm = 0;
if (cio_update_schib(sch))
sch->lpm = 0;
if (cio_update_schib(sch))
- return -ENODEV;
-
- return sch->lpm ? -EACCES : -ENODEV;
+ ret = -ENODEV;
+ else
+ ret = sch->lpm ? -EACCES : -ENODEV;
+ break;
+ 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,