aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/qdio.h29
-rw-r--r--drivers/s390/cio/qdio_main.c6
-rw-r--r--drivers/s390/cio/qdio_thinint.c48
3 files changed, 50 insertions, 33 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 498a4cd99ff8..b962ffbc0803 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -418,32 +418,6 @@ static inline int multicast_outbound(struct qdio_q *q)
418#define queue_irqs_disabled(q) \ 418#define queue_irqs_disabled(q) \
419 (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0) 419 (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
420 420
421#define TIQDIO_SHARED_IND 63
422
423/* device state change indicators */
424struct indicator_t {
425 u32 ind; /* u32 because of compare-and-swap performance */
426 atomic_t count; /* use count, 0 or 1 for non-shared indicators */
427};
428
429extern struct indicator_t *q_indicators;
430
431static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq)
432{
433 return irq->nr_input_qs > 1;
434}
435
436static inline int references_shared_dsci(struct qdio_irq *irq)
437{
438 return irq->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
439}
440
441static inline int shared_ind(struct qdio_q *q)
442{
443 struct qdio_irq *i = q->irq_ptr;
444 return references_shared_dsci(i) || has_multiple_inq_on_dsci(i);
445}
446
447extern u64 last_ai_time; 421extern u64 last_ai_time;
448 422
449/* prototypes for thin interrupt */ 423/* prototypes for thin interrupt */
@@ -457,7 +431,8 @@ int tiqdio_allocate_memory(void);
457void tiqdio_free_memory(void); 431void tiqdio_free_memory(void);
458int tiqdio_register_thinints(void); 432int tiqdio_register_thinints(void);
459void tiqdio_unregister_thinints(void); 433void tiqdio_unregister_thinints(void);
460 434void clear_nonshared_ind(struct qdio_irq *);
435int test_nonshared_ind(struct qdio_irq *);
461 436
462/* prototypes for setup */ 437/* prototypes for setup */
463void qdio_inbound_processing(unsigned long data); 438void qdio_inbound_processing(unsigned long data);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 2fcdc0b2f0aa..3ef8d071c64a 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1719,9 +1719,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
1719 1719
1720 WARN_ON(queue_irqs_enabled(q)); 1720 WARN_ON(queue_irqs_enabled(q));
1721 1721
1722 if (!shared_ind(q)) 1722 clear_nonshared_ind(irq_ptr);
1723 xchg(q->irq_ptr->dsci, 0);
1724
1725 qdio_stop_polling(q); 1723 qdio_stop_polling(q);
1726 clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state); 1724 clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
1727 1725
@@ -1729,7 +1727,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
1729 * We need to check again to not lose initiative after 1727 * We need to check again to not lose initiative after
1730 * resetting the ACK state. 1728 * resetting the ACK state.
1731 */ 1729 */
1732 if (!shared_ind(q) && *q->irq_ptr->dsci) 1730 if (test_nonshared_ind(irq_ptr))
1733 goto rescan; 1731 goto rescan;
1734 if (!qdio_inbound_q_done(q)) 1732 if (!qdio_inbound_q_done(q))
1735 goto rescan; 1733 goto rescan;
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 9d1e7efb5bb5..011eadea3ee4 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -26,6 +26,13 @@
26 */ 26 */
27#define TIQDIO_NR_NONSHARED_IND 63 27#define TIQDIO_NR_NONSHARED_IND 63
28#define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1) 28#define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1)
29#define TIQDIO_SHARED_IND 63
30
31/* device state change indicators */
32struct indicator_t {
33 u32 ind; /* u32 because of compare-and-swap performance */
34 atomic_t count; /* use count, 0 or 1 for non-shared indicators */
35};
29 36
30/* list of thin interrupt input queues */ 37/* list of thin interrupt input queues */
31static LIST_HEAD(tiq_list); 38static LIST_HEAD(tiq_list);
@@ -34,7 +41,7 @@ static DEFINE_MUTEX(tiq_list_lock);
34/* adapter local summary indicator */ 41/* adapter local summary indicator */
35static u8 *tiqdio_alsi; 42static u8 *tiqdio_alsi;
36 43
37struct indicator_t *q_indicators; 44static struct indicator_t *q_indicators;
38 45
39u64 last_ai_time; 46u64 last_ai_time;
40 47
@@ -90,6 +97,43 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
90 synchronize_rcu(); 97 synchronize_rcu();
91} 98}
92 99
100static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)
101{
102 return irq_ptr->nr_input_qs > 1;
103}
104
105static inline int references_shared_dsci(struct qdio_irq *irq_ptr)
106{
107 return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
108}
109
110static inline int shared_ind(struct qdio_irq *irq_ptr)
111{
112 return references_shared_dsci(irq_ptr) ||
113 has_multiple_inq_on_dsci(irq_ptr);
114}
115
116void clear_nonshared_ind(struct qdio_irq *irq_ptr)
117{
118 if (!is_thinint_irq(irq_ptr))
119 return;
120 if (shared_ind(irq_ptr))
121 return;
122 xchg(irq_ptr->dsci, 0);
123}
124
125int test_nonshared_ind(struct qdio_irq *irq_ptr)
126{
127 if (!is_thinint_irq(irq_ptr))
128 return 0;
129 if (shared_ind(irq_ptr))
130 return 0;
131 if (*irq_ptr->dsci)
132 return 1;
133 else
134 return 0;
135}
136
93static inline u32 clear_shared_ind(void) 137static inline u32 clear_shared_ind(void)
94{ 138{
95 if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count)) 139 if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count))
@@ -119,7 +163,7 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
119 q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr, 163 q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
120 q->irq_ptr->int_parm); 164 q->irq_ptr->int_parm);
121 } else { 165 } else {
122 if (!shared_ind(q)) 166 if (!shared_ind(q->irq_ptr))
123 xchg(q->irq_ptr->dsci, 0); 167 xchg(q->irq_ptr->dsci, 0);
124 168
125 /* 169 /*