Commit 7940eaf2 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Vasily Gorbik
Browse files

s390/qdio: improve handling of PENDING buffers for QEBSM devices



For QEBSM devices the 'merge_pending' mechanism in get_buf_states()
doesn't apply, and we can actually get SLSB_P_OUTPUT_PENDING returned.

So for this case propagating the PENDING state to the driver via the
queue's sbal_state doesn't make sense and creates unnecessary overhead.
Instead introduce a new QDIO_ERROR_* flag that gets passed to the
driver, and triggers the same processing as if the buffers were flagged
as QDIO_OUTBUF_STATE_FLAG_PENDING.

Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 540936df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -315,6 +315,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
#define QDIO_ERROR_GET_BUF_STATE		0x0002
#define QDIO_ERROR_SET_BUF_STATE		0x0004
#define QDIO_ERROR_SLSB_STATE			0x0100
#define QDIO_ERROR_SLSB_PENDING			0x0200

#define QDIO_ERROR_FATAL			0x00ff
#define QDIO_ERROR_TEMPORARY			0xff00
+9 −2
Original line number Diff line number Diff line
@@ -571,6 +571,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start,
					unsigned int *error)
{
	unsigned char state = 0;
	unsigned int i;
	int count;

	q->timestamp = get_tod_clock_fast();
@@ -591,8 +592,14 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start,
		return 0;

	switch (state) {
	case SLSB_P_OUTPUT_EMPTY:
	case SLSB_P_OUTPUT_PENDING:
		/* detach the utilized QAOBs: */
		for (i = 0; i < count; i++)
			q->u.out.aobs[QDIO_BUFNR(start + i)] = NULL;

		*error = QDIO_ERROR_SLSB_PENDING;
		fallthrough;
	case SLSB_P_OUTPUT_EMPTY:
		/* the adapter got it */
		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
			"out empty:%1d %02x", q->nr, count);
@@ -643,7 +650,7 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start,
	if (count) {
		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr);

		if (q->u.out.use_cq) {
		if (q->u.out.use_cq && *error != QDIO_ERROR_SLSB_PENDING) {
			unsigned int i;

			for (i = 0; i < count; i++)
+6 −3
Original line number Diff line number Diff line
@@ -6068,14 +6068,17 @@ int qeth_poll(struct napi_struct *napi, int budget)
EXPORT_SYMBOL_GPL(qeth_poll);

static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
				 unsigned int bidx, bool error, int budget)
				 unsigned int bidx, unsigned int qdio_error,
				 int budget)
{
	struct qeth_qdio_out_buffer *buffer = queue->bufs[bidx];
	u8 sflags = buffer->buffer->element[15].sflags;
	struct qeth_card *card = queue->card;
	bool error = !!qdio_error;

	if (queue->bufstates && (queue->bufstates[bidx].flags &
				 QDIO_OUTBUF_STATE_FLAG_PENDING)) {
	if ((qdio_error == QDIO_ERROR_SLSB_PENDING) ||
	    (queue->bufstates && (queue->bufstates[bidx].flags &
				  QDIO_OUTBUF_STATE_FLAG_PENDING))) {
		WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED);

		QETH_CARD_TEXT_(card, 5, "pel%u", bidx);