diff options
Diffstat (limited to 'drivers/s390/cio/qdio_main.c')
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 351 |
1 files changed, 242 insertions, 109 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 00520f9a7a8e..570d4da10696 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
17 | #include <linux/kernel_stat.h> | ||
17 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
18 | #include <asm/debug.h> | 19 | #include <asm/debug.h> |
19 | #include <asm/qdio.h> | 20 | #include <asm/qdio.h> |
@@ -29,11 +30,12 @@ MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>,"\ | |||
29 | MODULE_DESCRIPTION("QDIO base support"); | 30 | MODULE_DESCRIPTION("QDIO base support"); |
30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
31 | 32 | ||
32 | static inline int do_siga_sync(struct subchannel_id schid, | 33 | static inline int do_siga_sync(unsigned long schid, |
33 | unsigned int out_mask, unsigned int in_mask) | 34 | unsigned int out_mask, unsigned int in_mask, |
35 | unsigned int fc) | ||
34 | { | 36 | { |
35 | register unsigned long __fc asm ("0") = 2; | 37 | register unsigned long __fc asm ("0") = fc; |
36 | register struct subchannel_id __schid asm ("1") = schid; | 38 | register unsigned long __schid asm ("1") = schid; |
37 | register unsigned long out asm ("2") = out_mask; | 39 | register unsigned long out asm ("2") = out_mask; |
38 | register unsigned long in asm ("3") = in_mask; | 40 | register unsigned long in asm ("3") = in_mask; |
39 | int cc; | 41 | int cc; |
@@ -47,10 +49,11 @@ static inline int do_siga_sync(struct subchannel_id schid, | |||
47 | return cc; | 49 | return cc; |
48 | } | 50 | } |
49 | 51 | ||
50 | static inline int do_siga_input(struct subchannel_id schid, unsigned int mask) | 52 | static inline int do_siga_input(unsigned long schid, unsigned int mask, |
53 | unsigned int fc) | ||
51 | { | 54 | { |
52 | register unsigned long __fc asm ("0") = 1; | 55 | register unsigned long __fc asm ("0") = fc; |
53 | register struct subchannel_id __schid asm ("1") = schid; | 56 | register unsigned long __schid asm ("1") = schid; |
54 | register unsigned long __mask asm ("2") = mask; | 57 | register unsigned long __mask asm ("2") = mask; |
55 | int cc; | 58 | int cc; |
56 | 59 | ||
@@ -279,16 +282,20 @@ void qdio_init_buf_states(struct qdio_irq *irq_ptr) | |||
279 | static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output, | 282 | static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output, |
280 | unsigned int input) | 283 | unsigned int input) |
281 | { | 284 | { |
285 | unsigned long schid = *((u32 *) &q->irq_ptr->schid); | ||
286 | unsigned int fc = QDIO_SIGA_SYNC; | ||
282 | int cc; | 287 | int cc; |
283 | 288 | ||
284 | if (!need_siga_sync(q)) | ||
285 | return 0; | ||
286 | |||
287 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr); | 289 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr); |
288 | qperf_inc(q, siga_sync); | 290 | qperf_inc(q, siga_sync); |
289 | 291 | ||
290 | cc = do_siga_sync(q->irq_ptr->schid, output, input); | 292 | if (is_qebsm(q)) { |
291 | if (cc) | 293 | schid = q->irq_ptr->sch_token; |
294 | fc |= QDIO_SIGA_QEBSM_FLAG; | ||
295 | } | ||
296 | |||
297 | cc = do_siga_sync(schid, output, input, fc); | ||
298 | if (unlikely(cc)) | ||
292 | DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc); | 299 | DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc); |
293 | return cc; | 300 | return cc; |
294 | } | 301 | } |
@@ -301,38 +308,22 @@ static inline int qdio_siga_sync_q(struct qdio_q *q) | |||
301 | return qdio_siga_sync(q, q->mask, 0); | 308 | return qdio_siga_sync(q, q->mask, 0); |
302 | } | 309 | } |
303 | 310 | ||
304 | static inline int qdio_siga_sync_out(struct qdio_q *q) | ||
305 | { | ||
306 | return qdio_siga_sync(q, ~0U, 0); | ||
307 | } | ||
308 | |||
309 | static inline int qdio_siga_sync_all(struct qdio_q *q) | ||
310 | { | ||
311 | return qdio_siga_sync(q, ~0U, ~0U); | ||
312 | } | ||
313 | |||
314 | static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit) | 311 | static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit) |
315 | { | 312 | { |
316 | unsigned long schid; | 313 | unsigned long schid = *((u32 *) &q->irq_ptr->schid); |
317 | unsigned int fc = 0; | 314 | unsigned int fc = QDIO_SIGA_WRITE; |
318 | u64 start_time = 0; | 315 | u64 start_time = 0; |
319 | int cc; | 316 | int cc; |
320 | 317 | ||
321 | if (q->u.out.use_enh_siga) | ||
322 | fc = 3; | ||
323 | |||
324 | if (is_qebsm(q)) { | 318 | if (is_qebsm(q)) { |
325 | schid = q->irq_ptr->sch_token; | 319 | schid = q->irq_ptr->sch_token; |
326 | fc |= 0x80; | 320 | fc |= QDIO_SIGA_QEBSM_FLAG; |
327 | } | 321 | } |
328 | else | ||
329 | schid = *((u32 *)&q->irq_ptr->schid); | ||
330 | |||
331 | again: | 322 | again: |
332 | cc = do_siga_output(schid, q->mask, busy_bit, fc); | 323 | cc = do_siga_output(schid, q->mask, busy_bit, fc); |
333 | 324 | ||
334 | /* hipersocket busy condition */ | 325 | /* hipersocket busy condition */ |
335 | if (*busy_bit) { | 326 | if (unlikely(*busy_bit)) { |
336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); | 327 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); |
337 | 328 | ||
338 | if (!start_time) { | 329 | if (!start_time) { |
@@ -347,32 +338,41 @@ again: | |||
347 | 338 | ||
348 | static inline int qdio_siga_input(struct qdio_q *q) | 339 | static inline int qdio_siga_input(struct qdio_q *q) |
349 | { | 340 | { |
341 | unsigned long schid = *((u32 *) &q->irq_ptr->schid); | ||
342 | unsigned int fc = QDIO_SIGA_READ; | ||
350 | int cc; | 343 | int cc; |
351 | 344 | ||
352 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr); | 345 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr); |
353 | qperf_inc(q, siga_read); | 346 | qperf_inc(q, siga_read); |
354 | 347 | ||
355 | cc = do_siga_input(q->irq_ptr->schid, q->mask); | 348 | if (is_qebsm(q)) { |
356 | if (cc) | 349 | schid = q->irq_ptr->sch_token; |
350 | fc |= QDIO_SIGA_QEBSM_FLAG; | ||
351 | } | ||
352 | |||
353 | cc = do_siga_input(schid, q->mask, fc); | ||
354 | if (unlikely(cc)) | ||
357 | DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc); | 355 | DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc); |
358 | return cc; | 356 | return cc; |
359 | } | 357 | } |
360 | 358 | ||
361 | static inline void qdio_sync_after_thinint(struct qdio_q *q) | 359 | #define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0) |
360 | #define qdio_siga_sync_all(q) qdio_siga_sync(q, ~0U, ~0U) | ||
361 | |||
362 | static inline void qdio_sync_queues(struct qdio_q *q) | ||
362 | { | 363 | { |
363 | if (pci_out_supported(q)) { | 364 | /* PCI capable outbound queues will also be scanned so sync them too */ |
364 | if (need_siga_sync_thinint(q)) | 365 | if (pci_out_supported(q)) |
365 | qdio_siga_sync_all(q); | 366 | qdio_siga_sync_all(q); |
366 | else if (need_siga_sync_out_thinint(q)) | 367 | else |
367 | qdio_siga_sync_out(q); | ||
368 | } else | ||
369 | qdio_siga_sync_q(q); | 368 | qdio_siga_sync_q(q); |
370 | } | 369 | } |
371 | 370 | ||
372 | int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr, | 371 | int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr, |
373 | unsigned char *state) | 372 | unsigned char *state) |
374 | { | 373 | { |
375 | qdio_siga_sync_q(q); | 374 | if (need_siga_sync(q)) |
375 | qdio_siga_sync_q(q); | ||
376 | return get_buf_states(q, bufnr, state, 1, 0); | 376 | return get_buf_states(q, bufnr, state, 1, 0); |
377 | } | 377 | } |
378 | 378 | ||
@@ -407,13 +407,16 @@ static inline void account_sbals(struct qdio_q *q, int count) | |||
407 | q->q_stats.nr_sbals[pos]++; | 407 | q->q_stats.nr_sbals[pos]++; |
408 | } | 408 | } |
409 | 409 | ||
410 | static void announce_buffer_error(struct qdio_q *q, int count) | 410 | static void process_buffer_error(struct qdio_q *q, int count) |
411 | { | 411 | { |
412 | unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT : | ||
413 | SLSB_P_OUTPUT_NOT_INIT; | ||
414 | |||
412 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; | 415 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; |
413 | 416 | ||
414 | /* special handling for no target buffer empty */ | 417 | /* special handling for no target buffer empty */ |
415 | if ((!q->is_input_q && | 418 | if ((!q->is_input_q && |
416 | (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { | 419 | (q->sbal[q->first_to_check]->element[15].sflags) == 0x10)) { |
417 | qperf_inc(q, target_full); | 420 | qperf_inc(q, target_full); |
418 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", | 421 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", |
419 | q->first_to_check); | 422 | q->first_to_check); |
@@ -424,8 +427,14 @@ static void announce_buffer_error(struct qdio_q *q, int count) | |||
424 | DBF_ERROR((q->is_input_q) ? "IN:%2d" : "OUT:%2d", q->nr); | 427 | DBF_ERROR((q->is_input_q) ? "IN:%2d" : "OUT:%2d", q->nr); |
425 | DBF_ERROR("FTC:%3d C:%3d", q->first_to_check, count); | 428 | DBF_ERROR("FTC:%3d C:%3d", q->first_to_check, count); |
426 | DBF_ERROR("F14:%2x F15:%2x", | 429 | DBF_ERROR("F14:%2x F15:%2x", |
427 | q->sbal[q->first_to_check]->element[14].flags & 0xff, | 430 | q->sbal[q->first_to_check]->element[14].sflags, |
428 | q->sbal[q->first_to_check]->element[15].flags & 0xff); | 431 | q->sbal[q->first_to_check]->element[15].sflags); |
432 | |||
433 | /* | ||
434 | * Interrupts may be avoided as long as the error is present | ||
435 | * so change the buffer state immediately to avoid starvation. | ||
436 | */ | ||
437 | set_buf_states(q, q->first_to_check, state, count); | ||
429 | } | 438 | } |
430 | 439 | ||
431 | static inline void inbound_primed(struct qdio_q *q, int count) | 440 | static inline void inbound_primed(struct qdio_q *q, int count) |
@@ -476,7 +485,7 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
476 | static int get_inbound_buffer_frontier(struct qdio_q *q) | 485 | static int get_inbound_buffer_frontier(struct qdio_q *q) |
477 | { | 486 | { |
478 | int count, stop; | 487 | int count, stop; |
479 | unsigned char state; | 488 | unsigned char state = 0; |
480 | 489 | ||
481 | /* | 490 | /* |
482 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 491 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
@@ -506,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
506 | account_sbals(q, count); | 515 | account_sbals(q, count); |
507 | break; | 516 | break; |
508 | case SLSB_P_INPUT_ERROR: | 517 | case SLSB_P_INPUT_ERROR: |
509 | announce_buffer_error(q, count); | 518 | process_buffer_error(q, count); |
510 | /* process the buffer, the upper layer will take care of it */ | ||
511 | q->first_to_check = add_buf(q->first_to_check, count); | 519 | q->first_to_check = add_buf(q->first_to_check, count); |
512 | atomic_sub(count, &q->nr_buf_used); | 520 | atomic_sub(count, &q->nr_buf_used); |
513 | if (q->irq_ptr->perf_stat_enabled) | 521 | if (q->irq_ptr->perf_stat_enabled) |
@@ -549,7 +557,8 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
549 | if (!atomic_read(&q->nr_buf_used)) | 557 | if (!atomic_read(&q->nr_buf_used)) |
550 | return 1; | 558 | return 1; |
551 | 559 | ||
552 | qdio_siga_sync_q(q); | 560 | if (need_siga_sync(q)) |
561 | qdio_siga_sync_q(q); | ||
553 | get_buf_state(q, q->first_to_check, &state, 0); | 562 | get_buf_state(q, q->first_to_check, &state, 0); |
554 | 563 | ||
555 | if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR) | 564 | if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR) |
@@ -642,11 +651,14 @@ void qdio_inbound_processing(unsigned long data) | |||
642 | static int get_outbound_buffer_frontier(struct qdio_q *q) | 651 | static int get_outbound_buffer_frontier(struct qdio_q *q) |
643 | { | 652 | { |
644 | int count, stop; | 653 | int count, stop; |
645 | unsigned char state; | 654 | unsigned char state = 0; |
646 | 655 | ||
647 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && !pci_out_supported(q)) || | 656 | if (need_siga_sync(q)) |
648 | (queue_type(q) == QDIO_IQDIO_QFMT && multicast_outbound(q))) | 657 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && |
649 | qdio_siga_sync_q(q); | 658 | !pci_out_supported(q)) || |
659 | (queue_type(q) == QDIO_IQDIO_QFMT && | ||
660 | multicast_outbound(q))) | ||
661 | qdio_siga_sync_q(q); | ||
650 | 662 | ||
651 | /* | 663 | /* |
652 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 664 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
@@ -673,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
673 | account_sbals(q, count); | 685 | account_sbals(q, count); |
674 | break; | 686 | break; |
675 | case SLSB_P_OUTPUT_ERROR: | 687 | case SLSB_P_OUTPUT_ERROR: |
676 | announce_buffer_error(q, count); | 688 | process_buffer_error(q, count); |
677 | /* process the buffer, the upper layer will take care of it */ | ||
678 | q->first_to_check = add_buf(q->first_to_check, count); | 689 | q->first_to_check = add_buf(q->first_to_check, count); |
679 | atomic_sub(count, &q->nr_buf_used); | 690 | atomic_sub(count, &q->nr_buf_used); |
680 | if (q->irq_ptr->perf_stat_enabled) | 691 | if (q->irq_ptr->perf_stat_enabled) |
@@ -818,7 +829,8 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q) | |||
818 | static void __tiqdio_inbound_processing(struct qdio_q *q) | 829 | static void __tiqdio_inbound_processing(struct qdio_q *q) |
819 | { | 830 | { |
820 | qperf_inc(q, tasklet_inbound); | 831 | qperf_inc(q, tasklet_inbound); |
821 | qdio_sync_after_thinint(q); | 832 | if (need_siga_sync(q) && need_siga_sync_after_ai(q)) |
833 | qdio_sync_queues(q); | ||
822 | 834 | ||
823 | /* | 835 | /* |
824 | * The interrupt could be caused by a PCI request. Check the | 836 | * The interrupt could be caused by a PCI request. Check the |
@@ -884,19 +896,28 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) | |||
884 | if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | 896 | if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) |
885 | return; | 897 | return; |
886 | 898 | ||
887 | for_each_input_queue(irq_ptr, q, i) | 899 | for_each_input_queue(irq_ptr, q, i) { |
888 | tasklet_schedule(&q->tasklet); | 900 | if (q->u.in.queue_start_poll) { |
901 | /* skip if polling is enabled or already in work */ | ||
902 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
903 | &q->u.in.queue_irq_state)) { | ||
904 | qperf_inc(q, int_discarded); | ||
905 | continue; | ||
906 | } | ||
907 | q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr, | ||
908 | q->irq_ptr->int_parm); | ||
909 | } else | ||
910 | tasklet_schedule(&q->tasklet); | ||
911 | } | ||
889 | 912 | ||
890 | if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)) | 913 | if (!pci_out_supported(q)) |
891 | return; | 914 | return; |
892 | 915 | ||
893 | for_each_output_queue(irq_ptr, q, i) { | 916 | for_each_output_queue(irq_ptr, q, i) { |
894 | if (qdio_outbound_q_done(q)) | 917 | if (qdio_outbound_q_done(q)) |
895 | continue; | 918 | continue; |
896 | 919 | if (need_siga_sync(q) && need_siga_sync_out_after_pci(q)) | |
897 | if (!siga_syncs_out_pci(q)) | ||
898 | qdio_siga_sync_q(q); | 920 | qdio_siga_sync_q(q); |
899 | |||
900 | tasklet_schedule(&q->tasklet); | 921 | tasklet_schedule(&q->tasklet); |
901 | } | 922 | } |
902 | } | 923 | } |
@@ -959,6 +980,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
959 | return; | 980 | return; |
960 | } | 981 | } |
961 | 982 | ||
983 | kstat_cpu(smp_processor_id()).irqs[IOINT_QDI]++; | ||
962 | if (irq_ptr->perf_stat_enabled) | 984 | if (irq_ptr->perf_stat_enabled) |
963 | irq_ptr->perf_stat.qdio_int++; | 985 | irq_ptr->perf_stat.qdio_int++; |
964 | 986 | ||
@@ -1262,7 +1284,6 @@ int qdio_establish(struct qdio_initialize *init_data) | |||
1262 | } | 1284 | } |
1263 | 1285 | ||
1264 | qdio_setup_ssqd_info(irq_ptr); | 1286 | qdio_setup_ssqd_info(irq_ptr); |
1265 | DBF_EVENT("qDmmwc:%2x", irq_ptr->ssqd_desc.mmwc); | ||
1266 | DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac); | 1287 | DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac); |
1267 | 1288 | ||
1268 | /* qebsm is now setup if available, initialize buffer states */ | 1289 | /* qebsm is now setup if available, initialize buffer states */ |
@@ -1425,7 +1446,7 @@ set: | |||
1425 | static int handle_outbound(struct qdio_q *q, unsigned int callflags, | 1446 | static int handle_outbound(struct qdio_q *q, unsigned int callflags, |
1426 | int bufnr, int count) | 1447 | int bufnr, int count) |
1427 | { | 1448 | { |
1428 | unsigned char state; | 1449 | unsigned char state = 0; |
1429 | int used, rc = 0; | 1450 | int used, rc = 0; |
1430 | 1451 | ||
1431 | qperf_inc(q, outbound_call); | 1452 | qperf_inc(q, outbound_call); |
@@ -1434,52 +1455,38 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1434 | used = atomic_add_return(count, &q->nr_buf_used); | 1455 | used = atomic_add_return(count, &q->nr_buf_used); |
1435 | BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q); | 1456 | BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q); |
1436 | 1457 | ||
1458 | if (used == QDIO_MAX_BUFFERS_PER_Q) | ||
1459 | qperf_inc(q, outbound_queue_full); | ||
1460 | |||
1437 | if (callflags & QDIO_FLAG_PCI_OUT) { | 1461 | if (callflags & QDIO_FLAG_PCI_OUT) { |
1438 | q->u.out.pci_out_enabled = 1; | 1462 | q->u.out.pci_out_enabled = 1; |
1439 | qperf_inc(q, pci_request_int); | 1463 | qperf_inc(q, pci_request_int); |
1440 | } | 1464 | } else |
1441 | else | ||
1442 | q->u.out.pci_out_enabled = 0; | 1465 | q->u.out.pci_out_enabled = 0; |
1443 | 1466 | ||
1444 | if (queue_type(q) == QDIO_IQDIO_QFMT) { | 1467 | if (queue_type(q) == QDIO_IQDIO_QFMT) { |
1445 | if (multicast_outbound(q)) | 1468 | /* One SIGA-W per buffer required for unicast HiperSockets. */ |
1469 | WARN_ON_ONCE(count > 1 && !multicast_outbound(q)); | ||
1470 | |||
1471 | rc = qdio_kick_outbound_q(q); | ||
1472 | } else if (need_siga_sync(q)) { | ||
1473 | rc = qdio_siga_sync_q(q); | ||
1474 | } else { | ||
1475 | /* try to fast requeue buffers */ | ||
1476 | get_buf_state(q, prev_buf(bufnr), &state, 0); | ||
1477 | if (state != SLSB_CU_OUTPUT_PRIMED) | ||
1446 | rc = qdio_kick_outbound_q(q); | 1478 | rc = qdio_kick_outbound_q(q); |
1447 | else | 1479 | else |
1448 | if ((q->irq_ptr->ssqd_desc.mmwc > 1) && | 1480 | qperf_inc(q, fast_requeue); |
1449 | (count > 1) && | ||
1450 | (count <= q->irq_ptr->ssqd_desc.mmwc)) { | ||
1451 | /* exploit enhanced SIGA */ | ||
1452 | q->u.out.use_enh_siga = 1; | ||
1453 | rc = qdio_kick_outbound_q(q); | ||
1454 | } else { | ||
1455 | /* | ||
1456 | * One siga-w per buffer required for unicast | ||
1457 | * HiperSockets. | ||
1458 | */ | ||
1459 | q->u.out.use_enh_siga = 0; | ||
1460 | while (count--) { | ||
1461 | rc = qdio_kick_outbound_q(q); | ||
1462 | if (rc) | ||
1463 | goto out; | ||
1464 | } | ||
1465 | } | ||
1466 | goto out; | ||
1467 | } | 1481 | } |
1468 | 1482 | ||
1469 | if (need_siga_sync(q)) { | 1483 | /* in case of SIGA errors we must process the error immediately */ |
1470 | qdio_siga_sync_q(q); | 1484 | if (used >= q->u.out.scan_threshold || rc) |
1471 | goto out; | 1485 | tasklet_schedule(&q->tasklet); |
1472 | } | ||
1473 | |||
1474 | /* try to fast requeue buffers */ | ||
1475 | get_buf_state(q, prev_buf(bufnr), &state, 0); | ||
1476 | if (state != SLSB_CU_OUTPUT_PRIMED) | ||
1477 | rc = qdio_kick_outbound_q(q); | ||
1478 | else | 1486 | else |
1479 | qperf_inc(q, fast_requeue); | 1487 | /* free the SBALs in case of no further traffic */ |
1480 | 1488 | if (!timer_pending(&q->u.out.timer)) | |
1481 | out: | 1489 | mod_timer(&q->u.out.timer, jiffies + HZ); |
1482 | tasklet_schedule(&q->tasklet); | ||
1483 | return rc; | 1490 | return rc; |
1484 | } | 1491 | } |
1485 | 1492 | ||
@@ -1508,7 +1515,8 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1508 | 1515 | ||
1509 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) | 1516 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) |
1510 | return -EBUSY; | 1517 | return -EBUSY; |
1511 | 1518 | if (!count) | |
1519 | return 0; | ||
1512 | if (callflags & QDIO_FLAG_SYNC_INPUT) | 1520 | if (callflags & QDIO_FLAG_SYNC_INPUT) |
1513 | return handle_inbound(irq_ptr->input_qs[q_nr], | 1521 | return handle_inbound(irq_ptr->input_qs[q_nr], |
1514 | callflags, bufnr, count); | 1522 | callflags, bufnr, count); |
@@ -1519,30 +1527,155 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1519 | } | 1527 | } |
1520 | EXPORT_SYMBOL_GPL(do_QDIO); | 1528 | EXPORT_SYMBOL_GPL(do_QDIO); |
1521 | 1529 | ||
1530 | /** | ||
1531 | * qdio_start_irq - process input buffers | ||
1532 | * @cdev: associated ccw_device for the qdio subchannel | ||
1533 | * @nr: input queue number | ||
1534 | * | ||
1535 | * Return codes | ||
1536 | * 0 - success | ||
1537 | * 1 - irqs not started since new data is available | ||
1538 | */ | ||
1539 | int qdio_start_irq(struct ccw_device *cdev, int nr) | ||
1540 | { | ||
1541 | struct qdio_q *q; | ||
1542 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1543 | |||
1544 | if (!irq_ptr) | ||
1545 | return -ENODEV; | ||
1546 | q = irq_ptr->input_qs[nr]; | ||
1547 | |||
1548 | WARN_ON(queue_irqs_enabled(q)); | ||
1549 | |||
1550 | if (!shared_ind(q->irq_ptr->dsci)) | ||
1551 | xchg(q->irq_ptr->dsci, 0); | ||
1552 | |||
1553 | qdio_stop_polling(q); | ||
1554 | clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state); | ||
1555 | |||
1556 | /* | ||
1557 | * We need to check again to not lose initiative after | ||
1558 | * resetting the ACK state. | ||
1559 | */ | ||
1560 | if (!shared_ind(q->irq_ptr->dsci) && *q->irq_ptr->dsci) | ||
1561 | goto rescan; | ||
1562 | if (!qdio_inbound_q_done(q)) | ||
1563 | goto rescan; | ||
1564 | return 0; | ||
1565 | |||
1566 | rescan: | ||
1567 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
1568 | &q->u.in.queue_irq_state)) | ||
1569 | return 0; | ||
1570 | else | ||
1571 | return 1; | ||
1572 | |||
1573 | } | ||
1574 | EXPORT_SYMBOL(qdio_start_irq); | ||
1575 | |||
1576 | /** | ||
1577 | * qdio_get_next_buffers - process input buffers | ||
1578 | * @cdev: associated ccw_device for the qdio subchannel | ||
1579 | * @nr: input queue number | ||
1580 | * @bufnr: first filled buffer number | ||
1581 | * @error: buffers are in error state | ||
1582 | * | ||
1583 | * Return codes | ||
1584 | * < 0 - error | ||
1585 | * = 0 - no new buffers found | ||
1586 | * > 0 - number of processed buffers | ||
1587 | */ | ||
1588 | int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr, | ||
1589 | int *error) | ||
1590 | { | ||
1591 | struct qdio_q *q; | ||
1592 | int start, end; | ||
1593 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1594 | |||
1595 | if (!irq_ptr) | ||
1596 | return -ENODEV; | ||
1597 | q = irq_ptr->input_qs[nr]; | ||
1598 | WARN_ON(queue_irqs_enabled(q)); | ||
1599 | |||
1600 | /* | ||
1601 | * Cannot rely on automatic sync after interrupt since queues may | ||
1602 | * also be examined without interrupt. | ||
1603 | */ | ||
1604 | if (need_siga_sync(q)) | ||
1605 | qdio_sync_queues(q); | ||
1606 | |||
1607 | /* check the PCI capable outbound queues. */ | ||
1608 | qdio_check_outbound_after_thinint(q); | ||
1609 | |||
1610 | if (!qdio_inbound_q_moved(q)) | ||
1611 | return 0; | ||
1612 | |||
1613 | /* Note: upper-layer MUST stop processing immediately here ... */ | ||
1614 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) | ||
1615 | return -EIO; | ||
1616 | |||
1617 | start = q->first_to_kick; | ||
1618 | end = q->first_to_check; | ||
1619 | *bufnr = start; | ||
1620 | *error = q->qdio_error; | ||
1621 | |||
1622 | /* for the next time */ | ||
1623 | q->first_to_kick = end; | ||
1624 | q->qdio_error = 0; | ||
1625 | return sub_buf(end, start); | ||
1626 | } | ||
1627 | EXPORT_SYMBOL(qdio_get_next_buffers); | ||
1628 | |||
1629 | /** | ||
1630 | * qdio_stop_irq - disable interrupt processing for the device | ||
1631 | * @cdev: associated ccw_device for the qdio subchannel | ||
1632 | * @nr: input queue number | ||
1633 | * | ||
1634 | * Return codes | ||
1635 | * 0 - interrupts were already disabled | ||
1636 | * 1 - interrupts successfully disabled | ||
1637 | */ | ||
1638 | int qdio_stop_irq(struct ccw_device *cdev, int nr) | ||
1639 | { | ||
1640 | struct qdio_q *q; | ||
1641 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1642 | |||
1643 | if (!irq_ptr) | ||
1644 | return -ENODEV; | ||
1645 | q = irq_ptr->input_qs[nr]; | ||
1646 | |||
1647 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
1648 | &q->u.in.queue_irq_state)) | ||
1649 | return 0; | ||
1650 | else | ||
1651 | return 1; | ||
1652 | } | ||
1653 | EXPORT_SYMBOL(qdio_stop_irq); | ||
1654 | |||
1522 | static int __init init_QDIO(void) | 1655 | static int __init init_QDIO(void) |
1523 | { | 1656 | { |
1524 | int rc; | 1657 | int rc; |
1525 | 1658 | ||
1526 | rc = qdio_setup_init(); | 1659 | rc = qdio_debug_init(); |
1527 | if (rc) | 1660 | if (rc) |
1528 | return rc; | 1661 | return rc; |
1662 | rc = qdio_setup_init(); | ||
1663 | if (rc) | ||
1664 | goto out_debug; | ||
1529 | rc = tiqdio_allocate_memory(); | 1665 | rc = tiqdio_allocate_memory(); |
1530 | if (rc) | 1666 | if (rc) |
1531 | goto out_cache; | 1667 | goto out_cache; |
1532 | rc = qdio_debug_init(); | ||
1533 | if (rc) | ||
1534 | goto out_ti; | ||
1535 | rc = tiqdio_register_thinints(); | 1668 | rc = tiqdio_register_thinints(); |
1536 | if (rc) | 1669 | if (rc) |
1537 | goto out_debug; | 1670 | goto out_ti; |
1538 | return 0; | 1671 | return 0; |
1539 | 1672 | ||
1540 | out_debug: | ||
1541 | qdio_debug_exit(); | ||
1542 | out_ti: | 1673 | out_ti: |
1543 | tiqdio_free_memory(); | 1674 | tiqdio_free_memory(); |
1544 | out_cache: | 1675 | out_cache: |
1545 | qdio_setup_exit(); | 1676 | qdio_setup_exit(); |
1677 | out_debug: | ||
1678 | qdio_debug_exit(); | ||
1546 | return rc; | 1679 | return rc; |
1547 | } | 1680 | } |
1548 | 1681 | ||
@@ -1550,8 +1683,8 @@ static void __exit exit_QDIO(void) | |||
1550 | { | 1683 | { |
1551 | tiqdio_unregister_thinints(); | 1684 | tiqdio_unregister_thinints(); |
1552 | tiqdio_free_memory(); | 1685 | tiqdio_free_memory(); |
1553 | qdio_debug_exit(); | ||
1554 | qdio_setup_exit(); | 1686 | qdio_setup_exit(); |
1687 | qdio_debug_exit(); | ||
1555 | } | 1688 | } |
1556 | 1689 | ||
1557 | module_init(init_QDIO); | 1690 | module_init(init_QDIO); |