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

Commit 9c4eaabd authored by Thomas Falcon's avatar Thomas Falcon Committed by David S. Miller
Browse files

ibmvnic: Check CRQ command return codes



Check whether CRQ command is successful before awaiting a response
from the management partition. If the command was not successful, the
driver may hang waiting for a response 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 5153698e
Loading
Loading
Loading
Loading
+37 −14
Original line number Original line Diff line number Diff line
@@ -109,8 +109,8 @@ static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
					struct ibmvnic_sub_crq_queue *);
					struct ibmvnic_sub_crq_queue *);
static int ibmvnic_poll(struct napi_struct *napi, int data);
static int ibmvnic_poll(struct napi_struct *napi, int data);
static void send_map_query(struct ibmvnic_adapter *adapter);
static void send_map_query(struct ibmvnic_adapter *adapter);
static void send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
static void send_request_unmap(struct ibmvnic_adapter *, u8);
static int send_request_unmap(struct ibmvnic_adapter *, u8);
static int send_login(struct ibmvnic_adapter *adapter);
static int send_login(struct ibmvnic_adapter *adapter);
static void send_cap_queries(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_crqs(struct ibmvnic_adapter *);
@@ -172,6 +172,7 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
				struct ibmvnic_long_term_buff *ltb, int size)
				struct ibmvnic_long_term_buff *ltb, int size)
{
{
	struct device *dev = &adapter->vdev->dev;
	struct device *dev = &adapter->vdev->dev;
	int rc;


	ltb->size = size;
	ltb->size = size;
	ltb->buff = dma_alloc_coherent(dev, ltb->size, &ltb->addr,
	ltb->buff = dma_alloc_coherent(dev, ltb->size, &ltb->addr,
@@ -185,8 +186,12 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
	adapter->map_id++;
	adapter->map_id++;


	init_completion(&adapter->fw_done);
	init_completion(&adapter->fw_done);
	send_request_map(adapter, ltb->addr,
	rc = send_request_map(adapter, ltb->addr,
			      ltb->size, ltb->map_id);
			      ltb->size, ltb->map_id);
	if (rc) {
		dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
		return rc;
	}
	wait_for_completion(&adapter->fw_done);
	wait_for_completion(&adapter->fw_done);


	if (adapter->fw_done_rc) {
	if (adapter->fw_done_rc) {
@@ -215,10 +220,14 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
				struct ibmvnic_long_term_buff *ltb)
				struct ibmvnic_long_term_buff *ltb)
{
{
	int rc;

	memset(ltb->buff, 0, ltb->size);
	memset(ltb->buff, 0, ltb->size);


	init_completion(&adapter->fw_done);
	init_completion(&adapter->fw_done);
	send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
	rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
	if (rc)
		return rc;
	wait_for_completion(&adapter->fw_done);
	wait_for_completion(&adapter->fw_done);


	if (adapter->fw_done_rc) {
	if (adapter->fw_done_rc) {
@@ -952,6 +961,7 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
	struct device *dev = &adapter->vdev->dev;
	struct device *dev = &adapter->vdev->dev;
	union ibmvnic_crq crq;
	union ibmvnic_crq crq;
	int len = 0;
	int len = 0;
	int rc;


	if (adapter->vpd->buff)
	if (adapter->vpd->buff)
		len = adapter->vpd->len;
		len = adapter->vpd->len;
@@ -959,7 +969,9 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
	init_completion(&adapter->fw_done);
	init_completion(&adapter->fw_done);
	crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
	crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
	crq.get_vpd_size.cmd = GET_VPD_SIZE;
	crq.get_vpd_size.cmd = GET_VPD_SIZE;
	ibmvnic_send_crq(adapter, &crq);
	rc = ibmvnic_send_crq(adapter, &crq);
	if (rc)
		return rc;
	wait_for_completion(&adapter->fw_done);
	wait_for_completion(&adapter->fw_done);


	if (!adapter->vpd->len)
	if (!adapter->vpd->len)
@@ -992,7 +1004,12 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
	crq.get_vpd.cmd = GET_VPD;
	crq.get_vpd.cmd = GET_VPD;
	crq.get_vpd.ioba = cpu_to_be32(adapter->vpd->dma_addr);
	crq.get_vpd.ioba = cpu_to_be32(adapter->vpd->dma_addr);
	crq.get_vpd.len = cpu_to_be32((u32)adapter->vpd->len);
	crq.get_vpd.len = cpu_to_be32((u32)adapter->vpd->len);
	ibmvnic_send_crq(adapter, &crq);
	rc = ibmvnic_send_crq(adapter, &crq);
	if (rc) {
		kfree(adapter->vpd->buff);
		adapter->vpd->buff = NULL;
		return rc;
	}
	wait_for_completion(&adapter->fw_done);
	wait_for_completion(&adapter->fw_done);


	return 0;
	return 0;
@@ -1691,6 +1708,7 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p)
	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
	struct sockaddr *addr = p;
	struct sockaddr *addr = p;
	union ibmvnic_crq crq;
	union ibmvnic_crq crq;
	int rc;


	if (!is_valid_ether_addr(addr->sa_data))
	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;
		return -EADDRNOTAVAIL;
@@ -1701,7 +1719,9 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p)
	ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);
	ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);


	init_completion(&adapter->fw_done);
	init_completion(&adapter->fw_done);
	ibmvnic_send_crq(adapter, &crq);
	rc = ibmvnic_send_crq(adapter, &crq);
	if (rc)
		return rc;
	wait_for_completion(&adapter->fw_done);
	wait_for_completion(&adapter->fw_done);
	/* netdev->dev_addr is changed in handle_change_mac_rsp function */
	/* netdev->dev_addr is changed in handle_change_mac_rsp function */
	return adapter->fw_done_rc ? -EIO : 0;
	return adapter->fw_done_rc ? -EIO : 0;
@@ -2365,6 +2385,7 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
	struct ibmvnic_adapter *adapter = netdev_priv(dev);
	struct ibmvnic_adapter *adapter = netdev_priv(dev);
	union ibmvnic_crq crq;
	union ibmvnic_crq crq;
	int i, j;
	int i, j;
	int rc;


	memset(&crq, 0, sizeof(crq));
	memset(&crq, 0, sizeof(crq));
	crq.request_statistics.first = IBMVNIC_CRQ_CMD;
	crq.request_statistics.first = IBMVNIC_CRQ_CMD;
@@ -2375,7 +2396,9 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,


	/* Wait for data to be written */
	/* Wait for data to be written */
	init_completion(&adapter->stats_done);
	init_completion(&adapter->stats_done);
	ibmvnic_send_crq(adapter, &crq);
	rc = ibmvnic_send_crq(adapter, &crq);
	if (rc)
		return;
	wait_for_completion(&adapter->stats_done);
	wait_for_completion(&adapter->stats_done);


	for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
	for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
@@ -3377,7 +3400,7 @@ static int send_login(struct ibmvnic_adapter *adapter)
	return -1;
	return -1;
}
}


static void send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
static int send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
			    u32 len, u8 map_id)
			    u32 len, u8 map_id)
{
{
	union ibmvnic_crq crq;
	union ibmvnic_crq crq;
@@ -3388,10 +3411,10 @@ static void send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
	crq.request_map.map_id = map_id;
	crq.request_map.map_id = map_id;
	crq.request_map.ioba = cpu_to_be32(addr);
	crq.request_map.ioba = cpu_to_be32(addr);
	crq.request_map.len = cpu_to_be32(len);
	crq.request_map.len = cpu_to_be32(len);
	ibmvnic_send_crq(adapter, &crq);
	return ibmvnic_send_crq(adapter, &crq);
}
}


static void send_request_unmap(struct ibmvnic_adapter *adapter, u8 map_id)
static int send_request_unmap(struct ibmvnic_adapter *adapter, u8 map_id)
{
{
	union ibmvnic_crq crq;
	union ibmvnic_crq crq;


@@ -3399,7 +3422,7 @@ static void send_request_unmap(struct ibmvnic_adapter *adapter, u8 map_id)
	crq.request_unmap.first = IBMVNIC_CRQ_CMD;
	crq.request_unmap.first = IBMVNIC_CRQ_CMD;
	crq.request_unmap.cmd = REQUEST_UNMAP;
	crq.request_unmap.cmd = REQUEST_UNMAP;
	crq.request_unmap.map_id = map_id;
	crq.request_unmap.map_id = map_id;
	ibmvnic_send_crq(adapter, &crq);
	return ibmvnic_send_crq(adapter, &crq);
}
}


static void send_map_query(struct ibmvnic_adapter *adapter)
static void send_map_query(struct ibmvnic_adapter *adapter)