aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2011-10-30 10:16:04 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 10:16:15 -0400
commitde400d6b78d15a73023485f050bc6b1709dc7a79 (patch)
tree2d2e7233a76982db4cf12ff0859054a33e46a911 /drivers/s390/cio
parentce949717b559709423c1ef716a9db16d1dcadaed (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')
-rw-r--r--drivers/s390/cio/cio.c17
-rw-r--r--drivers/s390/cio/device.c13
-rw-r--r--drivers/s390/cio/device.h13
-rw-r--r--drivers/s390/cio/io_sch.h2
-rw-r--r--drivers/s390/cio/qdio_main.c2
5 files changed, 41 insertions, 6 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index eb3140ee821e..5586c1376cb0 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -622,6 +622,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
622 sch = (struct subchannel *)(unsigned long)tpi_info->intparm; 622 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
623 if (!sch) { 623 if (!sch) {
624 /* Clear pending interrupt condition. */ 624 /* Clear pending interrupt condition. */
625 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
625 tsch(tpi_info->schid, irb); 626 tsch(tpi_info->schid, irb);
626 continue; 627 continue;
627 } 628 }
@@ -634,7 +635,10 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
634 /* Call interrupt handler if there is one. */ 635 /* Call interrupt handler if there is one. */
635 if (sch->driver && sch->driver->irq) 636 if (sch->driver && sch->driver->irq)
636 sch->driver->irq(sch); 637 sch->driver->irq(sch);
637 } 638 else
639 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
640 } else
641 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
638 spin_unlock(sch->lock); 642 spin_unlock(sch->lock);
639 /* 643 /*
640 * Are more interrupts pending? 644 * Are more interrupts pending?
@@ -667,18 +671,23 @@ static int cio_tpi(void)
667 tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; 671 tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
668 if (tpi(NULL) != 1) 672 if (tpi(NULL) != 1)
669 return 0; 673 return 0;
674 kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
670 if (tpi_info->adapter_IO) { 675 if (tpi_info->adapter_IO) {
671 do_adapter_IO(tpi_info->isc); 676 do_adapter_IO(tpi_info->isc);
672 return 1; 677 return 1;
673 } 678 }
674 irb = (struct irb *)&S390_lowcore.irb; 679 irb = (struct irb *)&S390_lowcore.irb;
675 /* Store interrupt response block to lowcore. */ 680 /* Store interrupt response block to lowcore. */
676 if (tsch(tpi_info->schid, irb) != 0) 681 if (tsch(tpi_info->schid, irb) != 0) {
677 /* Not status pending or not operational. */ 682 /* Not status pending or not operational. */
683 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
678 return 1; 684 return 1;
685 }
679 sch = (struct subchannel *)(unsigned long)tpi_info->intparm; 686 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
680 if (!sch) 687 if (!sch) {
688 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
681 return 1; 689 return 1;
690 }
682 irq_context = in_interrupt(); 691 irq_context = in_interrupt();
683 if (!irq_context) 692 if (!irq_context)
684 local_bh_disable(); 693 local_bh_disable();
@@ -687,6 +696,8 @@ static int cio_tpi(void)
687 memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); 696 memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
688 if (sch->driver && sch->driver->irq) 697 if (sch->driver && sch->driver->irq)
689 sch->driver->irq(sch); 698 sch->driver->irq(sch);
699 else
700 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
690 spin_unlock(sch->lock); 701 spin_unlock(sch->lock);
691 irq_exit(); 702 irq_exit();
692 if (!irq_context) 703 if (!irq_context)
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
1015void io_subchannel_init_config(struct subchannel *sch) 1019void 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
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 0b7245c72d5e..179824b3082f 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -5,6 +5,7 @@
5#include <linux/atomic.h> 5#include <linux/atomic.h>
6#include <linux/wait.h> 6#include <linux/wait.h>
7#include <linux/notifier.h> 7#include <linux/notifier.h>
8#include <linux/kernel_stat.h>
8#include "io_sch.h" 9#include "io_sch.h"
9 10
10/* 11/*
@@ -56,7 +57,17 @@ extern fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS];
56static inline void 57static inline void
57dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event) 58dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event)
58{ 59{
59 dev_jumptable[cdev->private->state][dev_event](cdev, dev_event); 60 int state = cdev->private->state;
61
62 if (dev_event == DEV_EVENT_INTERRUPT) {
63 if (state == DEV_STATE_ONLINE)
64 kstat_cpu(smp_processor_id()).
65 irqs[cdev->private->int_class]++;
66 else if (state != DEV_STATE_CMFCHANGE &&
67 state != DEV_STATE_CMFUPDATE)
68 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
69 }
70 dev_jumptable[state][dev_event](cdev, dev_event);
60} 71}
61 72
62/* 73/*
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index ba31ad88f4f7..2ebb492a5c17 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -4,6 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <asm/schid.h> 5#include <asm/schid.h>
6#include <asm/ccwdev.h> 6#include <asm/ccwdev.h>
7#include <asm/irq.h>
7#include "css.h" 8#include "css.h"
8#include "orb.h" 9#include "orb.h"
9 10
@@ -157,6 +158,7 @@ struct ccw_device_private {
157 struct list_head cmb_list; /* list of measured devices */ 158 struct list_head cmb_list; /* list of measured devices */
158 u64 cmb_start_time; /* clock value of cmb reset */ 159 u64 cmb_start_time; /* clock value of cmb reset */
159 void *cmb_wait; /* deferred cmb enable/disable */ 160 void *cmb_wait; /* deferred cmb enable/disable */
161 enum interruption_class int_class;
160}; 162};
161 163
162static inline int rsch(struct subchannel_id schid) 164static inline int rsch(struct subchannel_id schid)
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 6547ff469410..7ded1b26fd25 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -15,7 +15,6 @@
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/gfp.h> 16#include <linux/gfp.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/kernel_stat.h>
19#include <linux/atomic.h> 18#include <linux/atomic.h>
20#include <asm/debug.h> 19#include <asm/debug.h>
21#include <asm/qdio.h> 20#include <asm/qdio.h>
@@ -1128,7 +1127,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
1128 return; 1127 return;
1129 } 1128 }
1130 1129
1131 kstat_cpu(smp_processor_id()).irqs[IOINT_QDI]++;
1132 if (irq_ptr->perf_stat_enabled) 1130 if (irq_ptr->perf_stat_enabled)
1133 irq_ptr->perf_stat.qdio_int++; 1131 irq_ptr->perf_stat.qdio_int++;
1134 1132