X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fs390%2Fcio%2Fdevice_status.c;h=aa96e6752592355a06b5a4fb6c97f346e4c1066d;hb=b5faa4b89e4d83203b1f44f143a351b518f7cda2;hp=bdcf930f7beb120a636565f461ac32c9e9c6b9c0;hpb=12472b4165a21f5415ff4f60f8f46311a6b7b9ac;p=linux-2.6 diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index bdcf930f7b..aa96e67525 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c @@ -25,7 +25,7 @@ * Check for any kind of channel or interface control check but don't * issue the message for the console device */ -static inline void +static void ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) { if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK | @@ -72,7 +72,7 @@ ccw_device_path_notoper(struct ccw_device *cdev) /* * Copy valid bits from the extended control word to device irb. */ -static inline void +static void ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) { /* @@ -94,7 +94,7 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) /* * Check if extended status word is valid. */ -static inline int +static int ccw_device_accumulate_esw_valid(struct irb *irb) { if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) @@ -109,7 +109,7 @@ ccw_device_accumulate_esw_valid(struct irb *irb) /* * Copy valid bits from the extended status word to device irb. */ -static inline void +static void ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb) { struct irb *cdev_irb; @@ -221,6 +221,14 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb) cdev_irb = &cdev->private->irb; + /* + * If the clear function had been performed, all formerly pending + * status at the subchannel has been cleared and we must not pass + * intermediate accumulated status to the device driver. + */ + if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) + memset(&cdev->private->irb, 0, sizeof(struct irb)); + /* Copy bits which are valid only for the start function. */ if (irb->scsw.fctl & SCSW_FCTL_START_FUNC) { /* Copy key. */ @@ -263,7 +271,11 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb) cdev_irb->scsw.cpa = irb->scsw.cpa; /* Accumulate device status, but not the device busy flag. */ cdev_irb->scsw.dstat &= ~DEV_STAT_BUSY; - cdev_irb->scsw.dstat |= irb->scsw.dstat; + /* dstat is not always valid. */ + if (irb->scsw.stctl & + (SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_SEC_STATUS + | SCSW_STCTL_INTER_STATUS | SCSW_STCTL_ALERT_STATUS)) + cdev_irb->scsw.dstat |= irb->scsw.dstat; /* Accumulate subchannel status. */ cdev_irb->scsw.cstat |= irb->scsw.cstat; /* Copy residual count if it is valid. */