X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fcio%2Fqdio.c;h=6fd1940842ebd05d9185b6959fae90e37653546b;hb=refs%2Fheads%2Fvserver;hp=9ed37dc9a1b048304f8ce2ddf9aa60f17677a808;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 9ed37dc9a..6fd194084 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -30,7 +30,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include @@ -38,6 +37,7 @@ #include #include #include +#include #include #include @@ -46,6 +46,7 @@ #include #include +#include #include #include "cio.h" @@ -65,12 +66,12 @@ 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; @@ -80,6 +81,8 @@ static int indicator_used[INDICATORS_PER_CACHELINE]; static __u32 * volatile indicators; static __u32 volatile spare_indicator; static atomic_t spare_indicator_usecount; +#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2 +static mempool_t *qdio_mempool_scssc; static debug_info_t *qdio_dbf_setup; static debug_info_t *qdio_dbf_sbal; @@ -113,7 +116,7 @@ qdio_min(int a,int b) static inline __u64 qdio_get_micros(void) { - return (get_clock() >> 10); /* time>>12 is microseconds */ + return (get_clock() >> 12); /* time>>12 is microseconds */ } /* @@ -273,9 +276,8 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, 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 */ + if (qdio_performance_stats) + perf_stats.siga_syncs++; cc = do_siga_sync(q->schid, gpr2, gpr3); if (cc) @@ -320,9 +322,8 @@ 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 */ + if (qdio_performance_stats) + perf_stats.siga_outs++; QDIO_DBF_TEXT4(0,trace,"sigaout"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -356,9 +357,8 @@ 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 */ + if (qdio_performance_stats) + perf_stats.siga_ins++; cc = do_siga_input(q->schid, q->mask); @@ -479,7 +479,7 @@ qdio_stop_polling(struct qdio_q *q) unsigned char state = 0; struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; - if (!atomic_swap(&q->polling,0)) + if (!atomic_xchg(&q->polling,0)) return 1; QDIO_DBF_TEXT4(0,trace,"stoppoll"); @@ -952,9 +952,8 @@ __qdio_outbound_processing(struct qdio_q *q) if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - o_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) + o_p_c++; /* as we're sissies, we'll check next time */ if (likely(!atomic_read(&q->is_in_shutdown))) { qdio_mark_q(q); @@ -962,10 +961,10 @@ __qdio_outbound_processing(struct qdio_q *q) } return; } -#ifdef QDIO_PERFORMANCE_STATS - o_p_nc++; - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) { + o_p_nc++; + perf_stats.tl_runs++; + } /* see comment in qdio_kick_outbound_q */ siga_attempts=atomic_read(&q->busy_siga_counter); @@ -980,12 +979,11 @@ __qdio_outbound_processing(struct qdio_q *q) if (q->is_iqdio_q) { /* - * for asynchronous queues, we better check, if the fill - * level is too high. for synchronous queues, the fill - * level will never be that high. + * for asynchronous queues, we better check, if the sent + * buffer is already switched from PRIMED to EMPTY. */ - if (atomic_read(&q->number_of_buffers_used)> - IQDIO_FILL_LEVEL_TO_POLL) + if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) && + !qdio_is_outbound_q_done(q)) qdio_mark_q(q); } else if (!q->hydra_gives_outbound_pcis) @@ -1127,7 +1125,7 @@ out: #ifdef QDIO_USE_PROCESSING_STATE if (last_position>=0) - set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count); + set_slsb(q, &last_position, SLSB_P_INPUT_PROCESSING, &count); #endif /* QDIO_USE_PROCESSING_STATE */ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); @@ -1140,15 +1138,16 @@ qdio_has_inbound_q_moved(struct qdio_q *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 */ + if (qdio_performance_stats) { + if ((old_pcis==perf_stats.pcis)&& + (old_thinints==perf_stats.thinints)) + perf_stats.start_time_inbound=NOW; + else + old_pcis=perf_stats.pcis; + } i=qdio_get_inbound_buffer_frontier(q); if ( (i!=GET_SAVED_FRONTIER(q)) || @@ -1338,10 +1337,10 @@ qdio_kick_inbound_handler(struct qdio_q *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 */ + if (qdio_performance_stats) { + perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound; + perf_stats.inbound_cnt++; + } } static inline void @@ -1361,9 +1360,8 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) */ if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - ii_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) + ii_p_c++; /* * as we might just be about to stop polling, we make * sure that we check again at least once more @@ -1371,9 +1369,8 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) tiqdio_sched_tl(); return; } -#ifdef QDIO_PERFORMANCE_STATS - ii_p_nc++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) + ii_p_nc++; if (unlikely(atomic_read(&q->is_in_shutdown))) { qdio_unmark_q(q); goto out; @@ -1414,11 +1411,11 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) irq_ptr = (struct qdio_irq*)q->irq_ptr; for (i=0;ino_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)) { + if (qdio_performance_stats) + perf_stats.tl_runs--; __qdio_outbound_processing(oq); + } } } @@ -1455,9 +1452,8 @@ __qdio_inbound_processing(struct qdio_q *q) if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - i_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) + i_p_c++; /* as we're sissies, we'll check next time */ if (likely(!atomic_read(&q->is_in_shutdown))) { qdio_mark_q(q); @@ -1465,10 +1461,10 @@ __qdio_inbound_processing(struct qdio_q *q) } return; } -#ifdef QDIO_PERFORMANCE_STATS - i_p_nc++; - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) { + i_p_nc++; + perf_stats.tl_runs++; + } again: if (qdio_has_inbound_q_moved(q)) { @@ -1514,9 +1510,8 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - ii_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) + ii_p_c++; /* * as we might just be about to stop polling, we make * sure that we check again at least once more @@ -1607,9 +1602,8 @@ tiqdio_tl(unsigned long data) { QDIO_DBF_TEXT4(0,trace,"iqdio_tl"); -#ifdef QDIO_PERFORMANCE_STATS - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ + if (qdio_performance_stats) + perf_stats.tl_runs++; tiqdio_inbound_checks(); } @@ -1637,7 +1631,7 @@ next: } kfree(irq_ptr->qdr); - kfree(irq_ptr); + free_page((unsigned long) irq_ptr); } static void @@ -1686,16 +1680,14 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr, int result=-ENOMEM; for (i=0;islib=kmalloc(PAGE_SIZE,GFP_KERNEL); + q->slib = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!q->slib) { QDIO_PRINT_ERR("kmalloc of slib failed!\n"); goto out; @@ -1705,14 +1697,12 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr, } for (i=0;islib=kmalloc(PAGE_SIZE,GFP_KERNEL); if (!q->slib) { QDIO_PRINT_ERR("kmalloc of slib failed!\n"); @@ -1743,7 +1733,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, void *ptr; int available; - sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no); + sprintf(dbf_text,"qfqs%4x",cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0,setup,dbf_text); for (i=0;iinput_qs[i]; @@ -1834,6 +1824,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, q->sbal[j]=*(outbound_sbals_array++); q->queue_type=q_format; + if ((q->queue_type == QDIO_IQDIO_QFMT) && + (no_output_qs > 1) && + (i == no_output_qs-1)) + q->queue_type = QDIO_IQDIO_QFMT_ASYNCH; q->int_parm=int_parm; q->is_input_q=0; q->schid = irq_ptr->schid; @@ -1920,10 +1914,10 @@ 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 */ + if (qdio_performance_stats) { + perf_stats.thinints++; + perf_stats.start_time_inbound=NOW; + } /* SVS only when needed: * issue SVS to benefit from iqdio interrupt avoidance @@ -1966,8 +1960,8 @@ qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN); QDIO_PRINT_WARN("sense data available on qdio channel.\n"); - HEXDUMP16(WARN,"irb: ",irb); - HEXDUMP16(WARN,"sense data: ",irb->ecw); + QDIO_HEXDUMP16(WARN,"irb: ",irb); + QDIO_HEXDUMP16(WARN,"sense data: ",irb->ecw); } } @@ -1978,18 +1972,17 @@ 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 */ + if (qdio_performance_stats) { + perf_stats.pcis++; + perf_stats.start_time_inbound=NOW; + } for (i=0;ino_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 */ + if (qdio_performance_stats) + perf_stats.tl_runs--; __qdio_inbound_processing(q); } } @@ -1997,11 +1990,10 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) return; for (i=0;ino_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; + if (qdio_performance_stats) + perf_stats.tl_runs--; if (!irq_ptr->sync_done_on_outb_pcis) SYNC_MEMORY; __qdio_outbound_processing(q); @@ -2047,11 +2039,13 @@ omit_handler_call: } static void -qdio_call_shutdown(void *data) +qdio_call_shutdown(struct work_struct *work) { + struct ccw_device_private *priv; struct ccw_device *cdev; - cdev = (struct ccw_device *)data; + priv = container_of(work, struct ccw_device_private, kick_work); + cdev = priv->cdev; qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); put_device(&cdev->dev); } @@ -2093,7 +2087,7 @@ qdio_timeout_handler(struct ccw_device *cdev) if (get_device(&cdev->dev)) { /* Can't call shutdown from interrupt context. */ PREPARE_WORK(&cdev->private->kick_work, - qdio_call_shutdown, (void *)cdev); + qdio_call_shutdown); queue_work(ccw_device_work, &cdev->private->kick_work); } break; @@ -2308,7 +2302,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) QDIO_DBF_TEXT0(0,setup,"getssqd"); qdioac = 0; - ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC); if (!ssqd_area) { QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no); @@ -2368,7 +2362,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) out: qdio_check_subchannel_qebsm(irq_ptr, qdioac, ssqd_area->sch_token); - free_page ((unsigned long) ssqd_area); + mempool_free(ssqd_area, qdio_mempool_scssc); irq_ptr->qdioac = qdioac; } @@ -2462,7 +2456,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind); } - scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + scssc_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC); if (!scssc_area) { QDIO_PRINT_WARN("No memory for setting indicators on " \ "subchannel 0.%x.%x.\n", @@ -2518,7 +2512,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long)); result = 0; out: - free_page ((unsigned long) scssc_area); + mempool_free(scssc_area, qdio_mempool_scssc); return result; } @@ -2547,7 +2541,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) if (!irq_ptr->is_thinint_irq) return -ENODEV; - scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + scsscf_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC); if (!scsscf_area) { QDIO_PRINT_WARN("No memory for setting delay target on " \ "subchannel 0.%x.%x.\n", @@ -2585,7 +2579,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long)); result = 0; /* not critical */ out: - free_page ((unsigned long) scsscf_area); + mempool_free(scsscf_area, qdio_mempool_scssc); return result; } @@ -2737,7 +2731,7 @@ qdio_free(struct ccw_device *cdev) QDIO_DBF_TEXT1(0,trace,dbf_text); QDIO_DBF_TEXT0(0,setup,dbf_text); - cdev->private->qdio_data = 0; + cdev->private->qdio_data = NULL; up(&irq_ptr->setting_up_sema); @@ -2926,7 +2920,7 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat) irq_ptr = cdev->private->qdio_data; - sprintf(dbf_text,"qehi%4x",cdev->private->sch_no); + sprintf(dbf_text,"qehi%4x",cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); @@ -2945,7 +2939,7 @@ qdio_initialize(struct qdio_initialize *init_data) int rc; char dbf_text[15]; - sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no); + sprintf(dbf_text,"qini%4x",init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); @@ -2966,7 +2960,7 @@ qdio_allocate(struct qdio_initialize *init_data) struct qdio_irq *irq_ptr; char dbf_text[15]; - sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no); + sprintf(dbf_text,"qalc%4x",init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) || @@ -2984,7 +2978,7 @@ qdio_allocate(struct qdio_initialize *init_data) qdio_allocate_do_dbf(init_data); /* create irq */ - irq_ptr=kmalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA); + irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); QDIO_DBF_TEXT0(0,setup,"irq_ptr:"); QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); @@ -2994,14 +2988,12 @@ qdio_allocate(struct qdio_initialize *init_data) return -ENOMEM; } - memset(irq_ptr,0,sizeof(struct qdio_irq)); - init_MUTEX(&irq_ptr->setting_up_sema); /* QDR must be in DMA area since CCW data address is only 32 bit */ irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA); if (!(irq_ptr->qdr)) { - kfree(irq_ptr); + free_page((unsigned long) irq_ptr); QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); return -ENOMEM; } @@ -3191,7 +3183,7 @@ qdio_establish(struct qdio_initialize *init_data) tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET); } - sprintf(dbf_text,"qest%4x",cdev->private->sch_no); + sprintf(dbf_text,"qest%4x",cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); @@ -3429,7 +3421,7 @@ do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, if ((used_elements+count==QDIO_MAX_BUFFERS_PER_Q)&& (callflags&QDIO_FLAG_UNDER_INTERRUPT)) - atomic_swap(&q->polling,0); + atomic_xchg(&q->polling,0); if (used_elements) return; @@ -3462,19 +3454,18 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, 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 */ + if (qdio_performance_stats) + perf_stats.start_time_outbound=NOW; 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 */ + if (qdio_performance_stats) { + perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound; + perf_stats.outbound_cnt++; + } return; } if (q->is_iqdio_q) { @@ -3504,9 +3495,8 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, 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 */ + if (qdio_performance_stats) + perf_stats.fast_reqs++; } } /* @@ -3517,10 +3507,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, __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 */ + if (qdio_performance_stats) { + perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound; + perf_stats.outbound_cnt++; + } } /* count must be 1 in iqdio */ @@ -3533,7 +3523,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, #ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; - sprintf(dbf_text,"doQD%04x",cdev->private->sch_no); + sprintf(dbf_text,"doQD%04x",cdev->private->schid.sch_no); QDIO_DBF_TEXT3(0,trace,dbf_text); #endif /* CONFIG_QDIO_DEBUG */ @@ -3578,7 +3568,6 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, 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) @@ -3594,29 +3583,29 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset, _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", + _OUTP_IT("Number of tasklet runs (total) : %lu\n", perf_stats.tl_runs); _OUTP_IT("\n"); - _OUTP_IT("Number of SIGA sync's issued : %u\n", + _OUTP_IT("Number of SIGA sync's issued : %lu\n", perf_stats.siga_syncs); - _OUTP_IT("Number of SIGA in's issued : %u\n", + _OUTP_IT("Number of SIGA in's issued : %lu\n", perf_stats.siga_ins); - _OUTP_IT("Number of SIGA out's issued : %u\n", + _OUTP_IT("Number of SIGA out's issued : %lu\n", perf_stats.siga_outs); - _OUTP_IT("Number of PCIs caught : %u\n", + _OUTP_IT("Number of PCIs caught : %lu\n", perf_stats.pcis); - _OUTP_IT("Number of adapter interrupts caught : %u\n", + _OUTP_IT("Number of adapter interrupts caught : %lu\n", perf_stats.thinints); - _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %u\n", + _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %lu\n", perf_stats.fast_reqs); _OUTP_IT("\n"); - _OUTP_IT("Total time of all inbound actions (us) incl. UL : %u\n", + _OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n", perf_stats.inbound_time); - _OUTP_IT("Number of inbound transfers : %u\n", + _OUTP_IT("Number of inbound transfers : %lu\n", perf_stats.inbound_cnt); - _OUTP_IT("Total time of all outbound do_QDIOs (us) : %u\n", + _OUTP_IT("Total time of all outbound do_QDIOs (us) : %lu\n", perf_stats.outbound_time); - _OUTP_IT("Number of do_QDIOs outbound : %u\n", + _OUTP_IT("Number of do_QDIOs outbound : %lu\n", perf_stats.outbound_cnt); _OUTP_IT("\n"); @@ -3624,12 +3613,10 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset, } 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); @@ -3641,20 +3628,58 @@ 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 */ + i_p_nc = 0; + i_p_c = 0; + ii_p_nc = 0; + ii_p_c = 0; + o_p_nc = 0; + o_p_c = 0; + memset(&perf_stats, 0, sizeof(struct qdio_perf_stats)); + } + } else { + QDIO_PRINT_WARN("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) { @@ -3686,10 +3711,10 @@ qdio_get_qdio_memory(void) for (i=1;i