History

s390/qdio: add IRQ reduction for error SBALs

SBALs in PRIMED or ERROR state represent new work on the Input Queue. But while inbound_primed() does all sorts of ACK management for new PRIMED work, the same handling is currently missing for ERROR work. In particular the path for ERROR work doesn't clear up _old_ ACKs. Treat ERROR work the same as PRIMED work, but consider that the QEBSM auto-ACK feature doesn't apply here. So we need to set the ACK manually, as if it was a non-QEBSM device. Note that this doesn't aspire to actually improve performance, the main goal is to just unify the code paths and have consistent behaviour.

Julian Wiedmann committed 6 years ago

Commit c70d82e1 parent 1db85d01 file · +11 −12Browse files

Unified · Split

drivers/s390/cio/qdio_main.c+11−12
@@ -438,15 +438,12 @@ static void process_buffer_error(struct qdio_q *q, unsigned int start, · 437 unmodified lines
438 q->sbal[start]->element[15].sflags);438 q->sbal[start]->element[15].sflags);
439}439}
440 440
441static inline void inbound_primed(struct qdio_q *q, unsigned int start,441static inline void inbound_handle_work(struct qdio_q *q, unsigned int start,
442 int count)442 int count, bool auto_ack)
443{443{
444 int new;444 int new;
445 445
446 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim:%1d %02x", q->nr, count);446 if (auto_ack) {
447
448 /* for QEBSM the ACK was already set by EQBS */
449 if (is_qebsm(q)) {
450 if (!q->u.in.ack_count) {447 if (!q->u.in.ack_count) {
451 q->u.in.ack_count = count;448 q->u.in.ack_count = count;
452 q->u.in.ack_start = start;449 q->u.in.ack_start = start;
@@ -507,19 +504,21 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start) · 54 unmodified lines
507 504
508 switch (state) {505 switch (state) {
509 case SLSB_P_INPUT_PRIMED:506 case SLSB_P_INPUT_PRIMED:
510 inbound_primed(q, start, count);507 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim:%1d %02x", q->nr,
508 count);
509
510 inbound_handle_work(q, start, count, is_qebsm(q));
511 if (atomic_sub_return(count, &q->nr_buf_used) == 0)511 if (atomic_sub_return(count, &q->nr_buf_used) == 0)
512 qperf_inc(q, inbound_queue_full);512 qperf_inc(q, inbound_queue_full);
513 if (q->irq_ptr->perf_stat_enabled)513 if (q->irq_ptr->perf_stat_enabled)
514 account_sbals(q, count);514 account_sbals(q, count);
515 return count;515 return count;
516 case SLSB_P_INPUT_ERROR:516 case SLSB_P_INPUT_ERROR:
517 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in err:%1d %02x", q->nr,
518 count);
519
517 process_buffer_error(q, start, count);520 process_buffer_error(q, start, count);
518 /*521 inbound_handle_work(q, start, count, false);
519 * Interrupts may be avoided as long as the error is present
520 * so change the buffer state immediately to avoid starvation.
521 */
522 set_buf_states(q, start, SLSB_P_INPUT_NOT_INIT, count);
523 if (atomic_sub_return(count, &q->nr_buf_used) == 0)522 if (atomic_sub_return(count, &q->nr_buf_used) == 0)
524 qperf_inc(q, inbound_queue_full);523 qperf_inc(q, inbound_queue_full);
525 if (q->irq_ptr->perf_stat_enabled)524 if (q->irq_ptr->perf_stat_enabled)