From: Jan Glauber <jglauber@redhat.com> Subject: Re: [RHEL5.1 PATCH] s390: runtime switch for qdio performance statistics Date: Tue, 15 May 2007 09:34:48 +0000 Bugzilla: 228048 Message-Id: <1179221688.7368.11.camel@localhost.localdomain> Changelog: [s390] runtime switch for qdio performance statistics BZ 228048 Add a runtime switch for the qdio performance statistics. The patch removes CONFIG_QDIO_PERF_STATS and adds a sysfs attribute instead. We want to have the ability to turn the statistics on/off at runtime. Patch is upstream with 2.6.20, tested by IBM. There should be no need to change the config files since the option is turned off. Note: although the config option is CONFIG_QDIO_PERF_STATS the code removes QDIO_PERFORMANCE_STATS which looks esoteric but is caused by this define in qdio.h: #ifdef CONFIG_QDIO_PERF_STATS #define QDIO_PERFORMANCE_STATS #endif /* CONFIG_QDIO_PERF_STATS */ Jan --- arch/s390/Kconfig | 8 - arch/s390/defconfig | 1 drivers/s390/cio/qdio.c | 303 ++++++++++++++++++++++++++++-------------------- drivers/s390/cio/qdio.h | 56 +++++--- 4 files changed, 216 insertions(+), 152 deletions(-) Index: linux-rhel5/arch/s390/Kconfig =================================================================== --- linux-rhel5.orig/arch/s390/Kconfig 2007-03-15 17:11:51.000000000 +0100 +++ linux-rhel5/arch/s390/Kconfig 2007-05-08 15:54:33.000000000 +0200 @@ -250,14 +250,6 @@ config QDIO If unsure, say Y. -config QDIO_PERF_STATS - bool "Performance statistics in /proc" - depends on QDIO - help - Say Y here to get performance statistics in /proc/qdio_perf - - If unsure, say N. - config QDIO_DEBUG bool "Extended debugging information" depends on QDIO Index: linux-rhel5/arch/s390/defconfig =================================================================== --- linux-rhel5.orig/arch/s390/defconfig 2007-03-15 17:11:51.000000000 +0100 +++ linux-rhel5/arch/s390/defconfig 2007-05-08 15:54:20.000000000 +0200 @@ -127,7 +127,6 @@ CONFIG_RESOURCES_64BIT=y # CONFIG_MACHCHK_WARNING=y CONFIG_QDIO=y -# CONFIG_QDIO_PERF_STATS is not set # CONFIG_QDIO_DEBUG is not set # Index: linux-rhel5/drivers/s390/cio/qdio.c =================================================================== --- linux-rhel5.orig/drivers/s390/cio/qdio.c 2007-03-15 17:11:55.000000000 +0100 +++ linux-rhel5/drivers/s390/cio/qdio.c 2007-05-08 16:29:47.000000000 +0200 @@ -65,12 +65,11 @@ MODULE_LICENSE("GPL"); /******************** HERE WE GO ***********************************/ static const char version[] = "QDIO base support version 2"; +extern struct bus_type ccw_bus_type; -#ifdef QDIO_PERFORMANCE_STATS +static int qdio_performance_stats = 0; static int proc_perf_file_registration; -static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc; static struct qdio_perf_stats perf_stats; -#endif /* QDIO_PERFORMANCE_STATS */ static int hydra_thinints; static int is_passthrough = 0; @@ -111,6 +110,31 @@ qdio_min(int a,int b) } /***************** SCRUBBER HELPER ROUTINES **********************/ +#ifdef CONFIG_64BIT +static inline void qdio_perf_stat_inc(atomic64_t *count) +{ + if (qdio_performance_stats) + atomic64_inc(count); +} + +static inline void qdio_perf_stat_dec(atomic64_t *count) +{ + if (qdio_performance_stats) + atomic64_dec(count); +} +#else /* CONFIG_64BIT */ +static inline void qdio_perf_stat_inc(atomic_t *count) +{ + if (qdio_performance_stats) + atomic_inc(count); +} + +static inline void qdio_perf_stat_dec(atomic_t *count) +{ + if (qdio_performance_stats) + atomic_dec(count); +} +#endif /* CONFIG_64BIT */ static inline __u64 qdio_get_micros(void) @@ -275,9 +299,7 @@ qdio_siga_sync(struct qdio_q *q, unsigne QDIO_DBF_TEXT4(0,trace,"sigasync"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.siga_syncs++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.siga_syncs); cc = do_siga_sync(q->schid, gpr2, gpr3); if (cc) @@ -322,9 +344,7 @@ qdio_siga_output(struct qdio_q *q) __u32 busy_bit; __u64 start_time=0; -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.siga_outs++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.siga_outs); QDIO_DBF_TEXT4(0,trace,"sigaout"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -358,9 +378,7 @@ qdio_siga_input(struct qdio_q *q) QDIO_DBF_TEXT4(0,trace,"sigain"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.siga_ins++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.siga_ins); cc = do_siga_input(q->schid, q->mask); @@ -954,9 +972,7 @@ __qdio_outbound_processing(struct qdio_q if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - o_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.outbound_tl_runs_resched); /* as we're sissies, we'll check next time */ if (likely(!atomic_read(&q->is_in_shutdown))) { qdio_mark_q(q); @@ -964,10 +980,8 @@ __qdio_outbound_processing(struct qdio_q } return; } -#ifdef QDIO_PERFORMANCE_STATS - o_p_nc++; - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.outbound_tl_runs); + qdio_perf_stat_inc(&perf_stats.tl_runs); /* see comment in qdio_kick_outbound_q */ siga_attempts=atomic_read(&q->busy_siga_counter); @@ -1142,16 +1156,6 @@ qdio_has_inbound_q_moved(struct qdio_q * { int i; -#ifdef QDIO_PERFORMANCE_STATS - static int old_pcis=0; - static int old_thinints=0; - - if ((old_pcis==perf_stats.pcis)&&(old_thinints==perf_stats.thinints)) - perf_stats.start_time_inbound=NOW; - else - old_pcis=perf_stats.pcis; -#endif /* QDIO_PERFORMANCE_STATS */ - i=qdio_get_inbound_buffer_frontier(q); if ( (i!=GET_SAVED_FRONTIER(q)) || (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { @@ -1340,10 +1344,7 @@ qdio_kick_inbound_handler(struct qdio_q q->siga_error=0; q->error_status_flags=0; -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound; - perf_stats.inbound_cnt++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.inbound_cnt); } static inline void @@ -1363,9 +1364,7 @@ __tiqdio_inbound_processing(struct qdio_ */ if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - ii_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched); /* * as we might just be about to stop polling, we make * sure that we check again at least once more @@ -1373,9 +1372,7 @@ __tiqdio_inbound_processing(struct qdio_ tiqdio_sched_tl(); return; } -#ifdef QDIO_PERFORMANCE_STATS - ii_p_nc++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs); if (unlikely(atomic_read(&q->is_in_shutdown))) { qdio_unmark_q(q); goto out; @@ -1416,11 +1413,10 @@ __tiqdio_inbound_processing(struct qdio_ irq_ptr = (struct qdio_irq*)q->irq_ptr; for (i=0;i<irq_ptr->no_output_qs;i++) { oq = irq_ptr->output_qs[i]; -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.tl_runs--; -#endif /* QDIO_PERFORMANCE_STATS */ - if (!qdio_is_outbound_q_done(oq)) + if (!qdio_is_outbound_q_done(oq)) { + qdio_perf_stat_dec(&perf_stats.tl_runs); __qdio_outbound_processing(oq); + } } } @@ -1457,9 +1453,7 @@ __qdio_inbound_processing(struct qdio_q if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - i_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.inbound_tl_runs_resched); /* as we're sissies, we'll check next time */ if (likely(!atomic_read(&q->is_in_shutdown))) { qdio_mark_q(q); @@ -1467,10 +1461,8 @@ __qdio_inbound_processing(struct qdio_q } return; } -#ifdef QDIO_PERFORMANCE_STATS - i_p_nc++; - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.inbound_tl_runs); + qdio_perf_stat_inc(&perf_stats.tl_runs); again: if (qdio_has_inbound_q_moved(q)) { @@ -1516,9 +1508,7 @@ tiqdio_reset_processing_state(struct qdi if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - ii_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched); /* * as we might just be about to stop polling, we make * sure that we check again at least once more @@ -1609,9 +1599,7 @@ tiqdio_tl(unsigned long data) { QDIO_DBF_TEXT4(0,trace,"iqdio_tl"); -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.tl_runs); tiqdio_inbound_checks(); } @@ -1918,10 +1906,7 @@ tiqdio_thinint_handler(void) { QDIO_DBF_TEXT4(0,trace,"thin_int"); -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.thinints++; - perf_stats.start_time_inbound=NOW; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.thinints); /* SVS only when needed: * issue SVS to benefit from iqdio interrupt avoidance @@ -1976,18 +1961,13 @@ qdio_handle_pci(struct qdio_irq *irq_ptr int i; struct qdio_q *q; -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.pcis++; - perf_stats.start_time_inbound=NOW; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.pcis); for (i=0;i<irq_ptr->no_input_qs;i++) { q=irq_ptr->input_qs[i]; if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT) qdio_mark_q(q); else { -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.tl_runs--; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_dec(&perf_stats.tl_runs); __qdio_inbound_processing(q); } } @@ -1995,11 +1975,9 @@ qdio_handle_pci(struct qdio_irq *irq_ptr return; for (i=0;i<irq_ptr->no_output_qs;i++) { q=irq_ptr->output_qs[i]; -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.tl_runs--; -#endif /* QDIO_PERFORMANCE_STATS */ if (qdio_is_outbound_q_done(q)) continue; + qdio_perf_stat_dec(&perf_stats.tl_runs); if (!irq_ptr->sync_done_on_outb_pcis) SYNC_MEMORY; __qdio_outbound_processing(q); @@ -3458,19 +3436,13 @@ do_qdio_handle_outbound(struct qdio_q *q struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; /* This is the outbound handling of queues */ -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.start_time_outbound=NOW; -#endif /* QDIO_PERFORMANCE_STATS */ qdio_do_qdio_fill_output(q,qidx,count,buffers); used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count; if (callflags&QDIO_FLAG_DONT_SIGA) { -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound; - perf_stats.outbound_cnt++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.outbound_cnt); return; } if (q->is_iqdio_q) { @@ -3500,9 +3472,7 @@ do_qdio_handle_outbound(struct qdio_q *q qdio_kick_outbound_q(q); } else { QDIO_DBF_TEXT3(0,trace, "fast-req"); -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.fast_reqs++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.fast_reqs); } } /* @@ -3513,10 +3483,7 @@ do_qdio_handle_outbound(struct qdio_q *q __qdio_outbound_processing(q); } -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound; - perf_stats.outbound_cnt++; -#endif /* QDIO_PERFORMANCE_STATS */ + qdio_perf_stat_inc(&perf_stats.outbound_cnt); } /* count must be 1 in iqdio */ @@ -3574,7 +3541,6 @@ do_QDIO(struct ccw_device *cdev,unsigned return 0; } -#ifdef QDIO_PERFORMANCE_STATS static int qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data) @@ -3587,45 +3553,77 @@ qdio_perf_procfile_read(char *buffer, ch return 0; #define _OUTP_IT(x...) c+=sprintf(buffer+c,x) - _OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c); - _OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c); - _OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c); - _OUTP_IT("Number of tasklet runs (total) : %u\n", - perf_stats.tl_runs); +#ifdef CONFIG_64BIT + _OUTP_IT("Number of tasklet runs (total) : %li\n", + (long)atomic64_read(&perf_stats.tl_runs)); + _OUTP_IT("Inbound tasklet runs tried/retried : %li/%li\n", + (long)atomic64_read(&perf_stats.inbound_tl_runs), + (long)atomic64_read(&perf_stats.inbound_tl_runs_resched)); + _OUTP_IT("Inbound-thin tasklet runs tried/retried : %li/%li\n", + (long)atomic64_read(&perf_stats.inbound_thin_tl_runs), + (long)atomic64_read(&perf_stats.inbound_thin_tl_runs_resched)); + _OUTP_IT("Outbound tasklet runs tried/retried : %li/%li\n", + (long)atomic64_read(&perf_stats.outbound_tl_runs), + (long)atomic64_read(&perf_stats.outbound_tl_runs_resched)); + _OUTP_IT("\n"); + _OUTP_IT("Number of SIGA sync's issued : %li\n", + (long)atomic64_read(&perf_stats.siga_syncs)); + _OUTP_IT("Number of SIGA in's issued : %li\n", + (long)atomic64_read(&perf_stats.siga_ins)); + _OUTP_IT("Number of SIGA out's issued : %li\n", + (long)atomic64_read(&perf_stats.siga_outs)); + _OUTP_IT("Number of PCIs caught : %li\n", + (long)atomic64_read(&perf_stats.pcis)); + _OUTP_IT("Number of adapter interrupts caught : %li\n", + (long)atomic64_read(&perf_stats.thinints)); + _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %li\n", + (long)atomic64_read(&perf_stats.fast_reqs)); _OUTP_IT("\n"); - _OUTP_IT("Number of SIGA sync's issued : %u\n", - perf_stats.siga_syncs); - _OUTP_IT("Number of SIGA in's issued : %u\n", - perf_stats.siga_ins); - _OUTP_IT("Number of SIGA out's issued : %u\n", - perf_stats.siga_outs); - _OUTP_IT("Number of PCIs caught : %u\n", - perf_stats.pcis); - _OUTP_IT("Number of adapter interrupts caught : %u\n", - perf_stats.thinints); - _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %u\n", - perf_stats.fast_reqs); + _OUTP_IT("Number of inbound transfers : %li\n", + (long)atomic64_read(&perf_stats.inbound_cnt)); + _OUTP_IT("Number of do_QDIOs outbound : %li\n", + (long)atomic64_read(&perf_stats.outbound_cnt)); +#else /* CONFIG_64BIT */ + _OUTP_IT("Number of tasklet runs (total) : %i\n", + atomic_read(&perf_stats.tl_runs)); + _OUTP_IT("Inbound tasklet runs tried/retried : %i/%i\n", + atomic_read(&perf_stats.inbound_tl_runs), + atomic_read(&perf_stats.inbound_tl_runs_resched)); + _OUTP_IT("Inbound-thin tasklet runs tried/retried : %i/%i\n", + atomic_read(&perf_stats.inbound_thin_tl_runs), + atomic_read(&perf_stats.inbound_thin_tl_runs_resched)); + _OUTP_IT("Outbound tasklet runs tried/retried : %i/%i\n", + atomic_read(&perf_stats.outbound_tl_runs), + atomic_read(&perf_stats.outbound_tl_runs_resched)); _OUTP_IT("\n"); - _OUTP_IT("Total time of all inbound actions (us) incl. UL : %u\n", - perf_stats.inbound_time); - _OUTP_IT("Number of inbound transfers : %u\n", - perf_stats.inbound_cnt); - _OUTP_IT("Total time of all outbound do_QDIOs (us) : %u\n", - perf_stats.outbound_time); - _OUTP_IT("Number of do_QDIOs outbound : %u\n", - perf_stats.outbound_cnt); + _OUTP_IT("Number of SIGA sync's issued : %i\n", + atomic_read(&perf_stats.siga_syncs)); + _OUTP_IT("Number of SIGA in's issued : %i\n", + atomic_read(&perf_stats.siga_ins)); + _OUTP_IT("Number of SIGA out's issued : %i\n", + atomic_read(&perf_stats.siga_outs)); + _OUTP_IT("Number of PCIs caught : %i\n", + atomic_read(&perf_stats.pcis)); + _OUTP_IT("Number of adapter interrupts caught : %i\n", + atomic_read(&perf_stats.thinints)); + _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %i\n", + atomic_read(&perf_stats.fast_reqs)); + _OUTP_IT("\n"); + _OUTP_IT("Number of inbound transfers : %i\n", + atomic_read(&perf_stats.inbound_cnt)); + _OUTP_IT("Number of do_QDIOs outbound : %i\n", + atomic_read(&perf_stats.outbound_cnt)); +#endif /* CONFIG_64BIT */ _OUTP_IT("\n"); return c; } static struct proc_dir_entry *qdio_perf_proc_file; -#endif /* QDIO_PERFORMANCE_STATS */ static void qdio_add_procfs_entry(void) { -#ifdef QDIO_PERFORMANCE_STATS proc_perf_file_registration=0; qdio_perf_proc_file=create_proc_entry(QDIO_PERF, S_IFREG|0444,&proc_root); @@ -3637,20 +3635,81 @@ qdio_add_procfs_entry(void) QDIO_PRINT_WARN("was not able to register perf. " \ "proc-file (%i).\n", proc_perf_file_registration); -#endif /* QDIO_PERFORMANCE_STATS */ } static void qdio_remove_procfs_entry(void) { -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.tl_runs=0; - if (!proc_perf_file_registration) /* means if it went ok earlier */ remove_proc_entry(QDIO_PERF,&proc_root); -#endif /* QDIO_PERFORMANCE_STATS */ } +/** + * attributes in sysfs + *****************************************************************************/ + +static ssize_t +qdio_performance_stats_show(struct bus_type *bus, char *buf) +{ + return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0); +} + +static ssize_t +qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count) +{ + char *tmp; + int i; + + i = simple_strtoul(buf, &tmp, 16); + if ((i == 0) || (i == 1)) { + if (i == qdio_performance_stats) + return count; + qdio_performance_stats = i; + if (i==0) { + /* reset perf. stat. info */ +#ifdef CONFIG_64BIT + atomic64_set(&perf_stats.tl_runs, 0); + atomic64_set(&perf_stats.outbound_tl_runs, 0); + atomic64_set(&perf_stats.inbound_tl_runs, 0); + atomic64_set(&perf_stats.inbound_tl_runs_resched, 0); + atomic64_set(&perf_stats.inbound_thin_tl_runs, 0); + atomic64_set(&perf_stats.inbound_thin_tl_runs_resched, + 0); + atomic64_set(&perf_stats.siga_outs, 0); + atomic64_set(&perf_stats.siga_ins, 0); + atomic64_set(&perf_stats.siga_syncs, 0); + atomic64_set(&perf_stats.pcis, 0); + atomic64_set(&perf_stats.thinints, 0); + atomic64_set(&perf_stats.fast_reqs, 0); + atomic64_set(&perf_stats.outbound_cnt, 0); + atomic64_set(&perf_stats.inbound_cnt, 0); +#else /* CONFIG_64BIT */ + atomic_set(&perf_stats.tl_runs, 0); + atomic_set(&perf_stats.outbound_tl_runs, 0); + atomic_set(&perf_stats.inbound_tl_runs, 0); + atomic_set(&perf_stats.inbound_tl_runs_resched, 0); + atomic_set(&perf_stats.inbound_thin_tl_runs, 0); + atomic_set(&perf_stats.inbound_thin_tl_runs_resched, 0); + atomic_set(&perf_stats.siga_outs, 0); + atomic_set(&perf_stats.siga_ins, 0); + atomic_set(&perf_stats.siga_syncs, 0); + atomic_set(&perf_stats.pcis, 0); + atomic_set(&perf_stats.thinints, 0); + atomic_set(&perf_stats.fast_reqs, 0); + atomic_set(&perf_stats.outbound_cnt, 0); + atomic_set(&perf_stats.inbound_cnt, 0); +#endif /* CONFIG_64BIT */ + } + } else { + QDIO_PRINT_ERR("QDIO performance_stats: write 0 or 1 to this file!\n"); + return -EINVAL; + } + return count; +} + +static BUS_ATTR(qdio_performance_stats, 0644, qdio_performance_stats_show, + qdio_performance_stats_store); + static void tiqdio_register_thinints(void) { @@ -3796,9 +3855,7 @@ static int __init init_QDIO(void) { int res; -#ifdef QDIO_PERFORMANCE_STATS void *ptr; -#endif /* QDIO_PERFORMANCE_STATS */ printk("qdio: loading %s\n",version); @@ -3811,13 +3868,12 @@ init_QDIO(void) return res; QDIO_DBF_TEXT0(0,setup,"initQDIO"); + res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); -#ifdef QDIO_PERFORMANCE_STATS - memset((void*)&perf_stats,0,sizeof(perf_stats)); + memset((void*)&perf_stats,0,sizeof(perf_stats)); QDIO_DBF_TEXT0(0,setup,"perfstat"); ptr=&perf_stats; QDIO_DBF_HEX0(0,setup,&ptr,sizeof(void*)); -#endif /* QDIO_PERFORMANCE_STATS */ qdio_add_procfs_entry(); @@ -3841,8 +3897,9 @@ cleanup_QDIO(void) qdio_release_qdio_memory(); qdio_unregister_dbf_views(); mempool_destroy(qdio_mempool_scssc); + bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); - printk("qdio: %s: module removed\n",version); + printk("qdio: %s: module removed\n",version); } module_init(init_QDIO); Index: linux-rhel5/drivers/s390/cio/qdio.h =================================================================== --- linux-rhel5.orig/drivers/s390/cio/qdio.h 2007-03-15 17:11:55.000000000 +0100 +++ linux-rhel5/drivers/s390/cio/qdio.h 2007-05-08 15:55:00.000000000 +0200 @@ -12,10 +12,6 @@ #endif /* CONFIG_QDIO_DEBUG */ #define QDIO_USE_PROCESSING_STATE -#ifdef CONFIG_QDIO_PERF_STATS -#define QDIO_PERFORMANCE_STATS -#endif /* CONFIG_QDIO_PERF_STATS */ - #define QDIO_MINIMAL_BH_RELIEF_TIME 16 #define QDIO_TIMER_POLL_VALUE 1 #define IQDIO_TIMER_POLL_VALUE 1 @@ -503,25 +499,45 @@ do_clear_global_summary(void) #define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08 #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04 -#ifdef QDIO_PERFORMANCE_STATS struct qdio_perf_stats { - unsigned int tl_runs; +#ifdef CONFIG_64BIT + atomic64_t tl_runs; + atomic64_t outbound_tl_runs; + atomic64_t outbound_tl_runs_resched; + atomic64_t inbound_tl_runs; + atomic64_t inbound_tl_runs_resched; + atomic64_t inbound_thin_tl_runs; + atomic64_t inbound_thin_tl_runs_resched; + + atomic64_t siga_outs; + atomic64_t siga_ins; + atomic64_t siga_syncs; + atomic64_t pcis; + atomic64_t thinints; + atomic64_t fast_reqs; - unsigned int siga_outs; - unsigned int siga_ins; - unsigned int siga_syncs; - unsigned int pcis; - unsigned int thinints; - unsigned int fast_reqs; - - __u64 start_time_outbound; - unsigned int outbound_cnt; - unsigned int outbound_time; - __u64 start_time_inbound; - unsigned int inbound_cnt; - unsigned int inbound_time; + atomic64_t outbound_cnt; + atomic64_t inbound_cnt; +#else /* CONFIG_64BIT */ + atomic_t tl_runs; + atomic_t outbound_tl_runs; + atomic_t outbound_tl_runs_resched; + atomic_t inbound_tl_runs; + atomic_t inbound_tl_runs_resched; + atomic_t inbound_thin_tl_runs; + atomic_t inbound_thin_tl_runs_resched; + + atomic_t siga_outs; + atomic_t siga_ins; + atomic_t siga_syncs; + atomic_t pcis; + atomic_t thinints; + atomic_t fast_reqs; + + atomic_t outbound_cnt; + atomic_t inbound_cnt; +#endif /* CONFIG_64BIT */ }; -#endif /* QDIO_PERFORMANCE_STATS */ #define atomic_swap(a,b) xchg((int*)a.counter,b)