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

Commit 20a8ab74 authored by Thomas Falcon's avatar Thomas Falcon Committed by David S. Miller
Browse files

ibmvnic: Do not attempt to login if RX or TX queues are not allocated



If a device reset fails for some reason, TX and RX queue resources
could be released. If a user attempts to open the device in this scenario,
it may result in a kernel panic as the driver tries to access this
memory. To fix this, include a check before device login that TX/RX
queues are still there before enabling the device. In addition, return a
value that can be checked in case of any errors to avoid waiting for a
completion that will never come.

Signed-off-by: default avatarThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0aecb13c
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ static int ibmvnic_poll(struct napi_struct *napi, int data);
static void send_map_query(struct ibmvnic_adapter *adapter);
static void send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
static void send_request_unmap(struct ibmvnic_adapter *, u8);
static void send_login(struct ibmvnic_adapter *adapter);
static int send_login(struct ibmvnic_adapter *adapter);
static void send_cap_queries(struct ibmvnic_adapter *adapter);
static int init_sub_crqs(struct ibmvnic_adapter *);
static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter);
@@ -809,8 +809,11 @@ static int ibmvnic_login(struct net_device *netdev)
		}

		reinit_completion(&adapter->init_done);
		send_login(adapter);
		if (!wait_for_completion_timeout(&adapter->init_done,
		rc = send_login(adapter);
		if (rc) {
			dev_err(dev, "Unable to attempt device login\n");
			return rc;
		} else if (!wait_for_completion_timeout(&adapter->init_done,
						 timeout)) {
			dev_err(dev, "Login timeout\n");
			return -1;
@@ -3074,7 +3077,7 @@ static void vnic_add_client_data(struct ibmvnic_adapter *adapter,
	strncpy(&vlcd->name, adapter->netdev->name, len);
}

static void send_login(struct ibmvnic_adapter *adapter)
static int send_login(struct ibmvnic_adapter *adapter)
{
	struct ibmvnic_login_rsp_buffer *login_rsp_buffer;
	struct ibmvnic_login_buffer *login_buffer;
@@ -3090,6 +3093,12 @@ static void send_login(struct ibmvnic_adapter *adapter)
	struct vnic_login_client_data *vlcd;
	int i;

	if (!adapter->tx_scrq || !adapter->rx_scrq) {
		netdev_err(adapter->netdev,
			   "RX or TX queues are not allocated, device login failed\n");
		return -1;
	}

	release_login_rsp_buffer(adapter);
	client_data_len = vnic_client_data_len(adapter);

@@ -3187,7 +3196,7 @@ static void send_login(struct ibmvnic_adapter *adapter)
	crq.login.len = cpu_to_be32(buffer_size);
	ibmvnic_send_crq(adapter, &crq);

	return;
	return 0;

buf_rsp_map_failed:
	kfree(login_rsp_buffer);
@@ -3196,7 +3205,7 @@ static void send_login(struct ibmvnic_adapter *adapter)
buf_map_failed:
	kfree(login_buffer);
buf_alloc_failed:
	return;
	return -1;
}

static void send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,