aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_eckd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r--drivers/s390/block/dasd_eckd.c145
1 files changed, 74 insertions, 71 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 7d5a6cee4bd8..7565d30f8c2f 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1522,6 +1522,40 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp)
1522} 1522}
1523 1523
1524/* 1524/*
1525 * Dump the range of CCWs into 'page' buffer
1526 * and return number of printed chars.
1527 */
1528static inline int
1529dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
1530{
1531 int len, count;
1532 char *datap;
1533
1534 len = 0;
1535 while (from <= to) {
1536 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1537 " CCW %p: %08X %08X DAT:",
1538 from, ((int *) from)[0], ((int *) from)[1]);
1539
1540 /* get pointer to data (consider IDALs) */
1541 if (from->flags & CCW_FLAG_IDA)
1542 datap = (char *) *((addr_t *) (addr_t) from->cda);
1543 else
1544 datap = (char *) ((addr_t) from->cda);
1545
1546 /* dump data (max 32 bytes) */
1547 for (count = 0; count < from->count && count < 32; count++) {
1548 if (count % 8 == 0) len += sprintf(page + len, " ");
1549 if (count % 4 == 0) len += sprintf(page + len, " ");
1550 len += sprintf(page + len, "%02x", datap[count]);
1551 }
1552 len += sprintf(page + len, "\n");
1553 from++;
1554 }
1555 return len;
1556}
1557
1558/*
1525 * Print sense data and related channel program. 1559 * Print sense data and related channel program.
1526 * Parts are printed because printk buffer is only 1024 bytes. 1560 * Parts are printed because printk buffer is only 1024 bytes.
1527 */ 1561 */
@@ -1530,8 +1564,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
1530 struct irb *irb) 1564 struct irb *irb)
1531{ 1565{
1532 char *page; 1566 char *page;
1533 struct ccw1 *act, *end, *last; 1567 struct ccw1 *first, *last, *fail, *from, *to;
1534 int len, sl, sct, count; 1568 int len, sl, sct;
1535 1569
1536 page = (char *) get_zeroed_page(GFP_ATOMIC); 1570 page = (char *) get_zeroed_page(GFP_ATOMIC);
1537 if (page == NULL) { 1571 if (page == NULL) {
@@ -1539,7 +1573,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
1539 "No memory to dump sense data"); 1573 "No memory to dump sense data");
1540 return; 1574 return;
1541 } 1575 }
1542 len = sprintf(page, KERN_ERR PRINTK_HEADER 1576 /* dump the sense data */
1577 len = sprintf(page, KERN_ERR PRINTK_HEADER
1543 " I/O status report for device %s:\n", 1578 " I/O status report for device %s:\n",
1544 device->cdev->dev.bus_id); 1579 device->cdev->dev.bus_id);
1545 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 1580 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
@@ -1564,87 +1599,55 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
1564 1599
1565 if (irb->ecw[27] & DASD_SENSE_BIT_0) { 1600 if (irb->ecw[27] & DASD_SENSE_BIT_0) {
1566 /* 24 Byte Sense Data */ 1601 /* 24 Byte Sense Data */
1567 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 1602 sprintf(page + len, KERN_ERR PRINTK_HEADER
1568 " 24 Byte: %x MSG %x, " 1603 " 24 Byte: %x MSG %x, "
1569 "%s MSGb to SYSOP\n", 1604 "%s MSGb to SYSOP\n",
1570 irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, 1605 irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
1571 irb->ecw[1] & 0x10 ? "" : "no"); 1606 irb->ecw[1] & 0x10 ? "" : "no");
1572 } else { 1607 } else {
1573 /* 32 Byte Sense Data */ 1608 /* 32 Byte Sense Data */
1574 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 1609 sprintf(page + len, KERN_ERR PRINTK_HEADER
1575 " 32 Byte: Format: %x " 1610 " 32 Byte: Format: %x "
1576 "Exception class %x\n", 1611 "Exception class %x\n",
1577 irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); 1612 irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
1578 } 1613 }
1579 } else { 1614 } else {
1580 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 1615 sprintf(page + len, KERN_ERR PRINTK_HEADER
1581 " SORRY - NO VALID SENSE AVAILABLE\n"); 1616 " SORRY - NO VALID SENSE AVAILABLE\n");
1582 } 1617 }
1583 MESSAGE_LOG(KERN_ERR, "%s", 1618 printk("%s", page);
1584 page + sizeof(KERN_ERR PRINTK_HEADER)); 1619
1585 1620 /* dump the Channel Program (max 140 Bytes per line) */
1586 /* dump the Channel Program */ 1621 /* Count CCW and print first CCWs (maximum 1024 % 140 = 7) */
1587 /* print first CCWs (maximum 8) */ 1622 first = req->cpaddr;
1588 act = req->cpaddr; 1623 for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
1589 for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); 1624 to = min(first + 6, last);
1590 end = min(act + 8, last); 1625 len = sprintf(page, KERN_ERR PRINTK_HEADER
1591 len = sprintf(page, KERN_ERR PRINTK_HEADER
1592 " Related CP in req: %p\n", req); 1626 " Related CP in req: %p\n", req);
1593 while (act <= end) { 1627 dasd_eckd_dump_ccw_range(first, to, page + len);
1594 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 1628 printk("%s", page);
1595 " CCW %p: %08X %08X DAT:",
1596 act, ((int *) act)[0], ((int *) act)[1]);
1597 for (count = 0; count < 32 && count < act->count;
1598 count += sizeof(int))
1599 len += sprintf(page + len, " %08X",
1600 ((int *) (addr_t) act->cda)
1601 [(count>>2)]);
1602 len += sprintf(page + len, "\n");
1603 act++;
1604 }
1605 MESSAGE_LOG(KERN_ERR, "%s",
1606 page + sizeof(KERN_ERR PRINTK_HEADER));
1607 1629
1608 /* print failing CCW area */ 1630 /* print failing CCW area (maximum 4) */
1631 /* scsw->cda is either valid or zero */
1609 len = 0; 1632 len = 0;
1610 if (act < ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) { 1633 from = ++to;
1611 act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2; 1634 fail = (struct ccw1 *)(addr_t) irb->scsw.cpa; /* failing CCW */
1612 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); 1635 if (from < fail - 2) {
1613 } 1636 from = fail - 2; /* there is a gap - print header */
1614 end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last); 1637 len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n");
1615 while (act <= end) {
1616 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1617 " CCW %p: %08X %08X DAT:",
1618 act, ((int *) act)[0], ((int *) act)[1]);
1619 for (count = 0; count < 32 && count < act->count;
1620 count += sizeof(int))
1621 len += sprintf(page + len, " %08X",
1622 ((int *) (addr_t) act->cda)
1623 [(count>>2)]);
1624 len += sprintf(page + len, "\n");
1625 act++;
1626 } 1638 }
1639 to = min(fail + 1, last);
1640 len += dasd_eckd_dump_ccw_range(from, to, page + len);
1627 1641
1628 /* print last CCWs */ 1642 /* print last CCWs (maximum 2) */
1629 if (act < last - 2) { 1643 from = max(from, ++to);
1630 act = last - 2; 1644 if (from < last - 1) {
1645 from = last - 1; /* there is a gap - print header */
1631 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); 1646 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
1632 } 1647 }
1633 while (act <= last) { 1648 len += dasd_eckd_dump_ccw_range(from, last, page + len);
1634 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1635 " CCW %p: %08X %08X DAT:",
1636 act, ((int *) act)[0], ((int *) act)[1]);
1637 for (count = 0; count < 32 && count < act->count;
1638 count += sizeof(int))
1639 len += sprintf(page + len, " %08X",
1640 ((int *) (addr_t) act->cda)
1641 [(count>>2)]);
1642 len += sprintf(page + len, "\n");
1643 act++;
1644 }
1645 if (len > 0) 1649 if (len > 0)
1646 MESSAGE_LOG(KERN_ERR, "%s", 1650 printk("%s", page);
1647 page + sizeof(KERN_ERR PRINTK_HEADER));
1648 free_page((unsigned long) page); 1651 free_page((unsigned long) page);
1649} 1652}
1650 1653