diff options
| -rw-r--r-- | drivers/s390/cio/qdio.h | 29 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_main.c | 6 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 48 |
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 */ | ||
| 424 | struct 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 | |||
| 429 | extern struct indicator_t *q_indicators; | ||
| 430 | |||
| 431 | static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq) | ||
| 432 | { | ||
| 433 | return irq->nr_input_qs > 1; | ||
| 434 | } | ||
| 435 | |||
| 436 | static inline int references_shared_dsci(struct qdio_irq *irq) | ||
| 437 | { | ||
| 438 | return irq->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; | ||
| 439 | } | ||
| 440 | |||
| 441 | static 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 | |||
| 447 | extern u64 last_ai_time; | 421 | extern 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); | |||
| 457 | void tiqdio_free_memory(void); | 431 | void tiqdio_free_memory(void); |
| 458 | int tiqdio_register_thinints(void); | 432 | int tiqdio_register_thinints(void); |
| 459 | void tiqdio_unregister_thinints(void); | 433 | void tiqdio_unregister_thinints(void); |
| 460 | 434 | void clear_nonshared_ind(struct qdio_irq *); | |
| 435 | int test_nonshared_ind(struct qdio_irq *); | ||
| 461 | 436 | ||
| 462 | /* prototypes for setup */ | 437 | /* prototypes for setup */ |
| 463 | void qdio_inbound_processing(unsigned long data); | 438 | void 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 */ | ||
| 32 | struct 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 */ |
| 31 | static LIST_HEAD(tiq_list); | 38 | static LIST_HEAD(tiq_list); |
| @@ -34,7 +41,7 @@ static DEFINE_MUTEX(tiq_list_lock); | |||
| 34 | /* adapter local summary indicator */ | 41 | /* adapter local summary indicator */ |
| 35 | static u8 *tiqdio_alsi; | 42 | static u8 *tiqdio_alsi; |
| 36 | 43 | ||
| 37 | struct indicator_t *q_indicators; | 44 | static struct indicator_t *q_indicators; |
| 38 | 45 | ||
| 39 | u64 last_ai_time; | 46 | u64 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 | ||
| 100 | static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr) | ||
| 101 | { | ||
| 102 | return irq_ptr->nr_input_qs > 1; | ||
| 103 | } | ||
| 104 | |||
| 105 | static inline int references_shared_dsci(struct qdio_irq *irq_ptr) | ||
| 106 | { | ||
| 107 | return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; | ||
| 108 | } | ||
| 109 | |||
| 110 | static 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 | |||
| 116 | void 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 | |||
| 125 | int 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 | |||
| 93 | static inline u32 clear_shared_ind(void) | 137 | static 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 | /* |
