diff options
-rw-r--r-- | arch/s390/Kconfig | 7 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.h | 4 | ||||
-rw-r--r-- | drivers/s390/cio/qdio.c | 589 | ||||
-rw-r--r-- | drivers/s390/cio/qdio.h | 104 | ||||
-rw-r--r-- | include/asm-s390/qdio.h | 8 |
5 files changed, 556 insertions, 156 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 477ac2758bd5..1846fbfd6bf2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -240,8 +240,8 @@ config MACHCHK_WARNING | |||
240 | config QDIO | 240 | config QDIO |
241 | tristate "QDIO support" | 241 | tristate "QDIO support" |
242 | ---help--- | 242 | ---help--- |
243 | This driver provides the Queued Direct I/O base support for the | 243 | This driver provides the Queued Direct I/O base support for |
244 | IBM S/390 (G5 and G6) and eServer zSeries (z800, z890, z900 and z990). | 244 | IBM mainframes. |
245 | 245 | ||
246 | For details please refer to the documentation provided by IBM at | 246 | For details please refer to the documentation provided by IBM at |
247 | <http://www10.software.ibm.com/developerworks/opensource/linux390> | 247 | <http://www10.software.ibm.com/developerworks/opensource/linux390> |
@@ -263,7 +263,8 @@ config QDIO_DEBUG | |||
263 | bool "Extended debugging information" | 263 | bool "Extended debugging information" |
264 | depends on QDIO | 264 | depends on QDIO |
265 | help | 265 | help |
266 | Say Y here to get extended debugging output in /proc/s390dbf/qdio... | 266 | Say Y here to get extended debugging output in |
267 | /sys/kernel/debug/s390dbf/qdio... | ||
267 | Warning: this option reduces the performance of the QDIO module. | 268 | Warning: this option reduces the performance of the QDIO module. |
268 | 269 | ||
269 | If unsure, say N. | 270 | If unsure, say N. |
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index be20da49d147..69450134bec7 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -43,7 +43,9 @@ struct css_general_char { | |||
43 | u32 ext_mb : 1; /* bit 48 */ | 43 | u32 ext_mb : 1; /* bit 48 */ |
44 | u32 : 7; | 44 | u32 : 7; |
45 | u32 aif_tdd : 1; /* bit 56 */ | 45 | u32 aif_tdd : 1; /* bit 56 */ |
46 | u32 : 10; | 46 | u32 : 1; |
47 | u32 qebsm : 1; /* bit 58 */ | ||
48 | u32 : 8; | ||
47 | u32 aif_osa : 1; /* bit 67 */ | 49 | u32 aif_osa : 1; /* bit 67 */ |
48 | u32 : 28; | 50 | u32 : 28; |
49 | }__attribute__((packed)); | 51 | }__attribute__((packed)); |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index eb39218b925e..e8bdfcd1d02a 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #include "ioasm.h" | 56 | #include "ioasm.h" |
57 | #include "chsc.h" | 57 | #include "chsc.h" |
58 | 58 | ||
59 | #define VERSION_QDIO_C "$Revision: 1.108 $" | 59 | #define VERSION_QDIO_C "$Revision: 1.113 $" |
60 | 60 | ||
61 | /****************** MODULE PARAMETER VARIABLES ********************/ | 61 | /****************** MODULE PARAMETER VARIABLES ********************/ |
62 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); | 62 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); |
@@ -76,6 +76,7 @@ static struct qdio_perf_stats perf_stats; | |||
76 | #endif /* QDIO_PERFORMANCE_STATS */ | 76 | #endif /* QDIO_PERFORMANCE_STATS */ |
77 | 77 | ||
78 | static int hydra_thinints; | 78 | static int hydra_thinints; |
79 | static int is_passthrough = 0; | ||
79 | static int omit_svs; | 80 | static int omit_svs; |
80 | 81 | ||
81 | static int indicator_used[INDICATORS_PER_CACHELINE]; | 82 | static int indicator_used[INDICATORS_PER_CACHELINE]; |
@@ -136,12 +137,126 @@ qdio_release_q(struct qdio_q *q) | |||
136 | atomic_dec(&q->use_count); | 137 | atomic_dec(&q->use_count); |
137 | } | 138 | } |
138 | 139 | ||
139 | static volatile inline void | 140 | /*check ccq */ |
140 | qdio_set_slsb(volatile char *slsb, unsigned char value) | 141 | static inline int |
142 | qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | ||
141 | { | 143 | { |
142 | xchg((char*)slsb,value); | 144 | char dbf_text[15]; |
145 | |||
146 | if (ccq == 0 || ccq == 32 || ccq == 96) | ||
147 | return 0; | ||
148 | if (ccq == 97) | ||
149 | return 1; | ||
150 | /*notify devices immediately*/ | ||
151 | sprintf(dbf_text,"%d", ccq); | ||
152 | QDIO_DBF_TEXT2(1,trace,dbf_text); | ||
153 | return -EIO; | ||
143 | } | 154 | } |
155 | /* EQBS: extract buffer states */ | ||
156 | static inline int | ||
157 | qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | ||
158 | unsigned int *start, unsigned int *cnt) | ||
159 | { | ||
160 | struct qdio_irq *irq; | ||
161 | unsigned int tmp_cnt, q_no, ccq; | ||
162 | int rc ; | ||
163 | char dbf_text[15]; | ||
144 | 164 | ||
165 | ccq = 0; | ||
166 | tmp_cnt = *cnt; | ||
167 | irq = (struct qdio_irq*)q->irq_ptr; | ||
168 | q_no = q->q_no; | ||
169 | if(!q->is_input_q) | ||
170 | q_no += irq->no_input_qs; | ||
171 | ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); | ||
172 | rc = qdio_check_ccq(q, ccq); | ||
173 | if (rc < 0) { | ||
174 | QDIO_DBF_TEXT2(1,trace,"eqberr"); | ||
175 | sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no); | ||
176 | QDIO_DBF_TEXT2(1,trace,dbf_text); | ||
177 | q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION| | ||
178 | QDIO_STATUS_LOOK_FOR_ERROR, | ||
179 | 0, 0, 0, -1, -1, q->int_parm); | ||
180 | return 0; | ||
181 | } | ||
182 | return (tmp_cnt - *cnt); | ||
183 | } | ||
184 | |||
185 | /* SQBS: set buffer states */ | ||
186 | static inline int | ||
187 | qdio_do_sqbs(struct qdio_q *q, unsigned char state, | ||
188 | unsigned int *start, unsigned int *cnt) | ||
189 | { | ||
190 | struct qdio_irq *irq; | ||
191 | unsigned int tmp_cnt, q_no, ccq; | ||
192 | int rc; | ||
193 | char dbf_text[15]; | ||
194 | |||
195 | ccq = 0; | ||
196 | tmp_cnt = *cnt; | ||
197 | irq = (struct qdio_irq*)q->irq_ptr; | ||
198 | q_no = q->q_no; | ||
199 | if(!q->is_input_q) | ||
200 | q_no += irq->no_input_qs; | ||
201 | ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt); | ||
202 | rc = qdio_check_ccq(q, ccq); | ||
203 | if (rc < 0) { | ||
204 | QDIO_DBF_TEXT3(1,trace,"sqberr"); | ||
205 | sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no); | ||
206 | QDIO_DBF_TEXT3(1,trace,dbf_text); | ||
207 | q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION| | ||
208 | QDIO_STATUS_LOOK_FOR_ERROR, | ||
209 | 0, 0, 0, -1, -1, q->int_parm); | ||
210 | return 0; | ||
211 | } | ||
212 | return (tmp_cnt - *cnt); | ||
213 | } | ||
214 | |||
215 | static inline int | ||
216 | qdio_set_slsb(struct qdio_q *q, unsigned int *bufno, | ||
217 | unsigned char state, unsigned int *count) | ||
218 | { | ||
219 | volatile char *slsb; | ||
220 | struct qdio_irq *irq; | ||
221 | |||
222 | irq = (struct qdio_irq*)q->irq_ptr; | ||
223 | if (!irq->is_qebsm) { | ||
224 | slsb = (char *)&q->slsb.acc.val[(*bufno)]; | ||
225 | xchg(slsb, state); | ||
226 | return 1; | ||
227 | } | ||
228 | return qdio_do_sqbs(q, state, bufno, count); | ||
229 | } | ||
230 | |||
231 | #ifdef CONFIG_QDIO_DEBUG | ||
232 | static inline void | ||
233 | qdio_trace_slsb(struct qdio_q *q) | ||
234 | { | ||
235 | if (q->queue_type==QDIO_TRACE_QTYPE) { | ||
236 | if (q->is_input_q) | ||
237 | QDIO_DBF_HEX2(0,slsb_in,&q->slsb, | ||
238 | QDIO_MAX_BUFFERS_PER_Q); | ||
239 | else | ||
240 | QDIO_DBF_HEX2(0,slsb_out,&q->slsb, | ||
241 | QDIO_MAX_BUFFERS_PER_Q); | ||
242 | } | ||
243 | } | ||
244 | #endif | ||
245 | |||
246 | static inline int | ||
247 | set_slsb(struct qdio_q *q, unsigned int *bufno, | ||
248 | unsigned char state, unsigned int *count) | ||
249 | { | ||
250 | int rc; | ||
251 | #ifdef CONFIG_QDIO_DEBUG | ||
252 | qdio_trace_slsb(q); | ||
253 | #endif | ||
254 | rc = qdio_set_slsb(q, bufno, state, count); | ||
255 | #ifdef CONFIG_QDIO_DEBUG | ||
256 | qdio_trace_slsb(q); | ||
257 | #endif | ||
258 | return rc; | ||
259 | } | ||
145 | static inline int | 260 | static inline int |
146 | qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, | 261 | qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, |
147 | unsigned int gpr3) | 262 | unsigned int gpr3) |
@@ -155,7 +270,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, | |||
155 | perf_stats.siga_syncs++; | 270 | perf_stats.siga_syncs++; |
156 | #endif /* QDIO_PERFORMANCE_STATS */ | 271 | #endif /* QDIO_PERFORMANCE_STATS */ |
157 | 272 | ||
158 | cc = do_siga_sync(q->irq, gpr2, gpr3); | 273 | cc = do_siga_sync(0x10000|q->irq, gpr2, gpr3); |
159 | if (cc) | 274 | if (cc) |
160 | QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); | 275 | QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); |
161 | 276 | ||
@@ -170,6 +285,19 @@ qdio_siga_sync_q(struct qdio_q *q) | |||
170 | return qdio_siga_sync(q, q->mask, 0); | 285 | return qdio_siga_sync(q, q->mask, 0); |
171 | } | 286 | } |
172 | 287 | ||
288 | static int | ||
289 | __do_siga_output(struct qdio_q *q, unsigned int *busy_bit) | ||
290 | { | ||
291 | struct qdio_irq *irq; | ||
292 | unsigned int fc = 0; | ||
293 | |||
294 | irq = (struct qdio_irq *) q->irq_ptr; | ||
295 | if (!irq->is_qebsm) | ||
296 | return do_siga_output(0x10000|q->irq, q->mask, busy_bit, fc); | ||
297 | fc |= 0x80; | ||
298 | return do_siga_output(irq->sch_token, q->mask, busy_bit, fc); | ||
299 | } | ||
300 | |||
173 | /* | 301 | /* |
174 | * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns | 302 | * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns |
175 | * an access exception | 303 | * an access exception |
@@ -189,7 +317,7 @@ qdio_siga_output(struct qdio_q *q) | |||
189 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 317 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
190 | 318 | ||
191 | for (;;) { | 319 | for (;;) { |
192 | cc = do_siga_output(q->irq, q->mask, &busy_bit); | 320 | cc = __do_siga_output(q, &busy_bit); |
193 | //QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit); | 321 | //QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit); |
194 | if ((cc==2) && (busy_bit) && (q->is_iqdio_q)) { | 322 | if ((cc==2) && (busy_bit) && (q->is_iqdio_q)) { |
195 | if (!start_time) | 323 | if (!start_time) |
@@ -221,7 +349,7 @@ qdio_siga_input(struct qdio_q *q) | |||
221 | perf_stats.siga_ins++; | 349 | perf_stats.siga_ins++; |
222 | #endif /* QDIO_PERFORMANCE_STATS */ | 350 | #endif /* QDIO_PERFORMANCE_STATS */ |
223 | 351 | ||
224 | cc = do_siga_input(q->irq, q->mask); | 352 | cc = do_siga_input(0x10000|q->irq, q->mask); |
225 | 353 | ||
226 | if (cc) | 354 | if (cc) |
227 | QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); | 355 | QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); |
@@ -230,7 +358,7 @@ qdio_siga_input(struct qdio_q *q) | |||
230 | } | 358 | } |
231 | 359 | ||
232 | /* locked by the locks in qdio_activate and qdio_cleanup */ | 360 | /* locked by the locks in qdio_activate and qdio_cleanup */ |
233 | static __u32 volatile * | 361 | static __u32 * |
234 | qdio_get_indicator(void) | 362 | qdio_get_indicator(void) |
235 | { | 363 | { |
236 | int i; | 364 | int i; |
@@ -258,7 +386,7 @@ qdio_put_indicator(__u32 *addr) | |||
258 | atomic_dec(&spare_indicator_usecount); | 386 | atomic_dec(&spare_indicator_usecount); |
259 | } | 387 | } |
260 | 388 | ||
261 | static inline volatile void | 389 | static inline void |
262 | tiqdio_clear_summary_bit(__u32 *location) | 390 | tiqdio_clear_summary_bit(__u32 *location) |
263 | { | 391 | { |
264 | QDIO_DBF_TEXT5(0,trace,"clrsummb"); | 392 | QDIO_DBF_TEXT5(0,trace,"clrsummb"); |
@@ -267,7 +395,7 @@ tiqdio_clear_summary_bit(__u32 *location) | |||
267 | xchg(location,0); | 395 | xchg(location,0); |
268 | } | 396 | } |
269 | 397 | ||
270 | static inline volatile void | 398 | static inline void |
271 | tiqdio_set_summary_bit(__u32 *location) | 399 | tiqdio_set_summary_bit(__u32 *location) |
272 | { | 400 | { |
273 | QDIO_DBF_TEXT5(0,trace,"setsummb"); | 401 | QDIO_DBF_TEXT5(0,trace,"setsummb"); |
@@ -336,7 +464,9 @@ static inline int | |||
336 | qdio_stop_polling(struct qdio_q *q) | 464 | qdio_stop_polling(struct qdio_q *q) |
337 | { | 465 | { |
338 | #ifdef QDIO_USE_PROCESSING_STATE | 466 | #ifdef QDIO_USE_PROCESSING_STATE |
339 | int gsf; | 467 | unsigned int tmp, gsf, count = 1; |
468 | unsigned char state = 0; | ||
469 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | ||
340 | 470 | ||
341 | if (!atomic_swap(&q->polling,0)) | 471 | if (!atomic_swap(&q->polling,0)) |
342 | return 1; | 472 | return 1; |
@@ -348,17 +478,22 @@ qdio_stop_polling(struct qdio_q *q) | |||
348 | if (!q->is_input_q) | 478 | if (!q->is_input_q) |
349 | return 1; | 479 | return 1; |
350 | 480 | ||
351 | gsf=GET_SAVED_FRONTIER(q); | 481 | tmp = gsf = GET_SAVED_FRONTIER(q); |
352 | set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)& | 482 | tmp = ((tmp + QDIO_MAX_BUFFERS_PER_Q-1) & (QDIO_MAX_BUFFERS_PER_Q-1) ); |
353 | (QDIO_MAX_BUFFERS_PER_Q-1)], | 483 | set_slsb(q, &tmp, SLSB_P_INPUT_NOT_INIT, &count); |
354 | SLSB_P_INPUT_NOT_INIT); | 484 | |
355 | /* | 485 | /* |
356 | * we don't issue this SYNC_MEMORY, as we trust Rick T and | 486 | * we don't issue this SYNC_MEMORY, as we trust Rick T and |
357 | * moreover will not use the PROCESSING state under VM, so | 487 | * moreover will not use the PROCESSING state under VM, so |
358 | * q->polling was 0 anyway | 488 | * q->polling was 0 anyway |
359 | */ | 489 | */ |
360 | /*SYNC_MEMORY;*/ | 490 | /*SYNC_MEMORY;*/ |
361 | if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED) | 491 | if (irq->is_qebsm) { |
492 | count = 1; | ||
493 | qdio_do_eqbs(q, &state, &gsf, &count); | ||
494 | } else | ||
495 | state = q->slsb.acc.val[gsf]; | ||
496 | if (state != SLSB_P_INPUT_PRIMED) | ||
362 | return 1; | 497 | return 1; |
363 | /* | 498 | /* |
364 | * set our summary bit again, as otherwise there is a | 499 | * set our summary bit again, as otherwise there is a |
@@ -431,18 +566,136 @@ tiqdio_clear_global_summary(void) | |||
431 | 566 | ||
432 | 567 | ||
433 | /************************* OUTBOUND ROUTINES *******************************/ | 568 | /************************* OUTBOUND ROUTINES *******************************/ |
569 | static int | ||
570 | qdio_qebsm_get_outbound_buffer_frontier(struct qdio_q *q) | ||
571 | { | ||
572 | struct qdio_irq *irq; | ||
573 | unsigned char state; | ||
574 | unsigned int cnt, count, ftc; | ||
575 | |||
576 | irq = (struct qdio_irq *) q->irq_ptr; | ||
577 | if ((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis)) | ||
578 | SYNC_MEMORY; | ||
579 | |||
580 | ftc = q->first_to_check; | ||
581 | count = qdio_min(atomic_read(&q->number_of_buffers_used), | ||
582 | (QDIO_MAX_BUFFERS_PER_Q-1)); | ||
583 | if (count == 0) | ||
584 | return q->first_to_check; | ||
585 | cnt = qdio_do_eqbs(q, &state, &ftc, &count); | ||
586 | if (cnt == 0) | ||
587 | return q->first_to_check; | ||
588 | switch (state) { | ||
589 | case SLSB_P_OUTPUT_ERROR: | ||
590 | QDIO_DBF_TEXT3(0,trace,"outperr"); | ||
591 | atomic_sub(cnt , &q->number_of_buffers_used); | ||
592 | if (q->qdio_error) | ||
593 | q->error_status_flags |= | ||
594 | QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR; | ||
595 | q->qdio_error = SLSB_P_OUTPUT_ERROR; | ||
596 | q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR; | ||
597 | q->first_to_check = ftc; | ||
598 | break; | ||
599 | case SLSB_P_OUTPUT_EMPTY: | ||
600 | QDIO_DBF_TEXT5(0,trace,"outpempt"); | ||
601 | atomic_sub(cnt, &q->number_of_buffers_used); | ||
602 | q->first_to_check = ftc; | ||
603 | break; | ||
604 | case SLSB_CU_OUTPUT_PRIMED: | ||
605 | /* all buffers primed */ | ||
606 | QDIO_DBF_TEXT5(0,trace,"outpprim"); | ||
607 | break; | ||
608 | default: | ||
609 | break; | ||
610 | } | ||
611 | QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); | ||
612 | return q->first_to_check; | ||
613 | } | ||
614 | |||
615 | static int | ||
616 | qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q) | ||
617 | { | ||
618 | struct qdio_irq *irq; | ||
619 | unsigned char state; | ||
620 | int tmp, ftc, count, cnt; | ||
621 | char dbf_text[15]; | ||
622 | |||
623 | |||
624 | irq = (struct qdio_irq *) q->irq_ptr; | ||
625 | ftc = q->first_to_check; | ||
626 | count = qdio_min(atomic_read(&q->number_of_buffers_used), | ||
627 | (QDIO_MAX_BUFFERS_PER_Q-1)); | ||
628 | if (count == 0) | ||
629 | return q->first_to_check; | ||
630 | cnt = qdio_do_eqbs(q, &state, &ftc, &count); | ||
631 | if (cnt == 0) | ||
632 | return q->first_to_check; | ||
633 | switch (state) { | ||
634 | case SLSB_P_INPUT_ERROR : | ||
635 | #ifdef CONFIG_QDIO_DEBUG | ||
636 | QDIO_DBF_TEXT3(1,trace,"inperr"); | ||
637 | sprintf(dbf_text,"%2x,%2x",ftc,count); | ||
638 | QDIO_DBF_TEXT3(1,trace,dbf_text); | ||
639 | #endif /* CONFIG_QDIO_DEBUG */ | ||
640 | if (q->qdio_error) | ||
641 | q->error_status_flags |= | ||
642 | QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR; | ||
643 | q->qdio_error = SLSB_P_INPUT_ERROR; | ||
644 | q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR; | ||
645 | atomic_sub(cnt, &q->number_of_buffers_used); | ||
646 | q->first_to_check = ftc; | ||
647 | break; | ||
648 | case SLSB_P_INPUT_PRIMED : | ||
649 | QDIO_DBF_TEXT3(0,trace,"inptprim"); | ||
650 | sprintf(dbf_text,"%2x,%2x",ftc,count); | ||
651 | QDIO_DBF_TEXT3(1,trace,dbf_text); | ||
652 | tmp = 0; | ||
653 | ftc = q->first_to_check; | ||
654 | #ifdef QDIO_USE_PROCESSING_STATE | ||
655 | if (cnt > 1) { | ||
656 | cnt -= 1; | ||
657 | tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt); | ||
658 | if (!tmp) | ||
659 | break; | ||
660 | } | ||
661 | cnt = 1; | ||
662 | tmp += set_slsb(q, &ftc, | ||
663 | SLSB_P_INPUT_PROCESSING, &cnt); | ||
664 | atomic_set(&q->polling, 1); | ||
665 | #else | ||
666 | tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt); | ||
667 | #endif | ||
668 | atomic_sub(tmp, &q->number_of_buffers_used); | ||
669 | q->first_to_check = ftc; | ||
670 | break; | ||
671 | case SLSB_CU_INPUT_EMPTY: | ||
672 | case SLSB_P_INPUT_NOT_INIT: | ||
673 | case SLSB_P_INPUT_PROCESSING: | ||
674 | QDIO_DBF_TEXT5(0,trace,"inpnipro"); | ||
675 | break; | ||
676 | default: | ||
677 | break; | ||
678 | } | ||
679 | QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); | ||
680 | return q->first_to_check; | ||
681 | } | ||
434 | 682 | ||
435 | static inline int | 683 | static inline int |
436 | qdio_get_outbound_buffer_frontier(struct qdio_q *q) | 684 | qdio_get_outbound_buffer_frontier(struct qdio_q *q) |
437 | { | 685 | { |
438 | int f,f_mod_no; | 686 | struct qdio_irq *irq; |
439 | volatile char *slsb; | 687 | volatile char *slsb; |
440 | int first_not_to_check; | 688 | unsigned int count = 1; |
689 | int first_not_to_check, f, f_mod_no; | ||
441 | char dbf_text[15]; | 690 | char dbf_text[15]; |
442 | 691 | ||
443 | QDIO_DBF_TEXT4(0,trace,"getobfro"); | 692 | QDIO_DBF_TEXT4(0,trace,"getobfro"); |
444 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 693 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
445 | 694 | ||
695 | irq = (struct qdio_irq *) q->irq_ptr; | ||
696 | if (irq->is_qebsm) | ||
697 | return qdio_qebsm_get_outbound_buffer_frontier(q); | ||
698 | |||
446 | slsb=&q->slsb.acc.val[0]; | 699 | slsb=&q->slsb.acc.val[0]; |
447 | f_mod_no=f=q->first_to_check; | 700 | f_mod_no=f=q->first_to_check; |
448 | /* | 701 | /* |
@@ -484,7 +737,7 @@ check_next: | |||
484 | QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); | 737 | QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); |
485 | 738 | ||
486 | /* kind of process the buffer */ | 739 | /* kind of process the buffer */ |
487 | set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT); | 740 | set_slsb(q, &f_mod_no, SLSB_P_OUTPUT_NOT_INIT, &count); |
488 | 741 | ||
489 | /* | 742 | /* |
490 | * we increment the frontier, as this buffer | 743 | * we increment the frontier, as this buffer |
@@ -597,48 +850,48 @@ qdio_kick_outbound_q(struct qdio_q *q) | |||
597 | 850 | ||
598 | result=qdio_siga_output(q); | 851 | result=qdio_siga_output(q); |
599 | 852 | ||
600 | switch (result) { | 853 | switch (result) { |
601 | case 0: | 854 | case 0: |
602 | /* went smooth this time, reset timestamp */ | 855 | /* went smooth this time, reset timestamp */ |
603 | #ifdef CONFIG_QDIO_DEBUG | 856 | #ifdef CONFIG_QDIO_DEBUG |
604 | QDIO_DBF_TEXT3(0,trace,"cc2reslv"); | 857 | QDIO_DBF_TEXT3(0,trace,"cc2reslv"); |
605 | sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, | 858 | sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, |
606 | atomic_read(&q->busy_siga_counter)); | 859 | atomic_read(&q->busy_siga_counter)); |
607 | QDIO_DBF_TEXT3(0,trace,dbf_text); | 860 | QDIO_DBF_TEXT3(0,trace,dbf_text); |
608 | #endif /* CONFIG_QDIO_DEBUG */ | 861 | #endif /* CONFIG_QDIO_DEBUG */ |
609 | q->timing.busy_start=0; | 862 | q->timing.busy_start=0; |
863 | break; | ||
864 | case (2|QDIO_SIGA_ERROR_B_BIT_SET): | ||
865 | /* cc=2 and busy bit: */ | ||
866 | atomic_inc(&q->busy_siga_counter); | ||
867 | |||
868 | /* if the last siga was successful, save | ||
869 | * timestamp here */ | ||
870 | if (!q->timing.busy_start) | ||
871 | q->timing.busy_start=NOW; | ||
872 | |||
873 | /* if we're in time, don't touch error_status_flags | ||
874 | * and siga_error */ | ||
875 | if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) { | ||
876 | qdio_mark_q(q); | ||
610 | break; | 877 | break; |
611 | case (2|QDIO_SIGA_ERROR_B_BIT_SET): | 878 | } |
612 | /* cc=2 and busy bit: */ | 879 | QDIO_DBF_TEXT2(0,trace,"cc2REPRT"); |
613 | atomic_inc(&q->busy_siga_counter); | ||
614 | |||
615 | /* if the last siga was successful, save | ||
616 | * timestamp here */ | ||
617 | if (!q->timing.busy_start) | ||
618 | q->timing.busy_start=NOW; | ||
619 | |||
620 | /* if we're in time, don't touch error_status_flags | ||
621 | * and siga_error */ | ||
622 | if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) { | ||
623 | qdio_mark_q(q); | ||
624 | break; | ||
625 | } | ||
626 | QDIO_DBF_TEXT2(0,trace,"cc2REPRT"); | ||
627 | #ifdef CONFIG_QDIO_DEBUG | 880 | #ifdef CONFIG_QDIO_DEBUG |
628 | sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, | 881 | sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, |
629 | atomic_read(&q->busy_siga_counter)); | 882 | atomic_read(&q->busy_siga_counter)); |
630 | QDIO_DBF_TEXT3(0,trace,dbf_text); | 883 | QDIO_DBF_TEXT3(0,trace,dbf_text); |
631 | #endif /* CONFIG_QDIO_DEBUG */ | 884 | #endif /* CONFIG_QDIO_DEBUG */ |
632 | /* else fallthrough and report error */ | 885 | /* else fallthrough and report error */ |
633 | default: | 886 | default: |
634 | /* for plain cc=1, 2 or 3: */ | 887 | /* for plain cc=1, 2 or 3: */ |
635 | if (q->siga_error) | 888 | if (q->siga_error) |
636 | q->error_status_flags|= | ||
637 | QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; | ||
638 | q->error_status_flags|= | 889 | q->error_status_flags|= |
639 | QDIO_STATUS_LOOK_FOR_ERROR; | 890 | QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; |
640 | q->siga_error=result; | 891 | q->error_status_flags|= |
641 | } | 892 | QDIO_STATUS_LOOK_FOR_ERROR; |
893 | q->siga_error=result; | ||
894 | } | ||
642 | } | 895 | } |
643 | 896 | ||
644 | static inline void | 897 | static inline void |
@@ -743,8 +996,10 @@ qdio_outbound_processing(struct qdio_q *q) | |||
743 | static inline int | 996 | static inline int |
744 | qdio_get_inbound_buffer_frontier(struct qdio_q *q) | 997 | qdio_get_inbound_buffer_frontier(struct qdio_q *q) |
745 | { | 998 | { |
999 | struct qdio_irq *irq; | ||
746 | int f,f_mod_no; | 1000 | int f,f_mod_no; |
747 | volatile char *slsb; | 1001 | volatile char *slsb; |
1002 | unsigned int count = 1; | ||
748 | int first_not_to_check; | 1003 | int first_not_to_check; |
749 | #ifdef CONFIG_QDIO_DEBUG | 1004 | #ifdef CONFIG_QDIO_DEBUG |
750 | char dbf_text[15]; | 1005 | char dbf_text[15]; |
@@ -756,6 +1011,10 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) | |||
756 | QDIO_DBF_TEXT4(0,trace,"getibfro"); | 1011 | QDIO_DBF_TEXT4(0,trace,"getibfro"); |
757 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 1012 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
758 | 1013 | ||
1014 | irq = (struct qdio_irq *) q->irq_ptr; | ||
1015 | if (irq->is_qebsm) | ||
1016 | return qdio_qebsm_get_inbound_buffer_frontier(q); | ||
1017 | |||
759 | slsb=&q->slsb.acc.val[0]; | 1018 | slsb=&q->slsb.acc.val[0]; |
760 | f_mod_no=f=q->first_to_check; | 1019 | f_mod_no=f=q->first_to_check; |
761 | /* | 1020 | /* |
@@ -792,19 +1051,19 @@ check_next: | |||
792 | * kill VM in terms of CP overhead | 1051 | * kill VM in terms of CP overhead |
793 | */ | 1052 | */ |
794 | if (q->siga_sync) { | 1053 | if (q->siga_sync) { |
795 | set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); | 1054 | set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count); |
796 | } else { | 1055 | } else { |
797 | /* set the previous buffer to NOT_INIT. The current | 1056 | /* set the previous buffer to NOT_INIT. The current |
798 | * buffer will be set to PROCESSING at the end of | 1057 | * buffer will be set to PROCESSING at the end of |
799 | * this function to avoid further interrupts. */ | 1058 | * this function to avoid further interrupts. */ |
800 | if (last_position>=0) | 1059 | if (last_position>=0) |
801 | set_slsb(&slsb[last_position], | 1060 | set_slsb(q, &last_position, |
802 | SLSB_P_INPUT_NOT_INIT); | 1061 | SLSB_P_INPUT_NOT_INIT, &count); |
803 | atomic_set(&q->polling,1); | 1062 | atomic_set(&q->polling,1); |
804 | last_position=f_mod_no; | 1063 | last_position=f_mod_no; |
805 | } | 1064 | } |
806 | #else /* QDIO_USE_PROCESSING_STATE */ | 1065 | #else /* QDIO_USE_PROCESSING_STATE */ |
807 | set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); | 1066 | set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count); |
808 | #endif /* QDIO_USE_PROCESSING_STATE */ | 1067 | #endif /* QDIO_USE_PROCESSING_STATE */ |
809 | /* | 1068 | /* |
810 | * not needed, as the inbound queue will be synced on the next | 1069 | * not needed, as the inbound queue will be synced on the next |
@@ -829,7 +1088,7 @@ check_next: | |||
829 | QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); | 1088 | QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); |
830 | 1089 | ||
831 | /* kind of process the buffer */ | 1090 | /* kind of process the buffer */ |
832 | set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); | 1091 | set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count); |
833 | 1092 | ||
834 | if (q->qdio_error) | 1093 | if (q->qdio_error) |
835 | q->error_status_flags|= | 1094 | q->error_status_flags|= |
@@ -857,7 +1116,7 @@ out: | |||
857 | 1116 | ||
858 | #ifdef QDIO_USE_PROCESSING_STATE | 1117 | #ifdef QDIO_USE_PROCESSING_STATE |
859 | if (last_position>=0) | 1118 | if (last_position>=0) |
860 | set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING); | 1119 | set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count); |
861 | #endif /* QDIO_USE_PROCESSING_STATE */ | 1120 | #endif /* QDIO_USE_PROCESSING_STATE */ |
862 | 1121 | ||
863 | QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); | 1122 | QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); |
@@ -902,6 +1161,10 @@ static inline int | |||
902 | tiqdio_is_inbound_q_done(struct qdio_q *q) | 1161 | tiqdio_is_inbound_q_done(struct qdio_q *q) |
903 | { | 1162 | { |
904 | int no_used; | 1163 | int no_used; |
1164 | unsigned int start_buf, count; | ||
1165 | unsigned char state = 0; | ||
1166 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | ||
1167 | |||
905 | #ifdef CONFIG_QDIO_DEBUG | 1168 | #ifdef CONFIG_QDIO_DEBUG |
906 | char dbf_text[15]; | 1169 | char dbf_text[15]; |
907 | #endif | 1170 | #endif |
@@ -927,8 +1190,13 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) | |||
927 | if (!q->siga_sync) | 1190 | if (!q->siga_sync) |
928 | /* we'll check for more primed buffers in qeth_stop_polling */ | 1191 | /* we'll check for more primed buffers in qeth_stop_polling */ |
929 | return 0; | 1192 | return 0; |
930 | 1193 | if (irq->is_qebsm) { | |
931 | if (q->slsb.acc.val[q->first_to_check]!=SLSB_P_INPUT_PRIMED) | 1194 | count = 1; |
1195 | start_buf = q->first_to_check; | ||
1196 | qdio_do_eqbs(q, &state, &start_buf, &count); | ||
1197 | } else | ||
1198 | state = q->slsb.acc.val[q->first_to_check]; | ||
1199 | if (state != SLSB_P_INPUT_PRIMED) | ||
932 | /* | 1200 | /* |
933 | * nothing more to do, if next buffer is not PRIMED. | 1201 | * nothing more to do, if next buffer is not PRIMED. |
934 | * note that we did a SYNC_MEMORY before, that there | 1202 | * note that we did a SYNC_MEMORY before, that there |
@@ -955,6 +1223,10 @@ static inline int | |||
955 | qdio_is_inbound_q_done(struct qdio_q *q) | 1223 | qdio_is_inbound_q_done(struct qdio_q *q) |
956 | { | 1224 | { |
957 | int no_used; | 1225 | int no_used; |
1226 | unsigned int start_buf, count; | ||
1227 | unsigned char state = 0; | ||
1228 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | ||
1229 | |||
958 | #ifdef CONFIG_QDIO_DEBUG | 1230 | #ifdef CONFIG_QDIO_DEBUG |
959 | char dbf_text[15]; | 1231 | char dbf_text[15]; |
960 | #endif | 1232 | #endif |
@@ -973,8 +1245,13 @@ qdio_is_inbound_q_done(struct qdio_q *q) | |||
973 | QDIO_DBF_TEXT4(0,trace,dbf_text); | 1245 | QDIO_DBF_TEXT4(0,trace,dbf_text); |
974 | return 1; | 1246 | return 1; |
975 | } | 1247 | } |
976 | 1248 | if (irq->is_qebsm) { | |
977 | if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) { | 1249 | count = 1; |
1250 | start_buf = q->first_to_check; | ||
1251 | qdio_do_eqbs(q, &state, &start_buf, &count); | ||
1252 | } else | ||
1253 | state = q->slsb.acc.val[q->first_to_check]; | ||
1254 | if (state == SLSB_P_INPUT_PRIMED) { | ||
978 | /* we got something to do */ | 1255 | /* we got something to do */ |
979 | QDIO_DBF_TEXT4(0,trace,"inqisntA"); | 1256 | QDIO_DBF_TEXT4(0,trace,"inqisntA"); |
980 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 1257 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
@@ -1523,11 +1800,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, | |||
1523 | QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*)); | 1800 | QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*)); |
1524 | 1801 | ||
1525 | /* fill in slsb */ | 1802 | /* fill in slsb */ |
1526 | for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) { | 1803 | if (!irq_ptr->is_qebsm) { |
1527 | set_slsb(&q->slsb.acc.val[j], | 1804 | unsigned int count = 1; |
1528 | SLSB_P_INPUT_NOT_INIT); | 1805 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) |
1529 | /* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/ | 1806 | set_slsb(q, &j, SLSB_P_INPUT_NOT_INIT, &count); |
1530 | } | 1807 | } |
1531 | } | 1808 | } |
1532 | 1809 | ||
1533 | for (i=0;i<no_output_qs;i++) { | 1810 | for (i=0;i<no_output_qs;i++) { |
@@ -1584,11 +1861,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, | |||
1584 | QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*)); | 1861 | QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*)); |
1585 | 1862 | ||
1586 | /* fill in slsb */ | 1863 | /* fill in slsb */ |
1587 | for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) { | 1864 | if (!irq_ptr->is_qebsm) { |
1588 | set_slsb(&q->slsb.acc.val[j], | 1865 | unsigned int count = 1; |
1589 | SLSB_P_OUTPUT_NOT_INIT); | 1866 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) |
1590 | /* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/ | 1867 | set_slsb(q, &j, SLSB_P_OUTPUT_NOT_INIT, &count); |
1591 | } | 1868 | } |
1592 | } | 1869 | } |
1593 | } | 1870 | } |
1594 | 1871 | ||
@@ -1905,7 +2182,7 @@ int | |||
1905 | qdio_synchronize(struct ccw_device *cdev, unsigned int flags, | 2182 | qdio_synchronize(struct ccw_device *cdev, unsigned int flags, |
1906 | unsigned int queue_number) | 2183 | unsigned int queue_number) |
1907 | { | 2184 | { |
1908 | int cc; | 2185 | int cc = 0; |
1909 | struct qdio_q *q; | 2186 | struct qdio_q *q; |
1910 | struct qdio_irq *irq_ptr; | 2187 | struct qdio_irq *irq_ptr; |
1911 | void *ptr; | 2188 | void *ptr; |
@@ -1929,12 +2206,14 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, | |||
1929 | q=irq_ptr->input_qs[queue_number]; | 2206 | q=irq_ptr->input_qs[queue_number]; |
1930 | if (!q) | 2207 | if (!q) |
1931 | return -EINVAL; | 2208 | return -EINVAL; |
1932 | cc = do_siga_sync(q->irq, 0, q->mask); | 2209 | if (!(irq_ptr->is_qebsm)) |
2210 | cc = do_siga_sync(0x10000|q->irq, 0, q->mask); | ||
1933 | } else if (flags&QDIO_FLAG_SYNC_OUTPUT) { | 2211 | } else if (flags&QDIO_FLAG_SYNC_OUTPUT) { |
1934 | q=irq_ptr->output_qs[queue_number]; | 2212 | q=irq_ptr->output_qs[queue_number]; |
1935 | if (!q) | 2213 | if (!q) |
1936 | return -EINVAL; | 2214 | return -EINVAL; |
1937 | cc = do_siga_sync(q->irq, q->mask, 0); | 2215 | if (!(irq_ptr->is_qebsm)) |
2216 | cc = do_siga_sync(0x10000|q->irq, q->mask, 0); | ||
1938 | } else | 2217 | } else |
1939 | return -EINVAL; | 2218 | return -EINVAL; |
1940 | 2219 | ||
@@ -1945,12 +2224,49 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, | |||
1945 | return cc; | 2224 | return cc; |
1946 | } | 2225 | } |
1947 | 2226 | ||
1948 | static unsigned char | 2227 | static inline void |
1949 | qdio_check_siga_needs(int sch) | 2228 | qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac, |
2229 | unsigned long token) | ||
2230 | { | ||
2231 | struct qdio_q *q; | ||
2232 | int i; | ||
2233 | unsigned int count, start_buf; | ||
2234 | char dbf_text[15]; | ||
2235 | |||
2236 | /*check if QEBSM is disabled */ | ||
2237 | if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) { | ||
2238 | irq_ptr->is_qebsm = 0; | ||
2239 | irq_ptr->sch_token = 0; | ||
2240 | irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM; | ||
2241 | QDIO_DBF_TEXT0(0,setup,"noV=V"); | ||
2242 | return; | ||
2243 | } | ||
2244 | irq_ptr->sch_token = token; | ||
2245 | /*input queue*/ | ||
2246 | for (i = 0; i < irq_ptr->no_input_qs;i++) { | ||
2247 | q = irq_ptr->input_qs[i]; | ||
2248 | count = QDIO_MAX_BUFFERS_PER_Q; | ||
2249 | start_buf = 0; | ||
2250 | set_slsb(q, &start_buf, SLSB_P_INPUT_NOT_INIT, &count); | ||
2251 | } | ||
2252 | sprintf(dbf_text,"V=V:%2x",irq_ptr->is_qebsm); | ||
2253 | QDIO_DBF_TEXT0(0,setup,dbf_text); | ||
2254 | sprintf(dbf_text,"%8lx",irq_ptr->sch_token); | ||
2255 | QDIO_DBF_TEXT0(0,setup,dbf_text); | ||
2256 | /*output queue*/ | ||
2257 | for (i = 0; i < irq_ptr->no_output_qs; i++) { | ||
2258 | q = irq_ptr->output_qs[i]; | ||
2259 | count = QDIO_MAX_BUFFERS_PER_Q; | ||
2260 | start_buf = 0; | ||
2261 | set_slsb(q, &start_buf, SLSB_P_OUTPUT_NOT_INIT, &count); | ||
2262 | } | ||
2263 | } | ||
2264 | |||
2265 | static void | ||
2266 | qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | ||
1950 | { | 2267 | { |
1951 | int result; | 2268 | int result; |
1952 | unsigned char qdioac; | 2269 | unsigned char qdioac; |
1953 | |||
1954 | struct { | 2270 | struct { |
1955 | struct chsc_header request; | 2271 | struct chsc_header request; |
1956 | u16 reserved1; | 2272 | u16 reserved1; |
@@ -1964,67 +2280,80 @@ qdio_check_siga_needs(int sch) | |||
1964 | u8 reserved5; | 2280 | u8 reserved5; |
1965 | u16 sch; | 2281 | u16 sch; |
1966 | u8 qfmt; | 2282 | u8 qfmt; |
1967 | u8 reserved6; | 2283 | u8 parm; |
1968 | u8 qdioac; | 2284 | u8 qdioac1; |
1969 | u8 sch_class; | 2285 | u8 sch_class; |
1970 | u8 reserved7; | 2286 | u8 reserved7; |
1971 | u8 icnt; | 2287 | u8 icnt; |
1972 | u8 reserved8; | 2288 | u8 reserved8; |
1973 | u8 ocnt; | 2289 | u8 ocnt; |
2290 | u8 reserved9; | ||
2291 | u8 mbccnt; | ||
2292 | u16 qdioac2; | ||
2293 | u64 sch_token; | ||
1974 | } *ssqd_area; | 2294 | } *ssqd_area; |
1975 | 2295 | ||
2296 | QDIO_DBF_TEXT0(0,setup,"getssqd"); | ||
2297 | qdioac = 0; | ||
1976 | ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 2298 | ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
1977 | if (!ssqd_area) { | 2299 | if (!ssqd_area) { |
1978 | QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ | 2300 | QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ |
1979 | "SIGAs for sch x%x.\n", sch); | 2301 | "SIGAs for sch x%x.\n", irq_ptr->irq); |
1980 | return CHSC_FLAG_SIGA_INPUT_NECESSARY || | 2302 | irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || |
1981 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || | 2303 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || |
1982 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ | 2304 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ |
2305 | irq_ptr->is_qebsm = 0; | ||
2306 | irq_ptr->sch_token = 0; | ||
2307 | irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM; | ||
2308 | return; | ||
1983 | } | 2309 | } |
2310 | |||
1984 | ssqd_area->request = (struct chsc_header) { | 2311 | ssqd_area->request = (struct chsc_header) { |
1985 | .length = 0x0010, | 2312 | .length = 0x0010, |
1986 | .code = 0x0024, | 2313 | .code = 0x0024, |
1987 | }; | 2314 | }; |
1988 | 2315 | ssqd_area->first_sch = irq_ptr->irq; | |
1989 | ssqd_area->first_sch = sch; | 2316 | ssqd_area->last_sch = irq_ptr->irq; |
1990 | ssqd_area->last_sch = sch; | 2317 | result = chsc(ssqd_area); |
1991 | |||
1992 | result=chsc(ssqd_area); | ||
1993 | 2318 | ||
1994 | if (result) { | 2319 | if (result) { |
1995 | QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ | 2320 | QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ |
1996 | "SIGAs for sch x%x.\n", | 2321 | "SIGAs for sch x%x.\n", |
1997 | result,sch); | 2322 | result, irq_ptr->irq); |
1998 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || | 2323 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || |
1999 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || | 2324 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || |
2000 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ | 2325 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ |
2326 | irq_ptr->is_qebsm = 0; | ||
2001 | goto out; | 2327 | goto out; |
2002 | } | 2328 | } |
2003 | 2329 | ||
2004 | if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { | 2330 | if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { |
2005 | QDIO_PRINT_WARN("response upon checking SIGA needs " \ | 2331 | QDIO_PRINT_WARN("response upon checking SIGA needs " \ |
2006 | "is 0x%x. Using all SIGAs for sch x%x.\n", | 2332 | "is 0x%x. Using all SIGAs for sch x%x.\n", |
2007 | ssqd_area->response.code, sch); | 2333 | ssqd_area->response.code, irq_ptr->irq); |
2008 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || | 2334 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || |
2009 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || | 2335 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || |
2010 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ | 2336 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ |
2337 | irq_ptr->is_qebsm = 0; | ||
2011 | goto out; | 2338 | goto out; |
2012 | } | 2339 | } |
2013 | if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || | 2340 | if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || |
2014 | !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || | 2341 | !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || |
2015 | (ssqd_area->sch != sch)) { | 2342 | (ssqd_area->sch != irq_ptr->irq)) { |
2016 | QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ | 2343 | QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ |
2017 | "using all SIGAs.\n",sch); | 2344 | "using all SIGAs.\n",irq_ptr->irq); |
2018 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | | 2345 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | |
2019 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY | | 2346 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY | |
2020 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ | 2347 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ |
2348 | irq_ptr->is_qebsm = 0; | ||
2021 | goto out; | 2349 | goto out; |
2022 | } | 2350 | } |
2023 | 2351 | qdioac = ssqd_area->qdioac1; | |
2024 | qdioac = ssqd_area->qdioac; | ||
2025 | out: | 2352 | out: |
2353 | qdio_check_subchannel_qebsm(irq_ptr, qdioac, | ||
2354 | ssqd_area->sch_token); | ||
2026 | free_page ((unsigned long) ssqd_area); | 2355 | free_page ((unsigned long) ssqd_area); |
2027 | return qdioac; | 2356 | irq_ptr->qdioac = qdioac; |
2028 | } | 2357 | } |
2029 | 2358 | ||
2030 | static unsigned int | 2359 | static unsigned int |
@@ -2055,6 +2384,13 @@ tiqdio_check_chsc_availability(void) | |||
2055 | sprintf(dbf_text,"hydrati%1x", hydra_thinints); | 2384 | sprintf(dbf_text,"hydrati%1x", hydra_thinints); |
2056 | QDIO_DBF_TEXT0(0,setup,dbf_text); | 2385 | QDIO_DBF_TEXT0(0,setup,dbf_text); |
2057 | 2386 | ||
2387 | #ifdef CONFIG_ARCH_S390X | ||
2388 | /* Check for QEBSM support in general (bit 58). */ | ||
2389 | is_passthrough = css_general_characteristics.qebsm; | ||
2390 | #endif | ||
2391 | sprintf(dbf_text,"cssQBS:%1x", is_passthrough); | ||
2392 | QDIO_DBF_TEXT0(0,setup,dbf_text); | ||
2393 | |||
2058 | /* Check for aif time delay disablement fac (bit 56). If installed, | 2394 | /* Check for aif time delay disablement fac (bit 56). If installed, |
2059 | * omit svs even under lpar (good point by rick again) */ | 2395 | * omit svs even under lpar (good point by rick again) */ |
2060 | omit_svs = css_general_characteristics.aif_tdd; | 2396 | omit_svs = css_general_characteristics.aif_tdd; |
@@ -2698,7 +3034,7 @@ int qdio_fill_irq(struct qdio_initialize *init_data) | |||
2698 | QDIO_DBF_TEXT2(0,setup,dbf_text); | 3034 | QDIO_DBF_TEXT2(0,setup,dbf_text); |
2699 | 3035 | ||
2700 | if (irq_ptr->is_thinint_irq) { | 3036 | if (irq_ptr->is_thinint_irq) { |
2701 | irq_ptr->dev_st_chg_ind=qdio_get_indicator(); | 3037 | irq_ptr->dev_st_chg_ind = qdio_get_indicator(); |
2702 | QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); | 3038 | QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); |
2703 | if (!irq_ptr->dev_st_chg_ind) { | 3039 | if (!irq_ptr->dev_st_chg_ind) { |
2704 | QDIO_PRINT_WARN("no indicator location available " \ | 3040 | QDIO_PRINT_WARN("no indicator location available " \ |
@@ -2747,6 +3083,10 @@ int qdio_fill_irq(struct qdio_initialize *init_data) | |||
2747 | irq_ptr->qdr->qkey=QDIO_STORAGE_KEY; | 3083 | irq_ptr->qdr->qkey=QDIO_STORAGE_KEY; |
2748 | 3084 | ||
2749 | /* fill in qib */ | 3085 | /* fill in qib */ |
3086 | irq_ptr->is_qebsm = is_passthrough; | ||
3087 | if (irq_ptr->is_qebsm) | ||
3088 | irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM; | ||
3089 | |||
2750 | irq_ptr->qib.qfmt=init_data->q_format; | 3090 | irq_ptr->qib.qfmt=init_data->q_format; |
2751 | if (init_data->no_input_qs) | 3091 | if (init_data->no_input_qs) |
2752 | irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib); | 3092 | irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib); |
@@ -2884,7 +3224,7 @@ qdio_establish(struct qdio_initialize *init_data) | |||
2884 | return -EIO; | 3224 | return -EIO; |
2885 | } | 3225 | } |
2886 | 3226 | ||
2887 | irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq); | 3227 | qdio_get_ssqd_information(irq_ptr); |
2888 | /* if this gets set once, we're running under VM and can omit SVSes */ | 3228 | /* if this gets set once, we're running under VM and can omit SVSes */ |
2889 | if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) | 3229 | if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) |
2890 | omit_svs=1; | 3230 | omit_svs=1; |
@@ -3015,30 +3355,40 @@ static inline void | |||
3015 | qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, | 3355 | qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, |
3016 | unsigned int count, struct qdio_buffer *buffers) | 3356 | unsigned int count, struct qdio_buffer *buffers) |
3017 | { | 3357 | { |
3358 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | ||
3359 | qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); | ||
3360 | if (irq->is_qebsm) { | ||
3361 | while (count) | ||
3362 | set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); | ||
3363 | return; | ||
3364 | } | ||
3018 | for (;;) { | 3365 | for (;;) { |
3019 | set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_INPUT_EMPTY); | 3366 | set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); |
3020 | count--; | 3367 | count--; |
3021 | if (!count) break; | 3368 | if (!count) break; |
3022 | qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1); | 3369 | qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1); |
3023 | } | 3370 | } |
3024 | |||
3025 | /* not necessary, as the queues are synced during the SIGA read */ | ||
3026 | /*SYNC_MEMORY;*/ | ||
3027 | } | 3371 | } |
3028 | 3372 | ||
3029 | static inline void | 3373 | static inline void |
3030 | qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, | 3374 | qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, |
3031 | unsigned int count, struct qdio_buffer *buffers) | 3375 | unsigned int count, struct qdio_buffer *buffers) |
3032 | { | 3376 | { |
3377 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | ||
3378 | |||
3379 | qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); | ||
3380 | if (irq->is_qebsm) { | ||
3381 | while (count) | ||
3382 | set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); | ||
3383 | return; | ||
3384 | } | ||
3385 | |||
3033 | for (;;) { | 3386 | for (;;) { |
3034 | set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_OUTPUT_PRIMED); | 3387 | set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); |
3035 | count--; | 3388 | count--; |
3036 | if (!count) break; | 3389 | if (!count) break; |
3037 | qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1); | 3390 | qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1); |
3038 | } | 3391 | } |
3039 | |||
3040 | /* SIGA write will sync the queues */ | ||
3041 | /*SYNC_MEMORY;*/ | ||
3042 | } | 3392 | } |
3043 | 3393 | ||
3044 | static inline void | 3394 | static inline void |
@@ -3083,6 +3433,9 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
3083 | struct qdio_buffer *buffers) | 3433 | struct qdio_buffer *buffers) |
3084 | { | 3434 | { |
3085 | int used_elements; | 3435 | int used_elements; |
3436 | unsigned int cnt, start_buf; | ||
3437 | unsigned char state = 0; | ||
3438 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | ||
3086 | 3439 | ||
3087 | /* This is the outbound handling of queues */ | 3440 | /* This is the outbound handling of queues */ |
3088 | #ifdef QDIO_PERFORMANCE_STATS | 3441 | #ifdef QDIO_PERFORMANCE_STATS |
@@ -3115,9 +3468,15 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
3115 | * SYNC_MEMORY :-/ ), we try to | 3468 | * SYNC_MEMORY :-/ ), we try to |
3116 | * fast-requeue buffers | 3469 | * fast-requeue buffers |
3117 | */ | 3470 | */ |
3118 | if (q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1) | 3471 | if (irq->is_qebsm) { |
3119 | &(QDIO_MAX_BUFFERS_PER_Q-1)]!= | 3472 | cnt = 1; |
3120 | SLSB_CU_OUTPUT_PRIMED) { | 3473 | start_buf = ((qidx+QDIO_MAX_BUFFERS_PER_Q-1) & |
3474 | (QDIO_MAX_BUFFERS_PER_Q-1)); | ||
3475 | qdio_do_eqbs(q, &state, &start_buf, &cnt); | ||
3476 | } else | ||
3477 | state = q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1) | ||
3478 | &(QDIO_MAX_BUFFERS_PER_Q-1) ]; | ||
3479 | if (state != SLSB_CU_OUTPUT_PRIMED) { | ||
3121 | qdio_kick_outbound_q(q); | 3480 | qdio_kick_outbound_q(q); |
3122 | } else { | 3481 | } else { |
3123 | QDIO_DBF_TEXT3(0,trace, "fast-req"); | 3482 | QDIO_DBF_TEXT3(0,trace, "fast-req"); |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 328e31cc6854..b5d303e79a24 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -3,14 +3,13 @@ | |||
3 | 3 | ||
4 | #include <asm/page.h> | 4 | #include <asm/page.h> |
5 | 5 | ||
6 | #define VERSION_CIO_QDIO_H "$Revision: 1.33 $" | 6 | #define VERSION_CIO_QDIO_H "$Revision: 1.37 $" |
7 | 7 | ||
8 | #ifdef CONFIG_QDIO_DEBUG | 8 | #ifdef CONFIG_QDIO_DEBUG |
9 | #define QDIO_VERBOSE_LEVEL 9 | 9 | #define QDIO_VERBOSE_LEVEL 9 |
10 | #else /* CONFIG_QDIO_DEBUG */ | 10 | #else /* CONFIG_QDIO_DEBUG */ |
11 | #define QDIO_VERBOSE_LEVEL 5 | 11 | #define QDIO_VERBOSE_LEVEL 5 |
12 | #endif /* CONFIG_QDIO_DEBUG */ | 12 | #endif /* CONFIG_QDIO_DEBUG */ |
13 | |||
14 | #define QDIO_USE_PROCESSING_STATE | 13 | #define QDIO_USE_PROCESSING_STATE |
15 | 14 | ||
16 | #ifdef CONFIG_QDIO_PERF_STATS | 15 | #ifdef CONFIG_QDIO_PERF_STATS |
@@ -265,6 +264,58 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ | |||
265 | /* | 264 | /* |
266 | * Some instructions as assembly | 265 | * Some instructions as assembly |
267 | */ | 266 | */ |
267 | |||
268 | static inline int | ||
269 | do_sqbs(unsigned long sch, unsigned char state, int queue, | ||
270 | unsigned int *start, unsigned int *count) | ||
271 | { | ||
272 | #ifdef CONFIG_ARCH_S390X | ||
273 | register unsigned long _ccq asm ("0") = *count; | ||
274 | register unsigned long _sch asm ("1") = sch; | ||
275 | unsigned long _queuestart = ((unsigned long)queue << 32) | *start; | ||
276 | |||
277 | asm volatile ( | ||
278 | " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t" | ||
279 | : "+d" (_ccq), "+d" (_queuestart) | ||
280 | : "d" ((unsigned long)state), "d" (_sch) | ||
281 | : "memory", "cc" | ||
282 | ); | ||
283 | *count = _ccq & 0xff; | ||
284 | *start = _queuestart & 0xff; | ||
285 | |||
286 | return (_ccq >> 32) & 0xff; | ||
287 | #else | ||
288 | return 0; | ||
289 | #endif | ||
290 | } | ||
291 | |||
292 | static inline int | ||
293 | do_eqbs(unsigned long sch, unsigned char *state, int queue, | ||
294 | unsigned int *start, unsigned int *count) | ||
295 | { | ||
296 | #ifdef CONFIG_ARCH_S390X | ||
297 | register unsigned long _ccq asm ("0") = *count; | ||
298 | register unsigned long _sch asm ("1") = sch; | ||
299 | unsigned long _queuestart = ((unsigned long)queue << 32) | *start; | ||
300 | unsigned long _state = 0; | ||
301 | |||
302 | asm volatile ( | ||
303 | " .insn rrf,0xB99c0000,%1,%2,0,0 \n\t" | ||
304 | : "+d" (_ccq), "+d" (_queuestart), "+d" (_state) | ||
305 | : "d" (_sch) | ||
306 | : "memory", "cc" | ||
307 | ); | ||
308 | *count = _ccq & 0xff; | ||
309 | *start = _queuestart & 0xff; | ||
310 | *state = _state & 0xff; | ||
311 | |||
312 | return (_ccq >> 32) & 0xff; | ||
313 | #else | ||
314 | return 0; | ||
315 | #endif | ||
316 | } | ||
317 | |||
318 | |||
268 | static inline int | 319 | static inline int |
269 | do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) | 320 | do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) |
270 | { | 321 | { |
@@ -280,7 +331,7 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) | |||
280 | "ipm %0 \n\t" | 331 | "ipm %0 \n\t" |
281 | "srl %0,28 \n\t" | 332 | "srl %0,28 \n\t" |
282 | : "=d" (cc) | 333 | : "=d" (cc) |
283 | : "d" (0x10000|irq), "d" (mask1), "d" (mask2) | 334 | : "d" (irq), "d" (mask1), "d" (mask2) |
284 | : "cc", "0", "1", "2", "3" | 335 | : "cc", "0", "1", "2", "3" |
285 | ); | 336 | ); |
286 | #else /* CONFIG_ARCH_S390X */ | 337 | #else /* CONFIG_ARCH_S390X */ |
@@ -293,7 +344,7 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) | |||
293 | "ipm %0 \n\t" | 344 | "ipm %0 \n\t" |
294 | "srl %0,28 \n\t" | 345 | "srl %0,28 \n\t" |
295 | : "=d" (cc) | 346 | : "=d" (cc) |
296 | : "d" (0x10000|irq), "d" (mask1), "d" (mask2) | 347 | : "d" (irq), "d" (mask1), "d" (mask2) |
297 | : "cc", "0", "1", "2", "3" | 348 | : "cc", "0", "1", "2", "3" |
298 | ); | 349 | ); |
299 | #endif /* CONFIG_ARCH_S390X */ | 350 | #endif /* CONFIG_ARCH_S390X */ |
@@ -314,7 +365,7 @@ do_siga_input(unsigned int irq, unsigned int mask) | |||
314 | "ipm %0 \n\t" | 365 | "ipm %0 \n\t" |
315 | "srl %0,28 \n\t" | 366 | "srl %0,28 \n\t" |
316 | : "=d" (cc) | 367 | : "=d" (cc) |
317 | : "d" (0x10000|irq), "d" (mask) | 368 | : "d" (irq), "d" (mask) |
318 | : "cc", "0", "1", "2", "memory" | 369 | : "cc", "0", "1", "2", "memory" |
319 | ); | 370 | ); |
320 | #else /* CONFIG_ARCH_S390X */ | 371 | #else /* CONFIG_ARCH_S390X */ |
@@ -326,7 +377,7 @@ do_siga_input(unsigned int irq, unsigned int mask) | |||
326 | "ipm %0 \n\t" | 377 | "ipm %0 \n\t" |
327 | "srl %0,28 \n\t" | 378 | "srl %0,28 \n\t" |
328 | : "=d" (cc) | 379 | : "=d" (cc) |
329 | : "d" (0x10000|irq), "d" (mask) | 380 | : "d" (irq), "d" (mask) |
330 | : "cc", "0", "1", "2", "memory" | 381 | : "cc", "0", "1", "2", "memory" |
331 | ); | 382 | ); |
332 | #endif /* CONFIG_ARCH_S390X */ | 383 | #endif /* CONFIG_ARCH_S390X */ |
@@ -335,7 +386,8 @@ do_siga_input(unsigned int irq, unsigned int mask) | |||
335 | } | 386 | } |
336 | 387 | ||
337 | static inline int | 388 | static inline int |
338 | do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) | 389 | do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb, |
390 | unsigned int fc) | ||
339 | { | 391 | { |
340 | int cc; | 392 | int cc; |
341 | __u32 busy_bit; | 393 | __u32 busy_bit; |
@@ -366,14 +418,14 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) | |||
366 | ".long 0b,2b \n\t" | 418 | ".long 0b,2b \n\t" |
367 | ".previous \n\t" | 419 | ".previous \n\t" |
368 | : "=d" (cc), "=d" (busy_bit) | 420 | : "=d" (cc), "=d" (busy_bit) |
369 | : "d" (0x10000|irq), "d" (mask), | 421 | : "d" (irq), "d" (mask), |
370 | "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION) | 422 | "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION) |
371 | : "cc", "0", "1", "2", "memory" | 423 | : "cc", "0", "1", "2", "memory" |
372 | ); | 424 | ); |
373 | #else /* CONFIG_ARCH_S390X */ | 425 | #else /* CONFIG_ARCH_S390X */ |
374 | asm volatile ( | 426 | asm volatile ( |
375 | "lghi 0,0 \n\t" | 427 | "llgfr 0,%5 \n\t" |
376 | "llgfr 1,%2 \n\t" | 428 | "lgr 1,%2 \n\t" |
377 | "llgfr 2,%3 \n\t" | 429 | "llgfr 2,%3 \n\t" |
378 | "siga 0 \n\t" | 430 | "siga 0 \n\t" |
379 | "0:" | 431 | "0:" |
@@ -391,8 +443,8 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) | |||
391 | ".quad 0b,1b \n\t" | 443 | ".quad 0b,1b \n\t" |
392 | ".previous \n\t" | 444 | ".previous \n\t" |
393 | : "=d" (cc), "=d" (busy_bit) | 445 | : "=d" (cc), "=d" (busy_bit) |
394 | : "d" (0x10000|irq), "d" (mask), | 446 | : "d" (irq), "d" (mask), |
395 | "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION) | 447 | "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc) |
396 | : "cc", "0", "1", "2", "memory" | 448 | : "cc", "0", "1", "2", "memory" |
397 | ); | 449 | ); |
398 | #endif /* CONFIG_ARCH_S390X */ | 450 | #endif /* CONFIG_ARCH_S390X */ |
@@ -494,33 +546,12 @@ struct qdio_perf_stats { | |||
494 | #define QDIO_GET_ADDR(x) ((__u32)(long)x) | 546 | #define QDIO_GET_ADDR(x) ((__u32)(long)x) |
495 | #endif /* CONFIG_ARCH_S390X */ | 547 | #endif /* CONFIG_ARCH_S390X */ |
496 | 548 | ||
497 | #ifdef CONFIG_QDIO_DEBUG | ||
498 | #define set_slsb(x,y) \ | ||
499 | if(q->queue_type==QDIO_TRACE_QTYPE) { \ | ||
500 | if(q->is_input_q) { \ | ||
501 | QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ | ||
502 | } else { \ | ||
503 | QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ | ||
504 | } \ | ||
505 | } \ | ||
506 | qdio_set_slsb(x,y); \ | ||
507 | if(q->queue_type==QDIO_TRACE_QTYPE) { \ | ||
508 | if(q->is_input_q) { \ | ||
509 | QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ | ||
510 | } else { \ | ||
511 | QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ | ||
512 | } \ | ||
513 | } | ||
514 | #else /* CONFIG_QDIO_DEBUG */ | ||
515 | #define set_slsb(x,y) qdio_set_slsb(x,y) | ||
516 | #endif /* CONFIG_QDIO_DEBUG */ | ||
517 | |||
518 | struct qdio_q { | 549 | struct qdio_q { |
519 | volatile struct slsb slsb; | 550 | volatile struct slsb slsb; |
520 | 551 | ||
521 | char unused[QDIO_MAX_BUFFERS_PER_Q]; | 552 | char unused[QDIO_MAX_BUFFERS_PER_Q]; |
522 | 553 | ||
523 | __u32 * volatile dev_st_chg_ind; | 554 | __u32 * dev_st_chg_ind; |
524 | 555 | ||
525 | int is_input_q; | 556 | int is_input_q; |
526 | int irq; | 557 | int irq; |
@@ -568,6 +599,7 @@ struct qdio_q { | |||
568 | struct tasklet_struct tasklet; | 599 | struct tasklet_struct tasklet; |
569 | #endif /* QDIO_USE_TIMERS_FOR_POLLING */ | 600 | #endif /* QDIO_USE_TIMERS_FOR_POLLING */ |
570 | 601 | ||
602 | |||
571 | enum qdio_irq_states state; | 603 | enum qdio_irq_states state; |
572 | 604 | ||
573 | /* used to store the error condition during a data transfer */ | 605 | /* used to store the error condition during a data transfer */ |
@@ -624,6 +656,10 @@ struct qdio_irq { | |||
624 | unsigned int hydra_gives_outbound_pcis; | 656 | unsigned int hydra_gives_outbound_pcis; |
625 | unsigned int sync_done_on_outb_pcis; | 657 | unsigned int sync_done_on_outb_pcis; |
626 | 658 | ||
659 | /* QEBSM facility */ | ||
660 | unsigned int is_qebsm; | ||
661 | unsigned long sch_token; | ||
662 | |||
627 | enum qdio_irq_states state; | 663 | enum qdio_irq_states state; |
628 | 664 | ||
629 | unsigned int no_input_qs; | 665 | unsigned int no_input_qs; |
diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h index 0ddf0a8ef8de..7bc15f0231db 100644 --- a/include/asm-s390/qdio.h +++ b/include/asm-s390/qdio.h | |||
@@ -195,12 +195,14 @@ struct qdr { | |||
195 | /* | 195 | /* |
196 | * queue information block (QIB) | 196 | * queue information block (QIB) |
197 | */ | 197 | */ |
198 | #define QIB_AC_INBOUND_PCI_SUPPORTED 0x80 | 198 | #define QIB_AC_INBOUND_PCI_SUPPORTED 0x80 |
199 | #define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40 | 199 | #define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40 |
200 | #define QIB_RFLAGS_ENABLE_QEBSM 0x80 | ||
201 | |||
200 | struct qib { | 202 | struct qib { |
201 | unsigned int qfmt : 8; /* queue format */ | 203 | unsigned int qfmt : 8; /* queue format */ |
202 | unsigned int pfmt : 8; /* impl. dep. parameter format */ | 204 | unsigned int pfmt : 8; /* impl. dep. parameter format */ |
203 | unsigned int res1 : 8; /* reserved */ | 205 | unsigned int rflags : 8; /* QEBSM */ |
204 | unsigned int ac : 8; /* adapter characteristics */ | 206 | unsigned int ac : 8; /* adapter characteristics */ |
205 | unsigned int res2; /* reserved */ | 207 | unsigned int res2; /* reserved */ |
206 | #ifdef QDIO_32_BIT | 208 | #ifdef QDIO_32_BIT |