diff options
Diffstat (limited to 'drivers/s390/cio/qdio_main.c')
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 102 |
1 files changed, 50 insertions, 52 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 6547ff469410..3ef8d071c64a 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/kernel_stat.h> | ||
19 | #include <linux/atomic.h> | 18 | #include <linux/atomic.h> |
20 | #include <asm/debug.h> | 19 | #include <asm/debug.h> |
21 | #include <asm/qdio.h> | 20 | #include <asm/qdio.h> |
@@ -105,9 +104,12 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | |||
105 | /* all done or next buffer state different */ | 104 | /* all done or next buffer state different */ |
106 | if (ccq == 0 || ccq == 32) | 105 | if (ccq == 0 || ccq == 32) |
107 | return 0; | 106 | return 0; |
108 | /* not all buffers processed */ | 107 | /* no buffer processed */ |
109 | if (ccq == 96 || ccq == 97) | 108 | if (ccq == 97) |
110 | return 1; | 109 | return 1; |
110 | /* not all buffers processed */ | ||
111 | if (ccq == 96) | ||
112 | return 2; | ||
111 | /* notify devices immediately */ | 113 | /* notify devices immediately */ |
112 | DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq); | 114 | DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq); |
113 | return -EIO; | 115 | return -EIO; |
@@ -127,10 +129,8 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | |||
127 | static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | 129 | static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, |
128 | int start, int count, int auto_ack) | 130 | int start, int count, int auto_ack) |
129 | { | 131 | { |
132 | int rc, tmp_count = count, tmp_start = start, nr = q->nr, retried = 0; | ||
130 | unsigned int ccq = 0; | 133 | unsigned int ccq = 0; |
131 | int tmp_count = count, tmp_start = start; | ||
132 | int nr = q->nr; | ||
133 | int rc; | ||
134 | 134 | ||
135 | BUG_ON(!q->irq_ptr->sch_token); | 135 | BUG_ON(!q->irq_ptr->sch_token); |
136 | qperf_inc(q, eqbs); | 136 | qperf_inc(q, eqbs); |
@@ -141,30 +141,34 @@ again: | |||
141 | ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count, | 141 | ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count, |
142 | auto_ack); | 142 | auto_ack); |
143 | rc = qdio_check_ccq(q, ccq); | 143 | rc = qdio_check_ccq(q, ccq); |
144 | 144 | if (!rc) | |
145 | /* At least one buffer was processed, return and extract the remaining | 145 | return count - tmp_count; |
146 | * buffers later. | ||
147 | */ | ||
148 | if ((ccq == 96) && (count != tmp_count)) { | ||
149 | qperf_inc(q, eqbs_partial); | ||
150 | return (count - tmp_count); | ||
151 | } | ||
152 | 146 | ||
153 | if (rc == 1) { | 147 | if (rc == 1) { |
154 | DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq); | 148 | DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq); |
155 | goto again; | 149 | goto again; |
156 | } | 150 | } |
157 | 151 | ||
158 | if (rc < 0) { | 152 | if (rc == 2) { |
159 | DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); | 153 | BUG_ON(tmp_count == count); |
160 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); | 154 | qperf_inc(q, eqbs_partial); |
161 | q->handler(q->irq_ptr->cdev, | 155 | DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x", |
162 | QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 156 | tmp_count); |
163 | q->nr, q->first_to_kick, count, | 157 | /* |
164 | q->irq_ptr->int_parm); | 158 | * Retry once, if that fails bail out and process the |
165 | return 0; | 159 | * extracted buffers before trying again. |
160 | */ | ||
161 | if (!retried++) | ||
162 | goto again; | ||
163 | else | ||
164 | return count - tmp_count; | ||
166 | } | 165 | } |
167 | return count - tmp_count; | 166 | |
167 | DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); | ||
168 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); | ||
169 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | ||
170 | 0, -1, -1, q->irq_ptr->int_parm); | ||
171 | return 0; | ||
168 | } | 172 | } |
169 | 173 | ||
170 | /** | 174 | /** |
@@ -197,22 +201,22 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start, | |||
197 | again: | 201 | again: |
198 | ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count); | 202 | ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count); |
199 | rc = qdio_check_ccq(q, ccq); | 203 | rc = qdio_check_ccq(q, ccq); |
200 | if (rc == 1) { | 204 | if (!rc) { |
205 | WARN_ON(tmp_count); | ||
206 | return count - tmp_count; | ||
207 | } | ||
208 | |||
209 | if (rc == 1 || rc == 2) { | ||
201 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq); | 210 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq); |
202 | qperf_inc(q, sqbs_partial); | 211 | qperf_inc(q, sqbs_partial); |
203 | goto again; | 212 | goto again; |
204 | } | 213 | } |
205 | if (rc < 0) { | 214 | |
206 | DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); | 215 | DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); |
207 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); | 216 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); |
208 | q->handler(q->irq_ptr->cdev, | 217 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION, |
209 | QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 218 | 0, -1, -1, q->irq_ptr->int_parm); |
210 | q->nr, q->first_to_kick, count, | 219 | return 0; |
211 | q->irq_ptr->int_parm); | ||
212 | return 0; | ||
213 | } | ||
214 | WARN_ON(tmp_count); | ||
215 | return count - tmp_count; | ||
216 | } | 220 | } |
217 | 221 | ||
218 | /* returns number of examined buffers and their common state in *state */ | 222 | /* returns number of examined buffers and their common state in *state */ |
@@ -277,7 +281,7 @@ static inline int set_buf_state(struct qdio_q *q, int bufnr, | |||
277 | } | 281 | } |
278 | 282 | ||
279 | /* set slsb states to initial state */ | 283 | /* set slsb states to initial state */ |
280 | void qdio_init_buf_states(struct qdio_irq *irq_ptr) | 284 | static void qdio_init_buf_states(struct qdio_irq *irq_ptr) |
281 | { | 285 | { |
282 | struct qdio_q *q; | 286 | struct qdio_q *q; |
283 | int i; | 287 | int i; |
@@ -446,7 +450,7 @@ static void process_buffer_error(struct qdio_q *q, int count) | |||
446 | qperf_inc(q, target_full); | 450 | qperf_inc(q, target_full); |
447 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", | 451 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", |
448 | q->first_to_check); | 452 | q->first_to_check); |
449 | return; | 453 | goto set; |
450 | } | 454 | } |
451 | 455 | ||
452 | DBF_ERROR("%4x BUF ERROR", SCH_NO(q)); | 456 | DBF_ERROR("%4x BUF ERROR", SCH_NO(q)); |
@@ -456,6 +460,7 @@ static void process_buffer_error(struct qdio_q *q, int count) | |||
456 | q->sbal[q->first_to_check]->element[14].sflags, | 460 | q->sbal[q->first_to_check]->element[14].sflags, |
457 | q->sbal[q->first_to_check]->element[15].sflags); | 461 | q->sbal[q->first_to_check]->element[15].sflags); |
458 | 462 | ||
463 | set: | ||
459 | /* | 464 | /* |
460 | * Interrupts may be avoided as long as the error is present | 465 | * Interrupts may be avoided as long as the error is present |
461 | * so change the buffer state immediately to avoid starvation. | 466 | * so change the buffer state immediately to avoid starvation. |
@@ -513,6 +518,8 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
513 | int count, stop; | 518 | int count, stop; |
514 | unsigned char state = 0; | 519 | unsigned char state = 0; |
515 | 520 | ||
521 | q->timestamp = get_clock_fast(); | ||
522 | |||
516 | /* | 523 | /* |
517 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 524 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
518 | * would return 0. | 525 | * would return 0. |
@@ -782,6 +789,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
782 | int count, stop; | 789 | int count, stop; |
783 | unsigned char state = 0; | 790 | unsigned char state = 0; |
784 | 791 | ||
792 | q->timestamp = get_clock_fast(); | ||
793 | |||
785 | if (need_siga_sync(q)) | 794 | if (need_siga_sync(q)) |
786 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && | 795 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && |
787 | !pci_out_supported(q)) || | 796 | !pci_out_supported(q)) || |
@@ -912,21 +921,13 @@ static void __qdio_outbound_processing(struct qdio_q *q) | |||
912 | if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) | 921 | if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) |
913 | goto sched; | 922 | goto sched; |
914 | 923 | ||
915 | /* bail out for HiperSockets unicast queues */ | ||
916 | if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) | ||
917 | return; | ||
918 | |||
919 | if ((queue_type(q) == QDIO_IQDIO_QFMT) && | ||
920 | (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) | ||
921 | goto sched; | ||
922 | |||
923 | if (q->u.out.pci_out_enabled) | 924 | if (q->u.out.pci_out_enabled) |
924 | return; | 925 | return; |
925 | 926 | ||
926 | /* | 927 | /* |
927 | * Now we know that queue type is either qeth without pci enabled | 928 | * Now we know that queue type is either qeth without pci enabled |
928 | * or HiperSockets multicast. Make sure buffer switch from PRIMED to | 929 | * or HiperSockets. Make sure buffer switch from PRIMED to EMPTY |
929 | * EMPTY is noticed and outbound_handler is called after some time. | 930 | * is noticed and outbound_handler is called after some time. |
930 | */ | 931 | */ |
931 | if (qdio_outbound_q_done(q)) | 932 | if (qdio_outbound_q_done(q)) |
932 | del_timer(&q->u.out.timer); | 933 | del_timer(&q->u.out.timer); |
@@ -1128,7 +1129,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1128 | return; | 1129 | return; |
1129 | } | 1130 | } |
1130 | 1131 | ||
1131 | kstat_cpu(smp_processor_id()).irqs[IOINT_QDI]++; | ||
1132 | if (irq_ptr->perf_stat_enabled) | 1132 | if (irq_ptr->perf_stat_enabled) |
1133 | irq_ptr->perf_stat.qdio_int++; | 1133 | irq_ptr->perf_stat.qdio_int++; |
1134 | 1134 | ||
@@ -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; |