aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/qdio.h4
-rw-r--r--drivers/s390/cio/qdio_main.c4
-rw-r--r--drivers/s390/cio/qdio_thinint.c54
3 files changed, 13 insertions, 49 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 0f4ef8769a3d..9b6ea3ca3ece 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -423,9 +423,9 @@ struct indicator_t {
423 423
424extern struct indicator_t *q_indicators; 424extern struct indicator_t *q_indicators;
425 425
426static inline int shared_ind(struct qdio_irq *irq_ptr) 426static inline int shared_ind(u32 *dsci)
427{ 427{
428 return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; 428 return dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
429} 429}
430 430
431/* prototypes for thin interrupt */ 431/* prototypes for thin interrupt */
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 194ea8c182b2..6621de94f3ad 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1552,7 +1552,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
1552 1552
1553 WARN_ON(queue_irqs_enabled(q)); 1553 WARN_ON(queue_irqs_enabled(q));
1554 1554
1555 if (!shared_ind(q->irq_ptr)) 1555 if (!shared_ind(q->irq_ptr->dsci))
1556 xchg(q->irq_ptr->dsci, 0); 1556 xchg(q->irq_ptr->dsci, 0);
1557 1557
1558 qdio_stop_polling(q); 1558 qdio_stop_polling(q);
@@ -1562,7 +1562,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
1562 * We need to check again to not lose initiative after 1562 * We need to check again to not lose initiative after
1563 * resetting the ACK state. 1563 * resetting the ACK state.
1564 */ 1564 */
1565 if (!shared_ind(q->irq_ptr) && *q->irq_ptr->dsci) 1565 if (!shared_ind(q->irq_ptr->dsci) && *q->irq_ptr->dsci)
1566 goto rescan; 1566 goto rescan;
1567 if (!qdio_inbound_q_done(q)) 1567 if (!qdio_inbound_q_done(q))
1568 goto rescan; 1568 goto rescan;
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 64b59a58a1cd..5c4e741d8221 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -36,22 +36,8 @@ static u8 *tiqdio_alsi;
36 36
37struct indicator_t *q_indicators; 37struct indicator_t *q_indicators;
38 38
39static int css_qdio_omit_svs;
40
41static u64 last_ai_time; 39static u64 last_ai_time;
42 40
43static inline unsigned long do_clear_global_summary(void)
44{
45 register unsigned long __fn asm("1") = 3;
46 register unsigned long __tmp asm("2");
47 register unsigned long __time asm("3");
48
49 asm volatile(
50 " .insn rre,0xb2650000,2,0"
51 : "+d" (__fn), "=d" (__tmp), "=d" (__time));
52 return __time;
53}
54
55/* returns addr for the device state change indicator */ 41/* returns addr for the device state change indicator */
56static u32 *get_indicator(void) 42static u32 *get_indicator(void)
57{ 43{
@@ -84,10 +70,6 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
84 struct qdio_q *q; 70 struct qdio_q *q;
85 int i; 71 int i;
86 72
87 /* No TDD facility? If we must use SIGA-s we can also omit SVS. */
88 if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync)
89 css_qdio_omit_svs = 1;
90
91 mutex_lock(&tiq_list_lock); 73 mutex_lock(&tiq_list_lock);
92 for_each_input_queue(irq_ptr, q, i) 74 for_each_input_queue(irq_ptr, q, i)
93 list_add_rcu(&q->entry, &tiq_list); 75 list_add_rcu(&q->entry, &tiq_list);
@@ -113,9 +95,9 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
113 } 95 }
114} 96}
115 97
116static inline int shared_ind_used(void) 98static inline u32 shared_ind_set(void)
117{ 99{
118 return atomic_read(&q_indicators[TIQDIO_SHARED_IND].count); 100 return q_indicators[TIQDIO_SHARED_IND].ind;
119} 101}
120 102
121/** 103/**
@@ -125,22 +107,12 @@ static inline int shared_ind_used(void)
125 */ 107 */
126static void tiqdio_thinint_handler(void *alsi, void *data) 108static void tiqdio_thinint_handler(void *alsi, void *data)
127{ 109{
110 u32 si_used = shared_ind_set();
128 struct qdio_q *q; 111 struct qdio_q *q;
129 112
130 last_ai_time = S390_lowcore.int_clock; 113 last_ai_time = S390_lowcore.int_clock;
131 kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++; 114 kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++;
132 115
133 /*
134 * SVS only when needed: issue SVS to benefit from iqdio interrupt
135 * avoidance (SVS clears adapter interrupt suppression overwrite).
136 */
137 if (!css_qdio_omit_svs)
138 do_clear_global_summary();
139
140 /* reset local summary indicator */
141 if (shared_ind_used())
142 xchg(tiqdio_alsi, 0);
143
144 /* protect tiq_list entries, only changed in activate or shutdown */ 116 /* protect tiq_list entries, only changed in activate or shutdown */
145 rcu_read_lock(); 117 rcu_read_lock();
146 118
@@ -148,7 +120,10 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
148 list_for_each_entry_rcu(q, &tiq_list, entry) { 120 list_for_each_entry_rcu(q, &tiq_list, entry) {
149 121
150 /* only process queues from changed sets */ 122 /* only process queues from changed sets */
151 if (!*q->irq_ptr->dsci) 123 if (unlikely(shared_ind(q->irq_ptr->dsci))) {
124 if (!si_used)
125 continue;
126 } else if (!*q->irq_ptr->dsci)
152 continue; 127 continue;
153 128
154 if (q->u.in.queue_start_poll) { 129 if (q->u.in.queue_start_poll) {
@@ -164,7 +139,7 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
164 q->irq_ptr->int_parm); 139 q->irq_ptr->int_parm);
165 } else { 140 } else {
166 /* only clear it if the indicator is non-shared */ 141 /* only clear it if the indicator is non-shared */
167 if (!shared_ind(q->irq_ptr)) 142 if (!shared_ind(q->irq_ptr->dsci))
168 xchg(q->irq_ptr->dsci, 0); 143 xchg(q->irq_ptr->dsci, 0);
169 /* 144 /*
170 * Call inbound processing but not directly 145 * Call inbound processing but not directly
@@ -180,13 +155,8 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
180 * If the shared indicator was used clear it now after all queues 155 * If the shared indicator was used clear it now after all queues
181 * were processed. 156 * were processed.
182 */ 157 */
183 if (shared_ind_used()) { 158 if (si_used && shared_ind_set())
184 xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0); 159 xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
185
186 /* prevent racing */
187 if (*tiqdio_alsi)
188 xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7);
189 }
190} 160}
191 161
192static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) 162static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
@@ -271,12 +241,6 @@ int qdio_establish_thinint(struct qdio_irq *irq_ptr)
271{ 241{
272 if (!is_thinint_irq(irq_ptr)) 242 if (!is_thinint_irq(irq_ptr))
273 return 0; 243 return 0;
274
275 /* Check for aif time delay disablement. If installed,
276 * omit SVS even under LPAR
277 */
278 if (css_general_characteristics.aif_tdd)
279 css_qdio_omit_svs = 1;
280 return set_subchannel_ind(irq_ptr, 0); 244 return set_subchannel_ind(irq_ptr, 0);
281} 245}
282 246