diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2011-01-05 06:47:54 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2011-01-05 06:47:28 -0500 |
commit | 90adac58d1a4daf3560739ff5b76497d5ece16c4 (patch) | |
tree | 6304b54c5b8200de91f3c151051a412a3536d0f4 /drivers/s390 | |
parent | 110da31709023de61735f2d8a3e52c20c23bb570 (diff) |
[S390] qdio: cleanup SIGA sync
Simplify the SIGA sync code and add unlikely annotations. In polling mode
SBALs may be accessed without interrupt, so call SIGA sync before every scan.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/qdio.h | 16 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 64 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_setup.c | 19 |
3 files changed, 44 insertions, 55 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 1b40a92fec14..7bc643f3f5ab 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -148,10 +148,9 @@ struct siga_flag { | |||
148 | u8 input:1; | 148 | u8 input:1; |
149 | u8 output:1; | 149 | u8 output:1; |
150 | u8 sync:1; | 150 | u8 sync:1; |
151 | u8 no_sync_ti:1; | 151 | u8 sync_after_ai:1; |
152 | u8 no_sync_out_ti:1; | 152 | u8 sync_out_after_pci:1; |
153 | u8 no_sync_out_pci:1; | 153 | u8:3; |
154 | u8:2; | ||
155 | } __attribute__ ((packed)); | 154 | } __attribute__ ((packed)); |
156 | 155 | ||
157 | struct chsc_ssqd_area { | 156 | struct chsc_ssqd_area { |
@@ -390,12 +389,13 @@ static inline int multicast_outbound(struct qdio_q *q) | |||
390 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) | 389 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
391 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) | 390 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) |
392 | 391 | ||
393 | #define need_siga_sync_thinint(q) (!q->irq_ptr->siga_flag.no_sync_ti) | ||
394 | #define need_siga_sync_out_thinint(q) (!q->irq_ptr->siga_flag.no_sync_out_ti) | ||
395 | #define need_siga_in(q) (q->irq_ptr->siga_flag.input) | 392 | #define need_siga_in(q) (q->irq_ptr->siga_flag.input) |
396 | #define need_siga_out(q) (q->irq_ptr->siga_flag.output) | 393 | #define need_siga_out(q) (q->irq_ptr->siga_flag.output) |
397 | #define need_siga_sync(q) (q->irq_ptr->siga_flag.sync) | 394 | #define need_siga_sync(q) (unlikely(q->irq_ptr->siga_flag.sync)) |
398 | #define siga_syncs_out_pci(q) (q->irq_ptr->siga_flag.no_sync_out_pci) | 395 | #define need_siga_sync_after_ai(q) \ |
396 | (unlikely(q->irq_ptr->siga_flag.sync_after_ai)) | ||
397 | #define need_siga_sync_out_after_pci(q) \ | ||
398 | (unlikely(q->irq_ptr->siga_flag.sync_out_after_pci)) | ||
399 | 399 | ||
400 | #define for_each_input_queue(irq_ptr, q, i) \ | 400 | #define for_each_input_queue(irq_ptr, q, i) \ |
401 | for (i = 0, q = irq_ptr->input_qs[0]; \ | 401 | for (i = 0, q = irq_ptr->input_qs[0]; \ |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 8a722f208325..e9fff2b9bce2 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -286,9 +286,6 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output, | |||
286 | unsigned int fc = QDIO_SIGA_SYNC; | 286 | unsigned int fc = QDIO_SIGA_SYNC; |
287 | int cc; | 287 | int cc; |
288 | 288 | ||
289 | if (!need_siga_sync(q)) | ||
290 | return 0; | ||
291 | |||
292 | 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); |
293 | qperf_inc(q, siga_sync); | 290 | qperf_inc(q, siga_sync); |
294 | 291 | ||
@@ -311,16 +308,6 @@ static inline int qdio_siga_sync_q(struct qdio_q *q) | |||
311 | return qdio_siga_sync(q, q->mask, 0); | 308 | return qdio_siga_sync(q, q->mask, 0); |
312 | } | 309 | } |
313 | 310 | ||
314 | static inline int qdio_siga_sync_out(struct qdio_q *q) | ||
315 | { | ||
316 | return qdio_siga_sync(q, ~0U, 0); | ||
317 | } | ||
318 | |||
319 | static inline int qdio_siga_sync_all(struct qdio_q *q) | ||
320 | { | ||
321 | return qdio_siga_sync(q, ~0U, ~0U); | ||
322 | } | ||
323 | |||
324 | 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) |
325 | { | 312 | { |
326 | unsigned long schid = *((u32 *) &q->irq_ptr->schid); | 313 | unsigned long schid = *((u32 *) &q->irq_ptr->schid); |
@@ -369,21 +356,23 @@ static inline int qdio_siga_input(struct qdio_q *q) | |||
369 | return cc; | 356 | return cc; |
370 | } | 357 | } |
371 | 358 | ||
372 | 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) | ||
373 | { | 363 | { |
374 | if (pci_out_supported(q)) { | 364 | /* PCI capable outbound queues will also be scanned so sync them too */ |
375 | if (need_siga_sync_thinint(q)) | 365 | if (pci_out_supported(q)) |
376 | qdio_siga_sync_all(q); | 366 | qdio_siga_sync_all(q); |
377 | else if (need_siga_sync_out_thinint(q)) | 367 | else |
378 | qdio_siga_sync_out(q); | ||
379 | } else | ||
380 | qdio_siga_sync_q(q); | 368 | qdio_siga_sync_q(q); |
381 | } | 369 | } |
382 | 370 | ||
383 | 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, |
384 | unsigned char *state) | 372 | unsigned char *state) |
385 | { | 373 | { |
386 | qdio_siga_sync_q(q); | 374 | if (need_siga_sync(q)) |
375 | qdio_siga_sync_q(q); | ||
387 | return get_buf_states(q, bufnr, state, 1, 0); | 376 | return get_buf_states(q, bufnr, state, 1, 0); |
388 | } | 377 | } |
389 | 378 | ||
@@ -560,7 +549,8 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
560 | if (!atomic_read(&q->nr_buf_used)) | 549 | if (!atomic_read(&q->nr_buf_used)) |
561 | return 1; | 550 | return 1; |
562 | 551 | ||
563 | qdio_siga_sync_q(q); | 552 | if (need_siga_sync(q)) |
553 | qdio_siga_sync_q(q); | ||
564 | get_buf_state(q, q->first_to_check, &state, 0); | 554 | get_buf_state(q, q->first_to_check, &state, 0); |
565 | 555 | ||
566 | if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR) | 556 | if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR) |
@@ -655,9 +645,12 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
655 | int count, stop; | 645 | int count, stop; |
656 | unsigned char state; | 646 | unsigned char state; |
657 | 647 | ||
658 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && !pci_out_supported(q)) || | 648 | if (need_siga_sync(q)) |
659 | (queue_type(q) == QDIO_IQDIO_QFMT && multicast_outbound(q))) | 649 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && |
660 | qdio_siga_sync_q(q); | 650 | !pci_out_supported(q)) || |
651 | (queue_type(q) == QDIO_IQDIO_QFMT && | ||
652 | multicast_outbound(q))) | ||
653 | qdio_siga_sync_q(q); | ||
661 | 654 | ||
662 | /* | 655 | /* |
663 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 656 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
@@ -829,7 +822,8 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q) | |||
829 | static void __tiqdio_inbound_processing(struct qdio_q *q) | 822 | static void __tiqdio_inbound_processing(struct qdio_q *q) |
830 | { | 823 | { |
831 | qperf_inc(q, tasklet_inbound); | 824 | qperf_inc(q, tasklet_inbound); |
832 | qdio_sync_after_thinint(q); | 825 | if (need_siga_sync(q) && need_siga_sync_after_ai(q)) |
826 | qdio_sync_queues(q); | ||
833 | 827 | ||
834 | /* | 828 | /* |
835 | * The interrupt could be caused by a PCI request. Check the | 829 | * The interrupt could be caused by a PCI request. Check the |
@@ -909,16 +903,14 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) | |||
909 | tasklet_schedule(&q->tasklet); | 903 | tasklet_schedule(&q->tasklet); |
910 | } | 904 | } |
911 | 905 | ||
912 | if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)) | 906 | if (!pci_out_supported(q)) |
913 | return; | 907 | return; |
914 | 908 | ||
915 | for_each_output_queue(irq_ptr, q, i) { | 909 | for_each_output_queue(irq_ptr, q, i) { |
916 | if (qdio_outbound_q_done(q)) | 910 | if (qdio_outbound_q_done(q)) |
917 | continue; | 911 | continue; |
918 | 912 | if (need_siga_sync(q) && need_siga_sync_out_after_pci(q)) | |
919 | if (!siga_syncs_out_pci(q)) | ||
920 | qdio_siga_sync_q(q); | 913 | qdio_siga_sync_q(q); |
921 | |||
922 | tasklet_schedule(&q->tasklet); | 914 | tasklet_schedule(&q->tasklet); |
923 | } | 915 | } |
924 | } | 916 | } |
@@ -1470,7 +1462,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1470 | WARN_ON_ONCE(count > 1 && !multicast_outbound(q)); | 1462 | WARN_ON_ONCE(count > 1 && !multicast_outbound(q)); |
1471 | 1463 | ||
1472 | rc = qdio_kick_outbound_q(q); | 1464 | rc = qdio_kick_outbound_q(q); |
1473 | } else if (unlikely(need_siga_sync(q))) { | 1465 | } else if (need_siga_sync(q)) { |
1474 | rc = qdio_siga_sync_q(q); | 1466 | rc = qdio_siga_sync_q(q); |
1475 | } else { | 1467 | } else { |
1476 | /* try to fast requeue buffers */ | 1468 | /* try to fast requeue buffers */ |
@@ -1597,12 +1589,14 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr, | |||
1597 | q = irq_ptr->input_qs[nr]; | 1589 | q = irq_ptr->input_qs[nr]; |
1598 | WARN_ON(queue_irqs_enabled(q)); | 1590 | WARN_ON(queue_irqs_enabled(q)); |
1599 | 1591 | ||
1600 | qdio_sync_after_thinint(q); | ||
1601 | |||
1602 | /* | 1592 | /* |
1603 | * The interrupt could be caused by a PCI request. Check the | 1593 | * Cannot rely on automatic sync after interrupt since queues may |
1604 | * PCI capable outbound queues. | 1594 | * also be examined without interrupt. |
1605 | */ | 1595 | */ |
1596 | if (need_siga_sync(q)) | ||
1597 | qdio_sync_queues(q); | ||
1598 | |||
1599 | /* check the PCI capable outbound queues. */ | ||
1606 | qdio_check_outbound_after_thinint(q); | 1600 | qdio_check_outbound_after_thinint(q); |
1607 | 1601 | ||
1608 | if (!qdio_inbound_q_moved(q)) | 1602 | if (!qdio_inbound_q_moved(q)) |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 635f35dc8466..89107d0938c4 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
@@ -197,14 +197,10 @@ static void process_ac_flags(struct qdio_irq *irq_ptr, unsigned char qdioac) | |||
197 | irq_ptr->siga_flag.output = 1; | 197 | irq_ptr->siga_flag.output = 1; |
198 | if (qdioac & AC1_SIGA_SYNC_NEEDED) | 198 | if (qdioac & AC1_SIGA_SYNC_NEEDED) |
199 | irq_ptr->siga_flag.sync = 1; | 199 | irq_ptr->siga_flag.sync = 1; |
200 | if (qdioac & AC1_AUTOMATIC_SYNC_ON_THININT) | 200 | if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_THININT)) |
201 | irq_ptr->siga_flag.no_sync_ti = 1; | 201 | irq_ptr->siga_flag.sync_after_ai = 1; |
202 | if (qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI) | 202 | if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI)) |
203 | irq_ptr->siga_flag.no_sync_out_pci = 1; | 203 | irq_ptr->siga_flag.sync_out_after_pci = 1; |
204 | |||
205 | if (irq_ptr->siga_flag.no_sync_out_pci && | ||
206 | irq_ptr->siga_flag.no_sync_ti) | ||
207 | irq_ptr->siga_flag.no_sync_out_ti = 1; | ||
208 | } | 204 | } |
209 | 205 | ||
210 | static void check_and_setup_qebsm(struct qdio_irq *irq_ptr, | 206 | static void check_and_setup_qebsm(struct qdio_irq *irq_ptr, |
@@ -452,7 +448,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, | |||
452 | char s[80]; | 448 | char s[80]; |
453 | 449 | ||
454 | snprintf(s, 80, "qdio: %s %s on SC %x using " | 450 | snprintf(s, 80, "qdio: %s %s on SC %x using " |
455 | "AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s%s\n", | 451 | "AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s\n", |
456 | dev_name(&cdev->dev), | 452 | dev_name(&cdev->dev), |
457 | (irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" : | 453 | (irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" : |
458 | ((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"), | 454 | ((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"), |
@@ -464,9 +460,8 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, | |||
464 | (irq_ptr->siga_flag.input) ? "R" : " ", | 460 | (irq_ptr->siga_flag.input) ? "R" : " ", |
465 | (irq_ptr->siga_flag.output) ? "W" : " ", | 461 | (irq_ptr->siga_flag.output) ? "W" : " ", |
466 | (irq_ptr->siga_flag.sync) ? "S" : " ", | 462 | (irq_ptr->siga_flag.sync) ? "S" : " ", |
467 | (!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ", | 463 | (irq_ptr->siga_flag.sync_after_ai) ? "A" : " ", |
468 | (!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ", | 464 | (irq_ptr->siga_flag.sync_out_after_pci) ? "P" : " "); |
469 | (!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " "); | ||
470 | printk(KERN_INFO "%s", s); | 465 | printk(KERN_INFO "%s", s); |
471 | } | 466 | } |
472 | 467 | ||