return;
}
cdev->private->flags.donotify = 1;
- /* Get device online again. */
- ccw_device_online(cdev);
}
/*
cdev->private->devno, sch->irq);
break;
case DEV_STATE_OFFLINE:
- if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID)
+ if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
+ ccw_device_handle_oper(cdev);
notify = 1;
- else /* fill out sense information */
- cdev->id = (struct ccw_device_id) {
- .cu_type = cdev->private->senseid.cu_type,
- .cu_model = cdev->private->senseid.cu_model,
- .dev_type = cdev->private->senseid.dev_type,
- .dev_model = cdev->private->senseid.dev_model,
- };
+ }
+ /* fill out sense information */
+ cdev->id = (struct ccw_device_id) {
+ .cu_type = cdev->private->senseid.cu_type,
+ .cu_model = cdev->private->senseid.cu_model,
+ .dev_type = cdev->private->senseid.dev_type,
+ .dev_model = cdev->private->senseid.dev_model,
+ };
+ if (notify) {
+ /* Get device online again. */
+ cdev->private->state = DEV_STATE_OFFLINE;
+ ccw_device_online(cdev);
+ wake_up(&cdev->private->wait_q);
+ return;
+ }
/* Issue device info message. */
CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: "
"CU Type/Mod = %04X/%02X, Dev Type/Mod = "
break;
}
cdev->private->state = state;
- if (notify && state == DEV_STATE_OFFLINE)
- ccw_device_handle_oper(cdev);
- else
- io_subchannel_recog_done(cdev);
+ io_subchannel_recog_done(cdev);
if (state != DEV_STATE_NOT_OPER)
wake_up(&cdev->private->wait_q);
}
irb = (struct irb *) __LC_IRB;
/* Check for unsolicited interrupt. */
- if (irb->scsw.stctl ==
- (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
+ if ((irb->scsw.stctl ==
+ (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS))
+ && (!irb->scsw.cc)) {
+ if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
+ !irb->esw.esw0.erw.cons) {
+ /* Unit check but no sense data. Need basic sense. */
+ if (ccw_device_do_sense(cdev, irb) != 0)
+ goto call_handler_unsol;
+ memcpy(irb, &cdev->private->irb, sizeof(struct irb));
+ cdev->private->state = DEV_STATE_W4SENSE;
+ cdev->private->intparm = 0;
+ return;
+ }
+call_handler_unsol:
if (cdev->handler)
cdev->handler (cdev, 0, irb);
return;
/* Check for unsolicited interrupt. */
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
- if (cdev->handler)
- cdev->handler (cdev, 0, irb);
if (irb->scsw.cc == 1)
/* Basic sense hasn't started. Try again. */
ccw_device_do_sense(cdev, irb);
+ else {
+ printk("Huh? %s(%s): unsolicited interrupt...\n",
+ __FUNCTION__, cdev->dev.bus_id);
+ if (cdev->handler)
+ cdev->handler (cdev, 0, irb);
+ }
return;
}
/* Add basic sense info to irb. */
struct irb *irb;
irb = (struct irb *) __LC_IRB;
- /* Check for unsolicited interrupt. */
- if (irb->scsw.stctl ==
- (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
- if (cdev->handler)
- cdev->handler (cdev, 0, irb);
- return;
- }
/* Accumulate status. We don't do basic sense. */
ccw_device_accumulate_irb(cdev, irb);
/* Try to start delayed device verification. */
struct subchannel *sch;
irb = (struct irb *) __LC_IRB;
- /* Check for unsolicited interrupt. */
- if (irb->scsw.stctl ==
- (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
- if (cdev->handler)
- cdev->handler (cdev, 0, irb);
- if (irb->scsw.cc == 1)
- goto call_handler;
- return;
- }
/*
* Accumulate status and find out if a basic sense is needed.
* This is fine since we have already adapted the lpm.
}
return;
}
-call_handler:
+
/* Iff device is idle, reset timeout. */
sch = to_subchannel(cdev->dev.parent);
if (!stsch(sch->irq, &sch->schib))
case DEV_EVENT_INTERRUPT:
irb = (struct irb *) __LC_IRB;
/* Check for unsolicited interrupt. */
- if (irb->scsw.stctl ==
- (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS))
+ if ((irb->scsw.stctl ==
+ (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) &&
+ (!irb->scsw.cc))
/* FIXME: we should restart stlck here, but this
* is extremely unlikely ... */
goto out_wakeup;