Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: [S390] Update default configuration. [S390] Have param.h simply include <asm-generic/param.h>. [S390] qdio: convert global statistics to per-device stats
This commit is contained in:
Коммит
741f21e811
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.31
|
# Linux kernel version: 2.6.33-rc2
|
||||||
# Tue Sep 22 17:43:13 2009
|
# Mon Jan 4 09:03:07 2010
|
||||||
#
|
#
|
||||||
CONFIG_SCHED_MC=y
|
CONFIG_SCHED_MC=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
|
@ -51,6 +51,7 @@ CONFIG_AUDIT=y
|
||||||
#
|
#
|
||||||
CONFIG_TREE_RCU=y
|
CONFIG_TREE_RCU=y
|
||||||
# CONFIG_TREE_PREEMPT_RCU is not set
|
# CONFIG_TREE_PREEMPT_RCU is not set
|
||||||
|
# CONFIG_TINY_RCU is not set
|
||||||
# CONFIG_RCU_TRACE is not set
|
# CONFIG_RCU_TRACE is not set
|
||||||
CONFIG_RCU_FANOUT=64
|
CONFIG_RCU_FANOUT=64
|
||||||
# CONFIG_RCU_FANOUT_EXACT is not set
|
# CONFIG_RCU_FANOUT_EXACT is not set
|
||||||
|
@ -113,7 +114,6 @@ CONFIG_HAVE_PERF_EVENTS=y
|
||||||
# CONFIG_PERF_EVENTS is not set
|
# CONFIG_PERF_EVENTS is not set
|
||||||
# CONFIG_PERF_COUNTERS is not set
|
# CONFIG_PERF_COUNTERS is not set
|
||||||
CONFIG_VM_EVENT_COUNTERS=y
|
CONFIG_VM_EVENT_COUNTERS=y
|
||||||
# CONFIG_STRIP_ASM_SYMS is not set
|
|
||||||
# CONFIG_COMPAT_BRK is not set
|
# CONFIG_COMPAT_BRK is not set
|
||||||
CONFIG_SLAB=y
|
CONFIG_SLAB=y
|
||||||
# CONFIG_SLUB is not set
|
# CONFIG_SLUB is not set
|
||||||
|
@ -149,21 +149,78 @@ CONFIG_STOP_MACHINE=y
|
||||||
CONFIG_BLOCK=y
|
CONFIG_BLOCK=y
|
||||||
CONFIG_BLK_DEV_BSG=y
|
CONFIG_BLK_DEV_BSG=y
|
||||||
# CONFIG_BLK_DEV_INTEGRITY is not set
|
# CONFIG_BLK_DEV_INTEGRITY is not set
|
||||||
|
# CONFIG_BLK_CGROUP is not set
|
||||||
CONFIG_BLOCK_COMPAT=y
|
CONFIG_BLOCK_COMPAT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# IO Schedulers
|
# IO Schedulers
|
||||||
#
|
#
|
||||||
CONFIG_IOSCHED_NOOP=y
|
CONFIG_IOSCHED_NOOP=y
|
||||||
CONFIG_IOSCHED_AS=y
|
|
||||||
CONFIG_IOSCHED_DEADLINE=y
|
CONFIG_IOSCHED_DEADLINE=y
|
||||||
CONFIG_IOSCHED_CFQ=y
|
CONFIG_IOSCHED_CFQ=y
|
||||||
# CONFIG_DEFAULT_AS is not set
|
# CONFIG_CFQ_GROUP_IOSCHED is not set
|
||||||
CONFIG_DEFAULT_DEADLINE=y
|
CONFIG_DEFAULT_DEADLINE=y
|
||||||
# CONFIG_DEFAULT_CFQ is not set
|
# CONFIG_DEFAULT_CFQ is not set
|
||||||
# CONFIG_DEFAULT_NOOP is not set
|
# CONFIG_DEFAULT_NOOP is not set
|
||||||
CONFIG_DEFAULT_IOSCHED="deadline"
|
CONFIG_DEFAULT_IOSCHED="deadline"
|
||||||
CONFIG_PREEMPT_NOTIFIERS=y
|
CONFIG_PREEMPT_NOTIFIERS=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_LOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
|
||||||
|
CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_TRYLOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_LOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_LOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_UNLOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
|
||||||
|
CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_TRYLOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_LOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
|
||||||
|
CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
|
||||||
|
# CONFIG_INLINE_SPIN_TRYLOCK is not set
|
||||||
|
# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_SPIN_LOCK is not set
|
||||||
|
# CONFIG_INLINE_SPIN_LOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
|
||||||
|
# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
|
||||||
|
# CONFIG_INLINE_SPIN_UNLOCK is not set
|
||||||
|
# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
|
||||||
|
# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
|
||||||
|
# CONFIG_INLINE_READ_TRYLOCK is not set
|
||||||
|
# CONFIG_INLINE_READ_LOCK is not set
|
||||||
|
# CONFIG_INLINE_READ_LOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_READ_LOCK_IRQ is not set
|
||||||
|
# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
|
||||||
|
# CONFIG_INLINE_READ_UNLOCK is not set
|
||||||
|
# CONFIG_INLINE_READ_UNLOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
|
||||||
|
# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
|
||||||
|
# CONFIG_INLINE_WRITE_TRYLOCK is not set
|
||||||
|
# CONFIG_INLINE_WRITE_LOCK is not set
|
||||||
|
# CONFIG_INLINE_WRITE_LOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
|
||||||
|
# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
|
||||||
|
# CONFIG_INLINE_WRITE_UNLOCK is not set
|
||||||
|
# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
|
||||||
|
# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
|
||||||
|
# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
|
||||||
|
# CONFIG_MUTEX_SPIN_ON_OWNER is not set
|
||||||
CONFIG_FREEZER=y
|
CONFIG_FREEZER=y
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -227,14 +284,13 @@ CONFIG_MEMORY_HOTPLUG=y
|
||||||
CONFIG_MEMORY_HOTPLUG_SPARSE=y
|
CONFIG_MEMORY_HOTPLUG_SPARSE=y
|
||||||
CONFIG_MEMORY_HOTREMOVE=y
|
CONFIG_MEMORY_HOTREMOVE=y
|
||||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
CONFIG_SPLIT_PTLOCK_CPUS=999999
|
||||||
CONFIG_MIGRATION=y
|
CONFIG_MIGRATION=y
|
||||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||||
CONFIG_ZONE_DMA_FLAG=1
|
CONFIG_ZONE_DMA_FLAG=1
|
||||||
CONFIG_BOUNCE=y
|
CONFIG_BOUNCE=y
|
||||||
CONFIG_VIRT_TO_BUS=y
|
CONFIG_VIRT_TO_BUS=y
|
||||||
CONFIG_HAVE_MLOCK=y
|
# CONFIG_KSM is not set
|
||||||
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
|
|
||||||
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
|
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -339,6 +395,7 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
|
||||||
CONFIG_INET6_XFRM_MODE_BEET=y
|
CONFIG_INET6_XFRM_MODE_BEET=y
|
||||||
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
|
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
|
||||||
CONFIG_IPV6_SIT=y
|
CONFIG_IPV6_SIT=y
|
||||||
|
# CONFIG_IPV6_SIT_6RD is not set
|
||||||
CONFIG_IPV6_NDISC_NODETYPE=y
|
CONFIG_IPV6_NDISC_NODETYPE=y
|
||||||
# CONFIG_IPV6_TUNNEL is not set
|
# CONFIG_IPV6_TUNNEL is not set
|
||||||
# CONFIG_IPV6_MULTIPLE_TABLES is not set
|
# CONFIG_IPV6_MULTIPLE_TABLES is not set
|
||||||
|
@ -504,6 +561,10 @@ CONFIG_BLK_DEV=y
|
||||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||||
CONFIG_BLK_DEV_LOOP=m
|
CONFIG_BLK_DEV_LOOP=m
|
||||||
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
|
||||||
|
#
|
||||||
CONFIG_BLK_DEV_NBD=m
|
CONFIG_BLK_DEV_NBD=m
|
||||||
# CONFIG_BLK_DEV_OSD is not set
|
# CONFIG_BLK_DEV_OSD is not set
|
||||||
CONFIG_BLK_DEV_RAM=y
|
CONFIG_BLK_DEV_RAM=y
|
||||||
|
@ -710,7 +771,6 @@ CONFIG_S390_VMUR=m
|
||||||
# CONFIG_PPS is not set
|
# CONFIG_PPS is not set
|
||||||
# CONFIG_POWER_SUPPLY is not set
|
# CONFIG_POWER_SUPPLY is not set
|
||||||
# CONFIG_THERMAL is not set
|
# CONFIG_THERMAL is not set
|
||||||
# CONFIG_THERMAL_HWMON is not set
|
|
||||||
# CONFIG_WATCHDOG is not set
|
# CONFIG_WATCHDOG is not set
|
||||||
# CONFIG_REGULATOR is not set
|
# CONFIG_REGULATOR is not set
|
||||||
# CONFIG_MEMSTICK is not set
|
# CONFIG_MEMSTICK is not set
|
||||||
|
@ -864,6 +924,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
|
||||||
CONFIG_ENABLE_MUST_CHECK=y
|
CONFIG_ENABLE_MUST_CHECK=y
|
||||||
CONFIG_FRAME_WARN=2048
|
CONFIG_FRAME_WARN=2048
|
||||||
CONFIG_MAGIC_SYSRQ=y
|
CONFIG_MAGIC_SYSRQ=y
|
||||||
|
# CONFIG_STRIP_ASM_SYMS is not set
|
||||||
# CONFIG_UNUSED_SYMBOLS is not set
|
# CONFIG_UNUSED_SYMBOLS is not set
|
||||||
CONFIG_DEBUG_FS=y
|
CONFIG_DEBUG_FS=y
|
||||||
# CONFIG_HEADERS_CHECK is not set
|
# CONFIG_HEADERS_CHECK is not set
|
||||||
|
@ -931,7 +992,6 @@ CONFIG_BRANCH_PROFILE_NONE=y
|
||||||
CONFIG_SAMPLES=y
|
CONFIG_SAMPLES=y
|
||||||
# CONFIG_SAMPLE_KOBJECT is not set
|
# CONFIG_SAMPLE_KOBJECT is not set
|
||||||
# CONFIG_SAMPLE_KPROBES is not set
|
# CONFIG_SAMPLE_KPROBES is not set
|
||||||
# CONFIG_KMEMCHECK is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Security options
|
# Security options
|
||||||
|
@ -939,7 +999,11 @@ CONFIG_SAMPLES=y
|
||||||
# CONFIG_KEYS is not set
|
# CONFIG_KEYS is not set
|
||||||
# CONFIG_SECURITY is not set
|
# CONFIG_SECURITY is not set
|
||||||
# CONFIG_SECURITYFS is not set
|
# CONFIG_SECURITYFS is not set
|
||||||
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
|
# CONFIG_DEFAULT_SECURITY_SELINUX is not set
|
||||||
|
# CONFIG_DEFAULT_SECURITY_SMACK is not set
|
||||||
|
# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
|
||||||
|
CONFIG_DEFAULT_SECURITY_DAC=y
|
||||||
|
CONFIG_DEFAULT_SECURITY=""
|
||||||
CONFIG_CRYPTO=y
|
CONFIG_CRYPTO=y
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,30 +1,6 @@
|
||||||
/*
|
|
||||||
* include/asm-s390/param.h
|
|
||||||
*
|
|
||||||
* S390 version
|
|
||||||
*
|
|
||||||
* Derived from "include/asm-i386/param.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ASMS390_PARAM_H
|
#ifndef _ASMS390_PARAM_H
|
||||||
#define _ASMS390_PARAM_H
|
#define _ASMS390_PARAM_H
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#include <asm-generic/param.h>
|
||||||
# define HZ CONFIG_HZ /* Internal kernel timer frequency */
|
|
||||||
# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
|
|
||||||
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HZ
|
#endif /* _ASMS390_PARAM_H */
|
||||||
#define HZ 100
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define EXEC_PAGESIZE 4096
|
|
||||||
|
|
||||||
#ifndef NOGROUP
|
|
||||||
#define NOGROUP (-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAXHOSTNAMELEN 64 /* max length of hostname */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -10,5 +10,5 @@ obj-y += ccw_device.o cmf.o
|
||||||
obj-$(CONFIG_CHSC_SCH) += chsc_sch.o
|
obj-$(CONFIG_CHSC_SCH) += chsc_sch.o
|
||||||
obj-$(CONFIG_CCWGROUP) += ccwgroup.o
|
obj-$(CONFIG_CCWGROUP) += ccwgroup.o
|
||||||
|
|
||||||
qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_perf.o qdio_setup.o
|
qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_setup.o
|
||||||
obj-$(CONFIG_QDIO) += qdio.o
|
obj-$(CONFIG_QDIO) += qdio.o
|
||||||
|
|
|
@ -182,6 +182,34 @@ struct scssc_area {
|
||||||
u32:32;
|
u32:32;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct qdio_dev_perf_stat {
|
||||||
|
unsigned int adapter_int;
|
||||||
|
unsigned int qdio_int;
|
||||||
|
unsigned int pci_request_int;
|
||||||
|
|
||||||
|
unsigned int tasklet_inbound;
|
||||||
|
unsigned int tasklet_inbound_resched;
|
||||||
|
unsigned int tasklet_inbound_resched2;
|
||||||
|
unsigned int tasklet_outbound;
|
||||||
|
|
||||||
|
unsigned int siga_read;
|
||||||
|
unsigned int siga_write;
|
||||||
|
unsigned int siga_sync;
|
||||||
|
|
||||||
|
unsigned int inbound_call;
|
||||||
|
unsigned int inbound_handler;
|
||||||
|
unsigned int stop_polling;
|
||||||
|
unsigned int inbound_queue_full;
|
||||||
|
unsigned int outbound_call;
|
||||||
|
unsigned int outbound_handler;
|
||||||
|
unsigned int fast_requeue;
|
||||||
|
unsigned int target_full;
|
||||||
|
unsigned int eqbs;
|
||||||
|
unsigned int eqbs_partial;
|
||||||
|
unsigned int sqbs;
|
||||||
|
unsigned int sqbs_partial;
|
||||||
|
};
|
||||||
|
|
||||||
struct qdio_input_q {
|
struct qdio_input_q {
|
||||||
/* input buffer acknowledgement flag */
|
/* input buffer acknowledgement flag */
|
||||||
int polling;
|
int polling;
|
||||||
|
@ -269,6 +297,7 @@ struct qdio_irq {
|
||||||
u32 *dsci; /* address of device state change indicator */
|
u32 *dsci; /* address of device state change indicator */
|
||||||
struct ccw_device *cdev;
|
struct ccw_device *cdev;
|
||||||
struct dentry *debugfs_dev;
|
struct dentry *debugfs_dev;
|
||||||
|
struct dentry *debugfs_perf;
|
||||||
|
|
||||||
unsigned long int_parm;
|
unsigned long int_parm;
|
||||||
struct subchannel_id schid;
|
struct subchannel_id schid;
|
||||||
|
@ -286,9 +315,10 @@ struct qdio_irq {
|
||||||
struct ciw aqueue;
|
struct ciw aqueue;
|
||||||
|
|
||||||
struct qdio_ssqd_desc ssqd_desc;
|
struct qdio_ssqd_desc ssqd_desc;
|
||||||
|
|
||||||
void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
|
void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
|
||||||
|
|
||||||
|
struct qdio_dev_perf_stat perf_stat;
|
||||||
|
int perf_stat_enabled;
|
||||||
/*
|
/*
|
||||||
* Warning: Leave these members together at the end so they won't be
|
* Warning: Leave these members together at the end so they won't be
|
||||||
* cleared in qdio_setup_irq.
|
* cleared in qdio_setup_irq.
|
||||||
|
@ -311,6 +341,10 @@ struct qdio_irq {
|
||||||
(irq->qib.qfmt == QDIO_IQDIO_QFMT || \
|
(irq->qib.qfmt == QDIO_IQDIO_QFMT || \
|
||||||
css_general_characteristics.aif_osa)
|
css_general_characteristics.aif_osa)
|
||||||
|
|
||||||
|
#define qperf(qdev,attr) qdev->perf_stat.attr
|
||||||
|
#define qperf_inc(q,attr) if (q->irq_ptr->perf_stat_enabled) \
|
||||||
|
q->irq_ptr->perf_stat.attr++
|
||||||
|
|
||||||
/* the highest iqdio queue is used for multicast */
|
/* the highest iqdio queue is used for multicast */
|
||||||
static inline int multicast_outbound(struct qdio_q *q)
|
static inline int multicast_outbound(struct qdio_q *q)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,13 +55,11 @@ static int qstat_show(struct seq_file *m, void *v)
|
||||||
if (!q)
|
if (!q)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci);
|
seq_printf(m, "DSCI: %d nr_used: %d\n",
|
||||||
seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used));
|
*(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
|
||||||
seq_printf(m, "ftc: %d\n", q->first_to_check);
|
seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
|
||||||
seq_printf(m, "last_move: %d\n", q->last_move);
|
seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
|
||||||
seq_printf(m, "polling: %d\n", q->u.in.polling);
|
q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
|
||||||
seq_printf(m, "ack start: %d\n", q->u.in.ack_start);
|
|
||||||
seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
|
|
||||||
seq_printf(m, "slsb buffer states:\n");
|
seq_printf(m, "slsb buffer states:\n");
|
||||||
seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
|
seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
|
||||||
|
|
||||||
|
@ -110,7 +108,6 @@ static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
|
||||||
|
|
||||||
if (!q)
|
if (!q)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (q->is_input_q)
|
if (q->is_input_q)
|
||||||
xchg(q->irq_ptr->dsci, 1);
|
xchg(q->irq_ptr->dsci, 1);
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
|
@ -134,6 +131,98 @@ static const struct file_operations debugfs_fops = {
|
||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char *qperf_names[] = {
|
||||||
|
"Assumed adapter interrupts",
|
||||||
|
"QDIO interrupts",
|
||||||
|
"Requested PCIs",
|
||||||
|
"Inbound tasklet runs",
|
||||||
|
"Inbound tasklet resched",
|
||||||
|
"Inbound tasklet resched2",
|
||||||
|
"Outbound tasklet runs",
|
||||||
|
"SIGA read",
|
||||||
|
"SIGA write",
|
||||||
|
"SIGA sync",
|
||||||
|
"Inbound calls",
|
||||||
|
"Inbound handler",
|
||||||
|
"Inbound stop_polling",
|
||||||
|
"Inbound queue full",
|
||||||
|
"Outbound calls",
|
||||||
|
"Outbound handler",
|
||||||
|
"Outbound fast_requeue",
|
||||||
|
"Outbound target_full",
|
||||||
|
"QEBSM eqbs",
|
||||||
|
"QEBSM eqbs partial",
|
||||||
|
"QEBSM sqbs",
|
||||||
|
"QEBSM sqbs partial"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int qperf_show(struct seq_file *m, void *v)
|
||||||
|
{
|
||||||
|
struct qdio_irq *irq_ptr = m->private;
|
||||||
|
unsigned int *stat;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!irq_ptr)
|
||||||
|
return 0;
|
||||||
|
if (!irq_ptr->perf_stat_enabled) {
|
||||||
|
seq_printf(m, "disabled\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
stat = (unsigned int *)&irq_ptr->perf_stat;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
|
||||||
|
seq_printf(m, "%26s:\t%u\n",
|
||||||
|
qperf_names[i], *(stat + i));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
|
||||||
|
size_t count, loff_t *off)
|
||||||
|
{
|
||||||
|
struct seq_file *seq = file->private_data;
|
||||||
|
struct qdio_irq *irq_ptr = seq->private;
|
||||||
|
unsigned long val;
|
||||||
|
char buf[8];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!irq_ptr)
|
||||||
|
return 0;
|
||||||
|
if (count >= sizeof(buf))
|
||||||
|
return -EINVAL;
|
||||||
|
if (copy_from_user(&buf, ubuf, count))
|
||||||
|
return -EFAULT;
|
||||||
|
buf[count] = 0;
|
||||||
|
|
||||||
|
ret = strict_strtoul(buf, 10, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
switch (val) {
|
||||||
|
case 0:
|
||||||
|
irq_ptr->perf_stat_enabled = 0;
|
||||||
|
memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
irq_ptr->perf_stat_enabled = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qperf_seq_open(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
return single_open(filp, qperf_show,
|
||||||
|
filp->f_path.dentry->d_inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct file_operations debugfs_perf_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = qperf_seq_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.write = qperf_seq_write,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
|
static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
char name[QDIO_DEBUGFS_NAME_LEN];
|
char name[QDIO_DEBUGFS_NAME_LEN];
|
||||||
|
@ -156,6 +245,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
|
||||||
debugfs_root);
|
debugfs_root);
|
||||||
if (IS_ERR(irq_ptr->debugfs_dev))
|
if (IS_ERR(irq_ptr->debugfs_dev))
|
||||||
irq_ptr->debugfs_dev = NULL;
|
irq_ptr->debugfs_dev = NULL;
|
||||||
|
|
||||||
|
irq_ptr->debugfs_perf = debugfs_create_file("statistics",
|
||||||
|
S_IFREG | S_IRUGO | S_IWUSR,
|
||||||
|
irq_ptr->debugfs_dev, irq_ptr,
|
||||||
|
&debugfs_perf_fops);
|
||||||
|
if (IS_ERR(irq_ptr->debugfs_perf))
|
||||||
|
irq_ptr->debugfs_perf = NULL;
|
||||||
|
|
||||||
for_each_input_queue(irq_ptr, q, i)
|
for_each_input_queue(irq_ptr, q, i)
|
||||||
setup_debugfs_entry(q, cdev);
|
setup_debugfs_entry(q, cdev);
|
||||||
for_each_output_queue(irq_ptr, q, i)
|
for_each_output_queue(irq_ptr, q, i)
|
||||||
|
@ -171,6 +268,7 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd
|
||||||
debugfs_remove(q->debugfs_q);
|
debugfs_remove(q->debugfs_q);
|
||||||
for_each_output_queue(irq_ptr, q, i)
|
for_each_output_queue(irq_ptr, q, i)
|
||||||
debugfs_remove(q->debugfs_q);
|
debugfs_remove(q->debugfs_q);
|
||||||
|
debugfs_remove(irq_ptr->debugfs_perf);
|
||||||
debugfs_remove(irq_ptr->debugfs_dev);
|
debugfs_remove(irq_ptr->debugfs_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "qdio.h"
|
#include "qdio.h"
|
||||||
#include "qdio_debug.h"
|
#include "qdio_debug.h"
|
||||||
#include "qdio_perf.h"
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>,"\
|
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>,"\
|
||||||
"Jan Glauber <jang@linux.vnet.ibm.com>");
|
"Jan Glauber <jang@linux.vnet.ibm.com>");
|
||||||
|
@ -126,7 +125,7 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
BUG_ON(!q->irq_ptr->sch_token);
|
BUG_ON(!q->irq_ptr->sch_token);
|
||||||
qdio_perf_stat_inc(&perf_stats.debug_eqbs_all);
|
qperf_inc(q, eqbs);
|
||||||
|
|
||||||
if (!q->is_input_q)
|
if (!q->is_input_q)
|
||||||
nr += q->irq_ptr->nr_input_qs;
|
nr += q->irq_ptr->nr_input_qs;
|
||||||
|
@ -139,7 +138,7 @@ again:
|
||||||
* buffers later.
|
* buffers later.
|
||||||
*/
|
*/
|
||||||
if ((ccq == 96) && (count != tmp_count)) {
|
if ((ccq == 96) && (count != tmp_count)) {
|
||||||
qdio_perf_stat_inc(&perf_stats.debug_eqbs_incomplete);
|
qperf_inc(q, eqbs_partial);
|
||||||
return (count - tmp_count);
|
return (count - tmp_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +181,7 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
BUG_ON(!q->irq_ptr->sch_token);
|
BUG_ON(!q->irq_ptr->sch_token);
|
||||||
qdio_perf_stat_inc(&perf_stats.debug_sqbs_all);
|
qperf_inc(q, sqbs);
|
||||||
|
|
||||||
if (!q->is_input_q)
|
if (!q->is_input_q)
|
||||||
nr += q->irq_ptr->nr_input_qs;
|
nr += q->irq_ptr->nr_input_qs;
|
||||||
|
@ -191,7 +190,7 @@ again:
|
||||||
rc = qdio_check_ccq(q, ccq);
|
rc = qdio_check_ccq(q, ccq);
|
||||||
if (rc == 1) {
|
if (rc == 1) {
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq);
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq);
|
||||||
qdio_perf_stat_inc(&perf_stats.debug_sqbs_incomplete);
|
qperf_inc(q, sqbs_partial);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -285,7 +284,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
|
||||||
qdio_perf_stat_inc(&perf_stats.siga_sync);
|
qperf_inc(q, siga_sync);
|
||||||
|
|
||||||
cc = do_siga_sync(q->irq_ptr->schid, output, input);
|
cc = do_siga_sync(q->irq_ptr->schid, output, input);
|
||||||
if (cc)
|
if (cc)
|
||||||
|
@ -350,7 +349,7 @@ static inline int qdio_siga_input(struct qdio_q *q)
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr);
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr);
|
||||||
qdio_perf_stat_inc(&perf_stats.siga_in);
|
qperf_inc(q, siga_read);
|
||||||
|
|
||||||
cc = do_siga_input(q->irq_ptr->schid, q->mask);
|
cc = do_siga_input(q->irq_ptr->schid, q->mask);
|
||||||
if (cc)
|
if (cc)
|
||||||
|
@ -382,7 +381,7 @@ static inline void qdio_stop_polling(struct qdio_q *q)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
q->u.in.polling = 0;
|
q->u.in.polling = 0;
|
||||||
qdio_perf_stat_inc(&perf_stats.debug_stop_polling);
|
qperf_inc(q, stop_polling);
|
||||||
|
|
||||||
/* show the card that we are not polling anymore */
|
/* show the card that we are not polling anymore */
|
||||||
if (is_qebsm(q)) {
|
if (is_qebsm(q)) {
|
||||||
|
@ -400,7 +399,7 @@ static void announce_buffer_error(struct qdio_q *q, int count)
|
||||||
/* special handling for no target buffer empty */
|
/* special handling for no target buffer empty */
|
||||||
if ((!q->is_input_q &&
|
if ((!q->is_input_q &&
|
||||||
(q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) {
|
(q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) {
|
||||||
qdio_perf_stat_inc(&perf_stats.outbound_target_full);
|
qperf_inc(q, target_full);
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
|
||||||
q->first_to_check);
|
q->first_to_check);
|
||||||
return;
|
return;
|
||||||
|
@ -487,7 +486,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
|
||||||
inbound_primed(q, count);
|
inbound_primed(q, count);
|
||||||
q->first_to_check = add_buf(q->first_to_check, count);
|
q->first_to_check = add_buf(q->first_to_check, count);
|
||||||
if (atomic_sub(count, &q->nr_buf_used) == 0)
|
if (atomic_sub(count, &q->nr_buf_used) == 0)
|
||||||
qdio_perf_stat_inc(&perf_stats.inbound_queue_full);
|
qperf_inc(q, inbound_queue_full);
|
||||||
break;
|
break;
|
||||||
case SLSB_P_INPUT_ERROR:
|
case SLSB_P_INPUT_ERROR:
|
||||||
announce_buffer_error(q, count);
|
announce_buffer_error(q, count);
|
||||||
|
@ -567,9 +566,10 @@ static void qdio_kick_handler(struct qdio_q *q)
|
||||||
count = sub_buf(end, start);
|
count = sub_buf(end, start);
|
||||||
|
|
||||||
if (q->is_input_q) {
|
if (q->is_input_q) {
|
||||||
qdio_perf_stat_inc(&perf_stats.inbound_handler);
|
qperf_inc(q, inbound_handler);
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
|
||||||
} else
|
} else
|
||||||
|
qperf_inc(q, outbound_handler);
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
|
||||||
start, count);
|
start, count);
|
||||||
|
|
||||||
|
@ -583,24 +583,28 @@ static void qdio_kick_handler(struct qdio_q *q)
|
||||||
|
|
||||||
static void __qdio_inbound_processing(struct qdio_q *q)
|
static void __qdio_inbound_processing(struct qdio_q *q)
|
||||||
{
|
{
|
||||||
qdio_perf_stat_inc(&perf_stats.tasklet_inbound);
|
qperf_inc(q, tasklet_inbound);
|
||||||
again:
|
again:
|
||||||
if (!qdio_inbound_q_moved(q))
|
if (!qdio_inbound_q_moved(q))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qdio_kick_handler(q);
|
qdio_kick_handler(q);
|
||||||
|
|
||||||
if (!qdio_inbound_q_done(q))
|
if (!qdio_inbound_q_done(q)) {
|
||||||
/* means poll time is not yet over */
|
/* means poll time is not yet over */
|
||||||
|
qperf_inc(q, tasklet_inbound_resched);
|
||||||
goto again;
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
qdio_stop_polling(q);
|
qdio_stop_polling(q);
|
||||||
/*
|
/*
|
||||||
* We need to check again to not lose initiative after
|
* We need to check again to not lose initiative after
|
||||||
* resetting the ACK state.
|
* resetting the ACK state.
|
||||||
*/
|
*/
|
||||||
if (!qdio_inbound_q_done(q))
|
if (!qdio_inbound_q_done(q)) {
|
||||||
|
qperf_inc(q, tasklet_inbound_resched2);
|
||||||
goto again;
|
goto again;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void qdio_inbound_processing(unsigned long data)
|
void qdio_inbound_processing(unsigned long data)
|
||||||
|
@ -688,7 +692,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
|
||||||
qdio_perf_stat_inc(&perf_stats.siga_out);
|
qperf_inc(q, siga_write);
|
||||||
|
|
||||||
cc = qdio_siga_output(q, &busy_bit);
|
cc = qdio_siga_output(q, &busy_bit);
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
|
@ -711,7 +715,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
|
||||||
|
|
||||||
static void __qdio_outbound_processing(struct qdio_q *q)
|
static void __qdio_outbound_processing(struct qdio_q *q)
|
||||||
{
|
{
|
||||||
qdio_perf_stat_inc(&perf_stats.tasklet_outbound);
|
qperf_inc(q, tasklet_outbound);
|
||||||
BUG_ON(atomic_read(&q->nr_buf_used) < 0);
|
BUG_ON(atomic_read(&q->nr_buf_used) < 0);
|
||||||
|
|
||||||
if (qdio_outbound_q_moved(q))
|
if (qdio_outbound_q_moved(q))
|
||||||
|
@ -739,12 +743,9 @@ static void __qdio_outbound_processing(struct qdio_q *q)
|
||||||
*/
|
*/
|
||||||
if (qdio_outbound_q_done(q))
|
if (qdio_outbound_q_done(q))
|
||||||
del_timer(&q->u.out.timer);
|
del_timer(&q->u.out.timer);
|
||||||
else {
|
else
|
||||||
if (!timer_pending(&q->u.out.timer)) {
|
if (!timer_pending(&q->u.out.timer))
|
||||||
mod_timer(&q->u.out.timer, jiffies + 10 * HZ);
|
mod_timer(&q->u.out.timer, jiffies + 10 * HZ);
|
||||||
qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sched:
|
sched:
|
||||||
|
@ -784,7 +785,7 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
|
||||||
|
|
||||||
static void __tiqdio_inbound_processing(struct qdio_q *q)
|
static void __tiqdio_inbound_processing(struct qdio_q *q)
|
||||||
{
|
{
|
||||||
qdio_perf_stat_inc(&perf_stats.thinint_inbound);
|
qperf_inc(q, tasklet_inbound);
|
||||||
qdio_sync_after_thinint(q);
|
qdio_sync_after_thinint(q);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -799,7 +800,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
|
||||||
qdio_kick_handler(q);
|
qdio_kick_handler(q);
|
||||||
|
|
||||||
if (!qdio_inbound_q_done(q)) {
|
if (!qdio_inbound_q_done(q)) {
|
||||||
qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop);
|
qperf_inc(q, tasklet_inbound_resched);
|
||||||
if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
|
if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
|
||||||
tasklet_schedule(&q->tasklet);
|
tasklet_schedule(&q->tasklet);
|
||||||
return;
|
return;
|
||||||
|
@ -812,7 +813,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
|
||||||
* resetting the ACK state.
|
* resetting the ACK state.
|
||||||
*/
|
*/
|
||||||
if (!qdio_inbound_q_done(q)) {
|
if (!qdio_inbound_q_done(q)) {
|
||||||
qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2);
|
qperf_inc(q, tasklet_inbound_resched2);
|
||||||
if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
|
if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
|
||||||
tasklet_schedule(&q->tasklet);
|
tasklet_schedule(&q->tasklet);
|
||||||
}
|
}
|
||||||
|
@ -851,8 +852,6 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
|
||||||
if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
|
if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qdio_perf_stat_inc(&perf_stats.pci_int);
|
|
||||||
|
|
||||||
for_each_input_queue(irq_ptr, q, i)
|
for_each_input_queue(irq_ptr, q, i)
|
||||||
tasklet_schedule(&q->tasklet);
|
tasklet_schedule(&q->tasklet);
|
||||||
|
|
||||||
|
@ -923,8 +922,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||||
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
||||||
int cstat, dstat;
|
int cstat, dstat;
|
||||||
|
|
||||||
qdio_perf_stat_inc(&perf_stats.qdio_int);
|
|
||||||
|
|
||||||
if (!intparm || !irq_ptr) {
|
if (!intparm || !irq_ptr) {
|
||||||
DBF_ERROR("qint:%4x", cdev->private->schid.sch_no);
|
DBF_ERROR("qint:%4x", cdev->private->schid.sch_no);
|
||||||
return;
|
return;
|
||||||
|
@ -1383,6 +1380,8 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
|
||||||
{
|
{
|
||||||
int used, diff;
|
int used, diff;
|
||||||
|
|
||||||
|
qperf_inc(q, inbound_call);
|
||||||
|
|
||||||
if (!q->u.in.polling)
|
if (!q->u.in.polling)
|
||||||
goto set;
|
goto set;
|
||||||
|
|
||||||
|
@ -1438,14 +1437,16 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
|
||||||
unsigned char state;
|
unsigned char state;
|
||||||
int used, rc = 0;
|
int used, rc = 0;
|
||||||
|
|
||||||
qdio_perf_stat_inc(&perf_stats.outbound_handler);
|
qperf_inc(q, outbound_call);
|
||||||
|
|
||||||
count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count);
|
count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count);
|
||||||
used = atomic_add_return(count, &q->nr_buf_used);
|
used = atomic_add_return(count, &q->nr_buf_used);
|
||||||
BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
|
BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
|
||||||
|
|
||||||
if (callflags & QDIO_FLAG_PCI_OUT)
|
if (callflags & QDIO_FLAG_PCI_OUT) {
|
||||||
q->u.out.pci_out_enabled = 1;
|
q->u.out.pci_out_enabled = 1;
|
||||||
|
qperf_inc(q, pci_request_int);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
q->u.out.pci_out_enabled = 0;
|
q->u.out.pci_out_enabled = 0;
|
||||||
|
|
||||||
|
@ -1484,7 +1485,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
|
||||||
if (state != SLSB_CU_OUTPUT_PRIMED)
|
if (state != SLSB_CU_OUTPUT_PRIMED)
|
||||||
rc = qdio_kick_outbound_q(q);
|
rc = qdio_kick_outbound_q(q);
|
||||||
else
|
else
|
||||||
qdio_perf_stat_inc(&perf_stats.fast_requeue);
|
qperf_inc(q, fast_requeue);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
tasklet_schedule(&q->tasklet);
|
tasklet_schedule(&q->tasklet);
|
||||||
|
@ -1540,16 +1541,11 @@ static int __init init_QDIO(void)
|
||||||
rc = qdio_debug_init();
|
rc = qdio_debug_init();
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_ti;
|
goto out_ti;
|
||||||
rc = qdio_setup_perf_stats();
|
|
||||||
if (rc)
|
|
||||||
goto out_debug;
|
|
||||||
rc = tiqdio_register_thinints();
|
rc = tiqdio_register_thinints();
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_perf;
|
goto out_debug;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_perf:
|
|
||||||
qdio_remove_perf_stats();
|
|
||||||
out_debug:
|
out_debug:
|
||||||
qdio_debug_exit();
|
qdio_debug_exit();
|
||||||
out_ti:
|
out_ti:
|
||||||
|
@ -1563,7 +1559,6 @@ static void __exit exit_QDIO(void)
|
||||||
{
|
{
|
||||||
tiqdio_unregister_thinints();
|
tiqdio_unregister_thinints();
|
||||||
tiqdio_free_memory();
|
tiqdio_free_memory();
|
||||||
qdio_remove_perf_stats();
|
|
||||||
qdio_debug_exit();
|
qdio_debug_exit();
|
||||||
qdio_setup_exit();
|
qdio_setup_exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* drivers/s390/cio/qdio_perf.c
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2008
|
|
||||||
*
|
|
||||||
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
|
|
||||||
*/
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/proc_fs.h>
|
|
||||||
#include <linux/seq_file.h>
|
|
||||||
#include <asm/ccwdev.h>
|
|
||||||
|
|
||||||
#include "cio.h"
|
|
||||||
#include "css.h"
|
|
||||||
#include "device.h"
|
|
||||||
#include "ioasm.h"
|
|
||||||
#include "chsc.h"
|
|
||||||
#include "qdio_debug.h"
|
|
||||||
#include "qdio_perf.h"
|
|
||||||
|
|
||||||
int qdio_performance_stats;
|
|
||||||
struct qdio_perf_stats perf_stats;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
|
||||||
static struct proc_dir_entry *qdio_perf_pde;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* procfs functions
|
|
||||||
*/
|
|
||||||
static int qdio_perf_proc_show(struct seq_file *m, void *v)
|
|
||||||
{
|
|
||||||
seq_printf(m, "Number of qdio interrupts\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.qdio_int));
|
|
||||||
seq_printf(m, "Number of PCI interrupts\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.pci_int));
|
|
||||||
seq_printf(m, "Number of adapter interrupts\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.thin_int));
|
|
||||||
seq_printf(m, "\n");
|
|
||||||
seq_printf(m, "Inbound tasklet runs\t\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.tasklet_inbound));
|
|
||||||
seq_printf(m, "Outbound tasklet runs\t\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.tasklet_outbound));
|
|
||||||
seq_printf(m, "Adapter interrupt tasklet runs/loops\t\t: %li/%li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.tasklet_thinint),
|
|
||||||
(long)atomic_long_read(&perf_stats.tasklet_thinint_loop));
|
|
||||||
seq_printf(m, "Adapter interrupt inbound tasklet runs/loops\t: %li/%li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.thinint_inbound),
|
|
||||||
(long)atomic_long_read(&perf_stats.thinint_inbound_loop));
|
|
||||||
seq_printf(m, "\n");
|
|
||||||
seq_printf(m, "Number of SIGA In issued\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.siga_in));
|
|
||||||
seq_printf(m, "Number of SIGA Out issued\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.siga_out));
|
|
||||||
seq_printf(m, "Number of SIGA Sync issued\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.siga_sync));
|
|
||||||
seq_printf(m, "\n");
|
|
||||||
seq_printf(m, "Number of inbound transfers\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.inbound_handler));
|
|
||||||
seq_printf(m, "Number of outbound transfers\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.outbound_handler));
|
|
||||||
seq_printf(m, "\n");
|
|
||||||
seq_printf(m, "Number of fast requeues (outg. SBAL w/o SIGA)\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.fast_requeue));
|
|
||||||
seq_printf(m, "Number of outbound target full condition\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.outbound_target_full));
|
|
||||||
seq_printf(m, "Number of inbound queue full condition\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.inbound_queue_full));
|
|
||||||
seq_printf(m, "Number of outbound tasklet mod_timer calls\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.debug_tl_out_timer));
|
|
||||||
seq_printf(m, "Number of stop polling calls\t\t\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.debug_stop_polling));
|
|
||||||
seq_printf(m, "AI inbound tasklet loops after stop polling\t: %li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.thinint_inbound_loop2));
|
|
||||||
seq_printf(m, "QEBSM EQBS total/incomplete\t\t\t: %li/%li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.debug_eqbs_all),
|
|
||||||
(long)atomic_long_read(&perf_stats.debug_eqbs_incomplete));
|
|
||||||
seq_printf(m, "QEBSM SQBS total/incomplete\t\t\t: %li/%li\n",
|
|
||||||
(long)atomic_long_read(&perf_stats.debug_sqbs_all),
|
|
||||||
(long)atomic_long_read(&perf_stats.debug_sqbs_incomplete));
|
|
||||||
seq_printf(m, "\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int qdio_perf_seq_open(struct inode *inode, struct file *filp)
|
|
||||||
{
|
|
||||||
return single_open(filp, qdio_perf_proc_show, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations qdio_perf_proc_fops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.open = qdio_perf_seq_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sysfs functions
|
|
||||||
*/
|
|
||||||
static ssize_t qdio_perf_stats_show(struct bus_type *bus, char *buf)
|
|
||||||
{
|
|
||||||
return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t qdio_perf_stats_store(struct bus_type *bus,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
unsigned long i;
|
|
||||||
|
|
||||||
if (strict_strtoul(buf, 16, &i) != 0)
|
|
||||||
return -EINVAL;
|
|
||||||
if ((i != 0) && (i != 1))
|
|
||||||
return -EINVAL;
|
|
||||||
if (i == qdio_performance_stats)
|
|
||||||
return count;
|
|
||||||
|
|
||||||
qdio_performance_stats = i;
|
|
||||||
/* reset performance statistics */
|
|
||||||
if (i == 0)
|
|
||||||
memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BUS_ATTR(qdio_performance_stats, 0644, qdio_perf_stats_show,
|
|
||||||
qdio_perf_stats_store);
|
|
||||||
|
|
||||||
int __init qdio_setup_perf_stats(void)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
|
||||||
memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
|
|
||||||
qdio_perf_pde = proc_create("qdio_perf", S_IFREG | S_IRUGO,
|
|
||||||
NULL, &qdio_perf_proc_fops);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qdio_remove_perf_stats(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_PROC_FS
|
|
||||||
remove_proc_entry("qdio_perf", NULL);
|
|
||||||
#endif
|
|
||||||
bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* drivers/s390/cio/qdio_perf.h
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2008
|
|
||||||
*
|
|
||||||
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
|
|
||||||
*/
|
|
||||||
#ifndef QDIO_PERF_H
|
|
||||||
#define QDIO_PERF_H
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <asm/atomic.h>
|
|
||||||
|
|
||||||
struct qdio_perf_stats {
|
|
||||||
/* interrupt handler calls */
|
|
||||||
atomic_long_t qdio_int;
|
|
||||||
atomic_long_t pci_int;
|
|
||||||
atomic_long_t thin_int;
|
|
||||||
|
|
||||||
/* tasklet runs */
|
|
||||||
atomic_long_t tasklet_inbound;
|
|
||||||
atomic_long_t tasklet_outbound;
|
|
||||||
atomic_long_t tasklet_thinint;
|
|
||||||
atomic_long_t tasklet_thinint_loop;
|
|
||||||
atomic_long_t thinint_inbound;
|
|
||||||
atomic_long_t thinint_inbound_loop;
|
|
||||||
atomic_long_t thinint_inbound_loop2;
|
|
||||||
|
|
||||||
/* signal adapter calls */
|
|
||||||
atomic_long_t siga_out;
|
|
||||||
atomic_long_t siga_in;
|
|
||||||
atomic_long_t siga_sync;
|
|
||||||
|
|
||||||
/* misc */
|
|
||||||
atomic_long_t inbound_handler;
|
|
||||||
atomic_long_t outbound_handler;
|
|
||||||
atomic_long_t fast_requeue;
|
|
||||||
atomic_long_t outbound_target_full;
|
|
||||||
atomic_long_t inbound_queue_full;
|
|
||||||
|
|
||||||
/* for debugging */
|
|
||||||
atomic_long_t debug_tl_out_timer;
|
|
||||||
atomic_long_t debug_stop_polling;
|
|
||||||
atomic_long_t debug_eqbs_all;
|
|
||||||
atomic_long_t debug_eqbs_incomplete;
|
|
||||||
atomic_long_t debug_sqbs_all;
|
|
||||||
atomic_long_t debug_sqbs_incomplete;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct qdio_perf_stats perf_stats;
|
|
||||||
extern int qdio_performance_stats;
|
|
||||||
|
|
||||||
static inline void qdio_perf_stat_inc(atomic_long_t *count)
|
|
||||||
{
|
|
||||||
if (qdio_performance_stats)
|
|
||||||
atomic_long_inc(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
int qdio_setup_perf_stats(void);
|
|
||||||
void qdio_remove_perf_stats(void);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,9 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* linux/drivers/s390/cio/thinint_qdio.c
|
* linux/drivers/s390/cio/thinint_qdio.c
|
||||||
*
|
*
|
||||||
* thin interrupt support for qdio
|
* Copyright 2000,2009 IBM Corp.
|
||||||
*
|
|
||||||
* Copyright 2000-2008 IBM Corp.
|
|
||||||
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>
|
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>
|
||||||
* Cornelia Huck <cornelia.huck@de.ibm.com>
|
* Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
* Jan Glauber <jang@linux.vnet.ibm.com>
|
* Jan Glauber <jang@linux.vnet.ibm.com>
|
||||||
|
@ -19,7 +17,6 @@
|
||||||
#include "ioasm.h"
|
#include "ioasm.h"
|
||||||
#include "qdio.h"
|
#include "qdio.h"
|
||||||
#include "qdio_debug.h"
|
#include "qdio_debug.h"
|
||||||
#include "qdio_perf.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restriction: only 63 iqdio subchannels would have its own indicator,
|
* Restriction: only 63 iqdio subchannels would have its own indicator,
|
||||||
|
@ -132,8 +129,6 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)
|
||||||
{
|
{
|
||||||
struct qdio_q *q;
|
struct qdio_q *q;
|
||||||
|
|
||||||
qdio_perf_stat_inc(&perf_stats.thin_int);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SVS only when needed: issue SVS to benefit from iqdio interrupt
|
* SVS only when needed: issue SVS to benefit from iqdio interrupt
|
||||||
* avoidance (SVS clears adapter interrupt suppression overwrite)
|
* avoidance (SVS clears adapter interrupt suppression overwrite)
|
||||||
|
@ -154,6 +149,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)
|
||||||
list_for_each_entry_rcu(q, &tiq_list, entry)
|
list_for_each_entry_rcu(q, &tiq_list, entry)
|
||||||
/* only process queues from changed sets */
|
/* only process queues from changed sets */
|
||||||
if (*q->irq_ptr->dsci) {
|
if (*q->irq_ptr->dsci) {
|
||||||
|
qperf_inc(q, adapter_int);
|
||||||
|
|
||||||
/* only clear it if the indicator is non-shared */
|
/* only clear it if the indicator is non-shared */
|
||||||
if (!shared_ind(q->irq_ptr))
|
if (!shared_ind(q->irq_ptr))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче