Commit 0b6f4990 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Vasily Gorbik
Browse files

s390/qdio: simplify ACK tracking



Current code uses a 'polling' flag to keep track of whether an Input
Queue has any ACKed SBALs. QEBSM devices might have multiple ACKed
SBALs, and those are tracked separately with 'ack_count'.

By also setting ack_count for non-QEBSM devices (to a fixed value of 1),
we can use 'ack_count != 0' as replacement for the polling flag.

Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent fcd98d40
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -182,11 +182,9 @@ enum qdio_queue_irq_states {
};

struct qdio_input_q {
	/* input buffer acknowledgement flag */
	int polling;
	/* first ACK'ed buffer */
	int ack_start;
	/* how much sbals are acknowledged with qebsm */
	/* how many SBALs are acknowledged */
	int ack_count;
	/* last time of noticing incoming data */
	u64 timestamp;
+2 −3
Original line number Diff line number Diff line
@@ -124,9 +124,8 @@ static int qstat_show(struct seq_file *m, void *v)
	seq_printf(m, "nr_used: %d  ftc: %d\n",
		   atomic_read(&q->nr_buf_used), q->first_to_check);
	if (q->is_input_q) {
		seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
			   q->u.in.polling, q->u.in.ack_start,
			   q->u.in.ack_count);
		seq_printf(m, "ack start: %d  ack count: %d\n",
			   q->u.in.ack_start, q->u.in.ack_count);
		seq_printf(m, "DSCI: %x   IRQs disabled: %u\n",
			   *(u8 *)q->irq_ptr->dsci,
			   test_bit(QDIO_QUEUE_IRQS_DISABLED,
+11 −18
Original line number Diff line number Diff line
@@ -393,19 +393,15 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,

static inline void qdio_stop_polling(struct qdio_q *q)
{
	if (!q->u.in.polling)
	if (!q->u.in.ack_count)
		return;

	q->u.in.polling = 0;
	qperf_inc(q, stop_polling);

	/* show the card that we are not polling anymore */
	if (is_qebsm(q)) {
	set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
		       q->u.in.ack_count);
	q->u.in.ack_count = 0;
	} else
		set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT);
}

static inline void account_sbals(struct qdio_q *q, unsigned int count)
@@ -451,8 +447,7 @@ static inline void inbound_primed(struct qdio_q *q, unsigned int start,

	/* for QEBSM the ACK was already set by EQBS */
	if (is_qebsm(q)) {
		if (!q->u.in.polling) {
			q->u.in.polling = 1;
		if (!q->u.in.ack_count) {
			q->u.in.ack_count = count;
			q->u.in.ack_start = start;
			return;
@@ -471,12 +466,12 @@ static inline void inbound_primed(struct qdio_q *q, unsigned int start,
	 * or by the next inbound run.
	 */
	new = add_buf(start, count - 1);
	if (q->u.in.polling) {
	if (q->u.in.ack_count) {
		/* reset the previous ACK but first set the new one */
		set_buf_state(q, new, SLSB_P_INPUT_ACK);
		set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT);
	} else {
		q->u.in.polling = 1;
		q->u.in.ack_count = 1;
		set_buf_state(q, new, SLSB_P_INPUT_ACK);
	}

@@ -1479,13 +1474,12 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,

	qperf_inc(q, inbound_call);

	if (!q->u.in.polling)
	if (!q->u.in.ack_count)
		goto set;

	/* protect against stop polling setting an ACK for an emptied slsb */
	if (count == QDIO_MAX_BUFFERS_PER_Q) {
		/* overwriting everything, just delete polling status */
		q->u.in.polling = 0;
		q->u.in.ack_count = 0;
		goto set;
	} else if (buf_in_between(q->u.in.ack_start, bufnr, count)) {
@@ -1495,15 +1489,14 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
			diff = sub_buf(diff, q->u.in.ack_start);
			q->u.in.ack_count -= diff;
			if (q->u.in.ack_count <= 0) {
				q->u.in.polling = 0;
				q->u.in.ack_count = 0;
				goto set;
			}
			q->u.in.ack_start = add_buf(q->u.in.ack_start, diff);
		} else {
			/* the only ACK will be deleted */
			q->u.in.ack_count = 0;
		}
		else
			/* the only ACK will be deleted, so stop polling */
			q->u.in.polling = 0;
	}

set: