Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0951c6ba authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller
Browse files

s390/qeth: simplify reply object handling



Current code enqueues & dequeues a reply object from the waiter list
in various places. In particular, the dequeue & enqueue in
qeth_send_control_data_cb() looks fragile - this can cause
qeth_clear_ipacmd_list() to skip the active object.
Add some helpers, and boil the logic down by giving
qeth_send_control_data() the sole responsibility to add and remove
objects.

qeth_send_control_data_cb() and qeth_clear_ipacmd_list() will now only
notify the reply object to interrupt its wait cycle. This can cause
a slight delay in the removal, but that's no concern.

Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 51581fd0
Loading
Loading
Loading
Loading
+61 −57
Original line number Diff line number Diff line
@@ -566,6 +566,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
	if (reply) {
		refcount_set(&reply->refcnt, 1);
		atomic_set(&reply->received, 0);
		init_waitqueue_head(&reply->wait_q);
	}
	return reply;
}
@@ -581,6 +582,26 @@ static void qeth_put_reply(struct qeth_reply *reply)
		kfree(reply);
}

static void qeth_enqueue_reply(struct qeth_card *card, struct qeth_reply *reply)
{
	spin_lock_irq(&card->lock);
	list_add_tail(&reply->list, &card->cmd_waiter_list);
	spin_unlock_irq(&card->lock);
}

static void qeth_dequeue_reply(struct qeth_card *card, struct qeth_reply *reply)
{
	spin_lock_irq(&card->lock);
	list_del(&reply->list);
	spin_unlock_irq(&card->lock);
}

static void qeth_notify_reply(struct qeth_reply *reply)
{
	atomic_inc(&reply->received);
	wake_up(&reply->wait_q);
}

static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
		struct qeth_card *card)
{
@@ -657,19 +678,15 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,

void qeth_clear_ipacmd_list(struct qeth_card *card)
{
	struct qeth_reply *reply, *r;
	struct qeth_reply *reply;
	unsigned long flags;

	QETH_CARD_TEXT(card, 4, "clipalst");

	spin_lock_irqsave(&card->lock, flags);
	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
		qeth_get_reply(reply);
	list_for_each_entry(reply, &card->cmd_waiter_list, list) {
		reply->rc = -EIO;
		atomic_inc(&reply->received);
		list_del_init(&reply->list);
		wake_up(&reply->wait_q);
		qeth_put_reply(reply);
		qeth_notify_reply(reply);
	}
	spin_unlock_irqrestore(&card->lock, flags);
}
@@ -774,9 +791,10 @@ static void qeth_send_control_data_cb(struct qeth_card *card,
				      struct qeth_cmd_buffer *iob)
{
	struct qeth_ipa_cmd *cmd = NULL;
	struct qeth_reply *reply, *r;
	struct qeth_reply *reply = NULL;
	struct qeth_reply *r;
	unsigned long flags;
	int keep_reply;
	int keep_reply = 0;
	int rc = 0;

	QETH_CARD_TEXT(card, 4, "sndctlcb");
@@ -808,44 +826,40 @@ static void qeth_send_control_data_cb(struct qeth_card *card,
			goto out;
	}

	/* match against pending cmd requests */
	spin_lock_irqsave(&card->lock, flags);
	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
		if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
		    ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
	list_for_each_entry(r, &card->cmd_waiter_list, list) {
		if ((r->seqno == QETH_IDX_COMMAND_SEQNO) ||
		    (cmd && (r->seqno == cmd->hdr.seqno))) {
			reply = r;
			/* take the object outside the lock */
			qeth_get_reply(reply);
			list_del_init(&reply->list);
			break;
		}
	}
	spin_unlock_irqrestore(&card->lock, flags);
			keep_reply = 0;
			if (reply->callback != NULL) {

	if (!reply)
		goto out;

	if (reply->callback) {
		if (cmd) {
					reply->offset = (__u16)((char *)cmd -
							(char *)iob->data);
					keep_reply = reply->callback(card,
							reply,
			reply->offset = (u16)((char *)cmd - (char *)iob->data);
			keep_reply = reply->callback(card, reply,
						     (unsigned long)cmd);
		} else
					keep_reply = reply->callback(card,
							reply,
			keep_reply = reply->callback(card, reply,
						     (unsigned long)iob);
	}
	if (cmd)
		reply->rc = (u16) cmd->hdr.return_code;
	else if (iob->rc)
		reply->rc = iob->rc;
			if (keep_reply) {
				spin_lock_irqsave(&card->lock, flags);
				list_add_tail(&reply->list,
					      &card->cmd_waiter_list);
				spin_unlock_irqrestore(&card->lock, flags);
			} else {
				atomic_inc(&reply->received);
				wake_up(&reply->wait_q);
			}

	if (!keep_reply)
		qeth_notify_reply(reply);
	qeth_put_reply(reply);
			goto out;
		}
	}
	spin_unlock_irqrestore(&card->lock, flags);

out:
	memcpy(&card->seqno.pdu_hdr_ack,
		QETH_PDU_HEADER_SEQ_NO(iob->data),
@@ -2047,8 +2061,6 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
	reply->callback = reply_cb;
	reply->param = reply_param;

	init_waitqueue_head(&reply->wait_q);

	while (atomic_cmpxchg(&channel->irq_pending, 0, 1)) ;

	if (IS_IPA(iob->data)) {
@@ -2062,9 +2074,7 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
	}
	qeth_prepare_control_data(card, len, iob);

	spin_lock_irq(&card->lock);
	list_add_tail(&reply->list, &card->cmd_waiter_list);
	spin_unlock_irq(&card->lock);
	qeth_enqueue_reply(card, reply);

	timeout = jiffies + event_timeout;

@@ -2077,10 +2087,8 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
		QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
				 CARD_DEVID(card), rc);
		QETH_CARD_TEXT_(card, 2, " err%d", rc);
		spin_lock_irq(&card->lock);
		list_del_init(&reply->list);
		qeth_dequeue_reply(card, reply);
		qeth_put_reply(reply);
		spin_unlock_irq(&card->lock);
		qeth_release_buffer(channel, iob);
		atomic_set(&channel->irq_pending, 0);
		wake_up(&card->wait_q);
@@ -2102,19 +2110,15 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
		}
	}

	qeth_dequeue_reply(card, reply);
	rc = reply->rc;
	qeth_put_reply(reply);
	return rc;

time_err:
	reply->rc = -ETIME;
	spin_lock_irq(&card->lock);
	list_del_init(&reply->list);
	spin_unlock_irq(&card->lock);
	atomic_inc(&reply->received);
	rc = reply->rc;
	qeth_dequeue_reply(card, reply);
	qeth_put_reply(reply);
	return rc;
	return -ETIME;
}

static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,