diff options
Diffstat (limited to 'drivers/s390/block')
-rw-r--r-- | drivers/s390/block/dasd.c | 11 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 70 |
2 files changed, 40 insertions, 41 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index aa95f1001761..80e45de096a9 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1099,11 +1099,20 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1099 | cqr = (struct dasd_ccw_req *) intparm; | 1099 | cqr = (struct dasd_ccw_req *) intparm; |
1100 | if (!cqr || ((scsw_cc(&irb->scsw) == 1) && | 1100 | if (!cqr || ((scsw_cc(&irb->scsw) == 1) && |
1101 | (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && | 1101 | (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && |
1102 | (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) { | 1102 | ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) || |
1103 | (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND | | ||
1104 | SCSW_STCTL_ALERT_STATUS))))) { | ||
1103 | if (cqr && cqr->status == DASD_CQR_IN_IO) | 1105 | if (cqr && cqr->status == DASD_CQR_IN_IO) |
1104 | cqr->status = DASD_CQR_QUEUED; | 1106 | cqr->status = DASD_CQR_QUEUED; |
1107 | if (cqr) | ||
1108 | memcpy(&cqr->irb, irb, sizeof(*irb)); | ||
1105 | device = dasd_device_from_cdev_locked(cdev); | 1109 | device = dasd_device_from_cdev_locked(cdev); |
1106 | if (!IS_ERR(device)) { | 1110 | if (!IS_ERR(device)) { |
1111 | device->discipline->dump_sense_dbf(device, irb, | ||
1112 | "unsolicited"); | ||
1113 | if ((device->features & DASD_FEATURE_ERPLOG)) | ||
1114 | device->discipline->dump_sense(device, cqr, | ||
1115 | irb); | ||
1107 | dasd_device_clear_timer(device); | 1116 | dasd_device_clear_timer(device); |
1108 | device->discipline->handle_unsolicited_interrupt(device, | 1117 | device->discipline->handle_unsolicited_interrupt(device, |
1109 | irb); | 1118 | irb); |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ea0e565ebc9d..50cf96389d2c 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1776,13 +1776,13 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
1776 | } | 1776 | } |
1777 | 1777 | ||
1778 | /* summary unit check */ | 1778 | /* summary unit check */ |
1779 | if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) && | 1779 | sense = dasd_get_sense(irb); |
1780 | (irb->ecw[7] == 0x0D)) { | 1780 | if (sense && (sense[7] == 0x0D) && |
1781 | (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) { | ||
1781 | dasd_alias_handle_summary_unit_check(device, irb); | 1782 | dasd_alias_handle_summary_unit_check(device, irb); |
1782 | return; | 1783 | return; |
1783 | } | 1784 | } |
1784 | 1785 | ||
1785 | sense = dasd_get_sense(irb); | ||
1786 | /* service information message SIM */ | 1786 | /* service information message SIM */ |
1787 | if (sense && !(sense[27] & DASD_SENSE_BIT_0) && | 1787 | if (sense && !(sense[27] & DASD_SENSE_BIT_0) && |
1788 | ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { | 1788 | ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { |
@@ -1791,26 +1791,15 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
1791 | return; | 1791 | return; |
1792 | } | 1792 | } |
1793 | 1793 | ||
1794 | if ((scsw_cc(&irb->scsw) == 1) && | 1794 | if ((scsw_cc(&irb->scsw) == 1) && !sense && |
1795 | (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && | 1795 | (scsw_fctl(&irb->scsw) == SCSW_FCTL_START_FUNC) && |
1796 | (scsw_actl(&irb->scsw) & SCSW_ACTL_START_PEND) && | 1796 | (scsw_actl(&irb->scsw) == SCSW_ACTL_START_PEND) && |
1797 | (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND)) { | 1797 | (scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND)) { |
1798 | /* fake irb do nothing, they are handled elsewhere */ | 1798 | /* fake irb do nothing, they are handled elsewhere */ |
1799 | dasd_schedule_device_bh(device); | 1799 | dasd_schedule_device_bh(device); |
1800 | return; | 1800 | return; |
1801 | } | 1801 | } |
1802 | 1802 | ||
1803 | if (!sense) { | ||
1804 | /* just report other unsolicited interrupts */ | ||
1805 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | ||
1806 | "unsolicited interrupt received"); | ||
1807 | } else { | ||
1808 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | ||
1809 | "unsolicited interrupt received " | ||
1810 | "(sense available)"); | ||
1811 | device->discipline->dump_sense_dbf(device, irb, "unsolicited"); | ||
1812 | } | ||
1813 | |||
1814 | dasd_schedule_device_bh(device); | 1803 | dasd_schedule_device_bh(device); |
1815 | return; | 1804 | return; |
1816 | }; | 1805 | }; |
@@ -3093,23 +3082,19 @@ dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct irb *irb, | |||
3093 | char *reason) | 3082 | char *reason) |
3094 | { | 3083 | { |
3095 | u64 *sense; | 3084 | u64 *sense; |
3096 | u32 stat; | 3085 | u64 *stat; |
3097 | 3086 | ||
3098 | sense = (u64 *) dasd_get_sense(irb); | 3087 | sense = (u64 *) dasd_get_sense(irb); |
3099 | stat = scsw_cstat(&irb->scsw); | 3088 | stat = (u64 *) &irb->scsw; |
3100 | stat <<= 8; | ||
3101 | stat |= scsw_dstat(&irb->scsw); | ||
3102 | stat <<= 8; | ||
3103 | stat |= scsw_cc(&irb->scsw); | ||
3104 | |||
3105 | if (sense) { | 3089 | if (sense) { |
3106 | DBF_DEV_EVENT(DBF_EMERG, device, | 3090 | DBF_DEV_EVENT(DBF_EMERG, device, "%s: %016llx %08x : " |
3107 | "%s: %s %06x %016llx %016llx %016llx %016llx", | 3091 | "%016llx %016llx %016llx %016llx", |
3108 | reason, scsw_is_tm(&irb->scsw) ? "t" : "c", stat, | 3092 | reason, *stat, *((u32 *) (stat + 1)), |
3109 | sense[0], sense[1], sense[2], sense[3]); | 3093 | sense[0], sense[1], sense[2], sense[3]); |
3110 | } else { | 3094 | } else { |
3111 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", | 3095 | DBF_DEV_EVENT(DBF_EMERG, device, "%s: %016llx %08x : %s", |
3112 | "SORRY - NO VALID SENSE AVAILABLE\n"); | 3096 | reason, *stat, *((u32 *) (stat + 1)), |
3097 | "NO VALID SENSE"); | ||
3113 | } | 3098 | } |
3114 | } | 3099 | } |
3115 | 3100 | ||
@@ -3135,9 +3120,12 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3135 | " I/O status report for device %s:\n", | 3120 | " I/O status report for device %s:\n", |
3136 | dev_name(&device->cdev->dev)); | 3121 | dev_name(&device->cdev->dev)); |
3137 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3122 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3138 | " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n", | 3123 | " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X " |
3139 | req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), | 3124 | "CS:%02X RC:%d\n", |
3140 | scsw_cc(&irb->scsw), req ? req->intrc : 0); | 3125 | req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), |
3126 | scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw), | ||
3127 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), | ||
3128 | req ? req->intrc : 0); | ||
3141 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3129 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3142 | " device %s: Failing CCW: %p\n", | 3130 | " device %s: Failing CCW: %p\n", |
3143 | dev_name(&device->cdev->dev), | 3131 | dev_name(&device->cdev->dev), |
@@ -3238,11 +3226,13 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
3238 | " I/O status report for device %s:\n", | 3226 | " I/O status report for device %s:\n", |
3239 | dev_name(&device->cdev->dev)); | 3227 | dev_name(&device->cdev->dev)); |
3240 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3228 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3241 | " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d " | 3229 | " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X " |
3242 | "fcxs: 0x%02X schxs: 0x%02X\n", req, | 3230 | "CS:%02X fcxs:%02X schxs:%02X RC:%d\n", |
3243 | scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), | 3231 | req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), |
3244 | scsw_cc(&irb->scsw), req->intrc, | 3232 | scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw), |
3245 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs); | 3233 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), |
3234 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs, | ||
3235 | req ? req->intrc : 0); | ||
3246 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3236 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3247 | " device %s: Failing TCW: %p\n", | 3237 | " device %s: Failing TCW: %p\n", |
3248 | dev_name(&device->cdev->dev), | 3238 | dev_name(&device->cdev->dev), |
@@ -3250,7 +3240,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
3250 | 3240 | ||
3251 | tsb = NULL; | 3241 | tsb = NULL; |
3252 | sense = NULL; | 3242 | sense = NULL; |
3253 | if (irb->scsw.tm.tcw && (irb->scsw.tm.fcxs == 0x01)) | 3243 | if (irb->scsw.tm.tcw && (irb->scsw.tm.fcxs & 0x01)) |
3254 | tsb = tcw_get_tsb( | 3244 | tsb = tcw_get_tsb( |
3255 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); | 3245 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); |
3256 | 3246 | ||
@@ -3348,7 +3338,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
3348 | static void dasd_eckd_dump_sense(struct dasd_device *device, | 3338 | static void dasd_eckd_dump_sense(struct dasd_device *device, |
3349 | struct dasd_ccw_req *req, struct irb *irb) | 3339 | struct dasd_ccw_req *req, struct irb *irb) |
3350 | { | 3340 | { |
3351 | if (req && scsw_is_tm(&req->irb.scsw)) | 3341 | if (scsw_is_tm(&irb->scsw)) |
3352 | dasd_eckd_dump_sense_tcw(device, req, irb); | 3342 | dasd_eckd_dump_sense_tcw(device, req, irb); |
3353 | else | 3343 | else |
3354 | dasd_eckd_dump_sense_ccw(device, req, irb); | 3344 | dasd_eckd_dump_sense_ccw(device, req, irb); |