diff options
author | Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | 2011-10-30 10:16:04 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-10-30 10:16:15 -0400 |
commit | de400d6b78d15a73023485f050bc6b1709dc7a79 (patch) | |
tree | 2d2e7233a76982db4cf12ff0859054a33e46a911 /drivers/s390/cio/device.c | |
parent | ce949717b559709423c1ef716a9db16d1dcadaed (diff) |
[S390] fix mismatch in summation of I/O IRQ statistics
Current IRQ statistics support does not show detail counts for I/O
interrupts which are processed internally only. The result is a
summation count which is way off such as this one:
CPU0 CPU1 CPU2
I/O: 1331 710 442
[...]
QAI: 15 16 16 [I/O] QDIO Adapter Interrupt
QDI: 1 0 0 [I/O] QDIO Interrupt
DAS: 706 645 381 [I/O] DASD
C15: 26 10 0 [I/O] 3215
C70: 0 0 0 [I/O] 3270
TAP: 0 0 0 [I/O] Tape
VMR: 0 0 0 [I/O] Unit Record Devices
LCS: 0 0 0 [I/O] LCS
CLW: 0 0 0 [I/O] CLAW
CTC: 0 0 0 [I/O] CTC
APB: 0 0 0 [I/O] AP Bus
Fix this by moving I/O interrupt accounting into the common I/O layer.
Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r-- | drivers/s390/cio/device.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 8e04c00cf0ad..d734f4a0ecac 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
24 | #include <linux/kernel_stat.h> | ||
24 | 25 | ||
25 | #include <asm/ccwdev.h> | 26 | #include <asm/ccwdev.h> |
26 | #include <asm/cio.h> | 27 | #include <asm/cio.h> |
@@ -747,6 +748,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch, | |||
747 | struct ccw_device *cdev) | 748 | struct ccw_device *cdev) |
748 | { | 749 | { |
749 | cdev->private->cdev = cdev; | 750 | cdev->private->cdev = cdev; |
751 | cdev->private->int_class = IOINT_CIO; | ||
750 | atomic_set(&cdev->private->onoff, 0); | 752 | atomic_set(&cdev->private->onoff, 0); |
751 | cdev->dev.parent = &sch->dev; | 753 | cdev->dev.parent = &sch->dev; |
752 | cdev->dev.release = ccw_device_release; | 754 | cdev->dev.release = ccw_device_release; |
@@ -1010,6 +1012,8 @@ static void io_subchannel_irq(struct subchannel *sch) | |||
1010 | CIO_TRACE_EVENT(6, dev_name(&sch->dev)); | 1012 | CIO_TRACE_EVENT(6, dev_name(&sch->dev)); |
1011 | if (cdev) | 1013 | if (cdev) |
1012 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); | 1014 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); |
1015 | else | ||
1016 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | ||
1013 | } | 1017 | } |
1014 | 1018 | ||
1015 | void io_subchannel_init_config(struct subchannel *sch) | 1019 | void io_subchannel_init_config(struct subchannel *sch) |
@@ -1621,6 +1625,7 @@ ccw_device_probe_console(void) | |||
1621 | memset(&console_private, 0, sizeof(struct ccw_device_private)); | 1625 | memset(&console_private, 0, sizeof(struct ccw_device_private)); |
1622 | console_cdev.private = &console_private; | 1626 | console_cdev.private = &console_private; |
1623 | console_private.cdev = &console_cdev; | 1627 | console_private.cdev = &console_cdev; |
1628 | console_private.int_class = IOINT_CIO; | ||
1624 | ret = ccw_device_console_enable(&console_cdev, sch); | 1629 | ret = ccw_device_console_enable(&console_cdev, sch); |
1625 | if (ret) { | 1630 | if (ret) { |
1626 | cio_release_console(); | 1631 | cio_release_console(); |
@@ -1702,11 +1707,18 @@ ccw_device_probe (struct device *dev) | |||
1702 | int ret; | 1707 | int ret; |
1703 | 1708 | ||
1704 | cdev->drv = cdrv; /* to let the driver call _set_online */ | 1709 | cdev->drv = cdrv; /* to let the driver call _set_online */ |
1710 | /* Note: we interpret class 0 in this context as an uninitialized | ||
1711 | * field since it translates to a non-I/O interrupt class. */ | ||
1712 | if (cdrv->int_class != 0) | ||
1713 | cdev->private->int_class = cdrv->int_class; | ||
1714 | else | ||
1715 | cdev->private->int_class = IOINT_CIO; | ||
1705 | 1716 | ||
1706 | ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; | 1717 | ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; |
1707 | 1718 | ||
1708 | if (ret) { | 1719 | if (ret) { |
1709 | cdev->drv = NULL; | 1720 | cdev->drv = NULL; |
1721 | cdev->private->int_class = IOINT_CIO; | ||
1710 | return ret; | 1722 | return ret; |
1711 | } | 1723 | } |
1712 | 1724 | ||
@@ -1740,6 +1752,7 @@ ccw_device_remove (struct device *dev) | |||
1740 | } | 1752 | } |
1741 | ccw_device_set_timeout(cdev, 0); | 1753 | ccw_device_set_timeout(cdev, 0); |
1742 | cdev->drv = NULL; | 1754 | cdev->drv = NULL; |
1755 | cdev->private->int_class = IOINT_CIO; | ||
1743 | return 0; | 1756 | return 0; |
1744 | } | 1757 | } |
1745 | 1758 | ||