Commit ae16bf15 authored by Sukadev Bhattiprolu's avatar Sukadev Bhattiprolu Committed by David S. Miller
Browse files

ibmvnic: init init_done_rc earlier



We currently initialize the ->init_done completion/return code fields
before issuing a CRQ_INIT command. But if we get a transport event soon
after registering the CRQ the taskslet may already have recorded the
completion and error code. If we initialize here, we might overwrite/
lose that and end up issuing the CRQ_INIT only to timeout later.

If that timeout happens during probe, we will leave the adapter in the
DOWN state rather than retrying to register/init the CRQ.

Initialize the completion before registering the CRQ so we don't lose
the notification.

Fixes: 032c5e82 ("Driver for IBM System i/p VNIC protocol")
Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 570425f8
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -2212,6 +2212,19 @@ static const char *reset_reason_to_string(enum ibmvnic_reset_reason reason)
	return "UNKNOWN";
}

/*
 * Initialize the init_done completion and return code values. We
 * can get a transport event just after registering the CRQ and the
 * tasklet will use this to communicate the transport event. To ensure
 * we don't miss the notification/error, initialize these _before_
 * regisering the CRQ.
 */
static inline void reinit_init_done(struct ibmvnic_adapter *adapter)
{
	reinit_completion(&adapter->init_done);
	adapter->init_done_rc = 0;
}

/*
 * do_reset returns zero if we are able to keep processing reset events, or
 * non-zero if we hit a fatal error and must halt.
@@ -2318,6 +2331,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
		 */
		adapter->state = VNIC_PROBED;

		reinit_init_done(adapter);

		if (adapter->reset_reason == VNIC_RESET_CHANGE_PARAM) {
			rc = init_crq_queue(adapter);
		} else if (adapter->reset_reason == VNIC_RESET_MOBILITY) {
@@ -2461,7 +2476,8 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
	 */
	adapter->state = VNIC_PROBED;

	reinit_completion(&adapter->init_done);
	reinit_init_done(adapter);

	rc = init_crq_queue(adapter);
	if (rc) {
		netdev_err(adapter->netdev,
@@ -5679,10 +5695,6 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)

	adapter->from_passive_init = false;

	if (reset)
		reinit_completion(&adapter->init_done);

	adapter->init_done_rc = 0;
	rc = ibmvnic_send_crq_init(adapter);
	if (rc) {
		dev_err(dev, "Send crq init failed with error %d\n", rc);
@@ -5696,12 +5708,14 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)

	if (adapter->init_done_rc) {
		release_crq_queue(adapter);
		dev_err(dev, "CRQ-init failed, %d\n", adapter->init_done_rc);
		return adapter->init_done_rc;
	}

	if (adapter->from_passive_init) {
		adapter->state = VNIC_OPEN;
		adapter->from_passive_init = false;
		dev_err(dev, "CRQ-init failed, passive-init\n");
		return -EINVAL;
	}

@@ -5795,6 +5809,8 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)

	init_success = false;
	do {
		reinit_init_done(adapter);

		rc = init_crq_queue(adapter);
		if (rc) {
			dev_err(&dev->dev, "Couldn't initialize crq. rc=%d\n",