From 1ecbcfd57ed6ee11ec39eac9b6516883c925c558 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 2 Jun 2020 14:09:10 +0200 Subject: s390/qdio: remove Input tasklet code Both qeth and zfcp have fully moved to the polling-driven flow for Input Queues with commit 0a6e634535f1 ("s390/qdio: extend polling support to multiple queues") and commit 0b524abc2dd1 ("scsi: zfcp: Lift Input Queue tasklet from qdio"). So remove the tasklet code for Input Queues, streamline the IRQ handlers and push the tasklet struct into struct qdio_output_q. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio_debug.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/s390/cio/qdio_debug.c') diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 863d17c802ca..728abf7e9ccb 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -197,9 +197,6 @@ 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", -- cgit v1.2.3 From bd83917155c1e60a6634dfef708972076b068c6e Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 15 Sep 2020 10:04:39 +0300 Subject: s390/qdio: track time of last data IRQ for each device We currently track the time of the most recent QDIO Adapter Interrupt. This is a system-wide timestamp (as such interrupts are not bound to one specific qdio device). If interrupt processing stalls on one device but is functional for a different device, the timestamp continues to be updated and is of no help for problem diagnosis. So for debugging purposes also track the time of the last Data IRQ on a per-device level. Collect this data in the legacy non-AI path as well. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio.h | 1 + drivers/s390/cio/qdio_debug.c | 5 +++-- drivers/s390/cio/qdio_main.c | 1 + drivers/s390/cio/qdio_thinint.c | 4 +++- 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/s390/cio/qdio_debug.c') diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 4a4e4de45bc9..da29c3729cd9 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -252,6 +252,7 @@ struct qdio_irq { struct ccw_device *cdev; struct list_head entry; /* list of thinint devices */ struct dentry *debugfs_dev; + u64 last_data_irq_time; unsigned long int_parm; struct subchannel_id schid; diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 728abf7e9ccb..d091ae12c367 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -105,8 +105,9 @@ static int qstat_show(struct seq_file *m, void *v) if (!q) return 0; - seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n", - q->timestamp, last_ai_time); + seq_printf(m, "Timestamp: %llx\n", q->timestamp); + seq_printf(m, "Last Data IRQ: %llx Last AI: %llx\n", + q->irq_ptr->last_data_irq_time, last_ai_time); seq_printf(m, "nr_used: %d ftc: %d\n", atomic_read(&q->nr_buf_used), q->first_to_check); if (q->is_input_q) { diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 3b1e8ed4ba14..c56b690f0a93 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -804,6 +804,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) return; qdio_deliver_irq(irq_ptr); + irq_ptr->last_data_irq_time = S390_lowcore.int_clock; if (!pci_out_supported(irq_ptr) || !irq_ptr->scan_threshold) return; diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index e1b923633372..8e09bf3a2fcd 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -97,10 +97,11 @@ static inline u32 clear_shared_ind(void) */ static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating) { + u64 irq_time = S390_lowcore.int_clock; u32 si_used = clear_shared_ind(); struct qdio_irq *irq; - last_ai_time = S390_lowcore.int_clock; + last_ai_time = irq_time; inc_irq_stat(IRQIO_QAI); /* protect tiq_list entries, only changed in activate or shutdown */ @@ -119,6 +120,7 @@ static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating) } qdio_deliver_irq(irq); + irq->last_data_irq_time = irq_time; QDIO_PERF_STAT_INC(irq, adapter_int); } -- cgit v1.2.3 From 3bf526e036c9be08e8d3eb7b48c3b27d3d082332 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Sat, 30 Jan 2021 12:28:30 +0100 Subject: s390/qdio: inline qdio_kick_handler() We don't kick the handler for Input Queues anymore. Move the remaining code into its only caller. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio.h | 1 - drivers/s390/cio/qdio_debug.c | 1 - drivers/s390/cio/qdio_main.c | 35 ++++++++++++----------------------- 3 files changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers/s390/cio/qdio_debug.c') diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index da29c3729cd9..84425e294e36 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -146,7 +146,6 @@ struct qdio_dev_perf_stat { 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; diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index d091ae12c367..00384f58f218 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -203,7 +203,6 @@ static char *qperf_names[] = { "SIGA write", "SIGA sync", "Inbound calls", - "Inbound handler", "Inbound stop_polling", "Inbound queue full", "Outbound calls", diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index c56b690f0a93..a83101d9ec4a 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -545,28 +545,6 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q, return phys_aob; } -static void qdio_kick_handler(struct qdio_q *q, unsigned int start, - unsigned int count) -{ - if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) - return; - - if (q->is_input_q) { - qperf_inc(q, inbound_handler); - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); - } else { - qperf_inc(q, outbound_handler); - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", - start, count); - } - - q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, - q->irq_ptr->int_parm); - - /* for the next time */ - q->qdio_error = 0; -} - static inline int qdio_tasklet_schedule(struct qdio_q *q) { if (likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) { @@ -729,7 +707,18 @@ void qdio_outbound_tasklet(struct tasklet_struct *t) count = qdio_outbound_q_moved(q, start); if (count) { q->first_to_check = add_buf(start, count); - qdio_kick_handler(q, start, count); + + if (q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE) { + qperf_inc(q, outbound_handler); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", + start, count); + + q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, + start, count, q->irq_ptr->int_parm); + + /* for the next time */ + q->qdio_error = 0; + } } if (queue_type(q) == QDIO_ZFCP_QFMT && !pci_out_supported(q->irq_ptr) && -- cgit v1.2.3