Skip to content

Commit

Permalink
ibmvnic: Serialize device queries
Browse files Browse the repository at this point in the history
Provide some serialization for device CRQ commands
and queries to ensure that the shared variable used for
storing return codes is properly synchronized.

Signed-off-by: Thomas Falcon <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
tlfalcon authored and davem330 committed Nov 26, 2019
1 parent 476d96c commit ff25dcb
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
54 changes: 49 additions & 5 deletions drivers/net/ethernet/ibm/ibmvnic.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,14 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
ltb->map_id = adapter->map_id;
adapter->map_id++;

mutex_lock(&adapter->fw_lock);
adapter->fw_done_rc = 0;
reinit_completion(&adapter->fw_done);
rc = send_request_map(adapter, ltb->addr,
ltb->size, ltb->map_id);
if (rc) {
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
mutex_unlock(&adapter->fw_lock);
return rc;
}

Expand All @@ -224,15 +227,18 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
"Long term map request aborted or timed out,rc = %d\n",
rc);
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
mutex_unlock(&adapter->fw_lock);
return rc;
}

if (adapter->fw_done_rc) {
dev_err(dev, "Couldn't map long term buffer,rc = %d\n",
adapter->fw_done_rc);
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
mutex_unlock(&adapter->fw_lock);
return -1;
}
mutex_unlock(&adapter->fw_lock);
return 0;
}

Expand All @@ -258,24 +264,32 @@ static int reset_long_term_buff(struct ibmvnic_adapter *adapter,

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

mutex_lock(&adapter->fw_lock);
adapter->fw_done_rc = 0;

reinit_completion(&adapter->fw_done);
rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
if (rc)
if (rc) {
mutex_unlock(&adapter->fw_lock);
return rc;
}

rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
if (rc) {
dev_info(dev,
"Reset failed, long term map request timed out or aborted\n");
mutex_unlock(&adapter->fw_lock);
return rc;
}

if (adapter->fw_done_rc) {
dev_info(dev,
"Reset failed, attempting to free and reallocate buffer\n");
free_long_term_buff(adapter, ltb);
mutex_unlock(&adapter->fw_lock);
return alloc_long_term_buff(adapter, ltb, ltb->size);
}
mutex_unlock(&adapter->fw_lock);
return 0;
}

Expand Down Expand Up @@ -992,18 +1006,25 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
if (adapter->vpd->buff)
len = adapter->vpd->len;

mutex_lock(&adapter->fw_lock);
adapter->fw_done_rc = 0;
reinit_completion(&adapter->fw_done);

crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
crq.get_vpd_size.cmd = GET_VPD_SIZE;
rc = ibmvnic_send_crq(adapter, &crq);
if (rc)
if (rc) {
mutex_unlock(&adapter->fw_lock);
return rc;
}

rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
if (rc) {
dev_err(dev, "Could not retrieve VPD size, rc = %d\n", rc);
mutex_unlock(&adapter->fw_lock);
return rc;
}
mutex_unlock(&adapter->fw_lock);

if (!adapter->vpd->len)
return -ENODATA;
Expand All @@ -1030,7 +1051,10 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
return -ENOMEM;
}

mutex_lock(&adapter->fw_lock);
adapter->fw_done_rc = 0;
reinit_completion(&adapter->fw_done);

crq.get_vpd.first = IBMVNIC_CRQ_CMD;
crq.get_vpd.cmd = GET_VPD;
crq.get_vpd.ioba = cpu_to_be32(adapter->vpd->dma_addr);
Expand All @@ -1039,6 +1063,7 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
if (rc) {
kfree(adapter->vpd->buff);
adapter->vpd->buff = NULL;
mutex_unlock(&adapter->fw_lock);
return rc;
}

Expand All @@ -1047,9 +1072,11 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
dev_err(dev, "Unable to retrieve VPD, rc = %d\n", rc);
kfree(adapter->vpd->buff);
adapter->vpd->buff = NULL;
mutex_unlock(&adapter->fw_lock);
return rc;
}

mutex_unlock(&adapter->fw_lock);
return 0;
}

Expand Down Expand Up @@ -1750,20 +1777,25 @@ static int __ibmvnic_set_mac(struct net_device *netdev, u8 *dev_addr)
crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;
ether_addr_copy(&crq.change_mac_addr.mac_addr[0], dev_addr);

mutex_lock(&adapter->fw_lock);
adapter->fw_done_rc = 0;
reinit_completion(&adapter->fw_done);

rc = ibmvnic_send_crq(adapter, &crq);
if (rc) {
rc = -EIO;
mutex_unlock(&adapter->fw_lock);
goto err;
}

rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
/* netdev->dev_addr is changed in handle_change_mac_rsp function */
if (rc || adapter->fw_done_rc) {
rc = -EIO;
mutex_unlock(&adapter->fw_lock);
goto err;
}

mutex_unlock(&adapter->fw_lock);
return 0;
err:
ether_addr_copy(adapter->mac_addr, netdev->dev_addr);
Expand Down Expand Up @@ -4486,15 +4518,24 @@ static int send_query_phys_parms(struct ibmvnic_adapter *adapter)
memset(&crq, 0, sizeof(crq));
crq.query_phys_parms.first = IBMVNIC_CRQ_CMD;
crq.query_phys_parms.cmd = QUERY_PHYS_PARMS;

mutex_lock(&adapter->fw_lock);
adapter->fw_done_rc = 0;
reinit_completion(&adapter->fw_done);

rc = ibmvnic_send_crq(adapter, &crq);
if (rc)
if (rc) {
mutex_unlock(&adapter->fw_lock);
return rc;
}

rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
if (rc)
if (rc) {
mutex_unlock(&adapter->fw_lock);
return rc;
}

mutex_unlock(&adapter->fw_lock);
return adapter->fw_done_rc ? -EIO : 0;
}

Expand Down Expand Up @@ -5050,6 +5091,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
__ibmvnic_delayed_reset);
INIT_LIST_HEAD(&adapter->rwi_list);
spin_lock_init(&adapter->rwi_lock);
mutex_init(&adapter->fw_lock);
init_completion(&adapter->init_done);
init_completion(&adapter->fw_done);
init_completion(&adapter->reset_done);
Expand Down Expand Up @@ -5111,6 +5153,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
ibmvnic_init_fail:
release_sub_crqs(adapter, 1);
release_crq_queue(adapter);
mutex_destroy(&adapter->fw_lock);
free_netdev(netdev);

return rc;
Expand All @@ -5135,6 +5178,7 @@ static int ibmvnic_remove(struct vio_dev *dev)
adapter->state = VNIC_REMOVED;

rtnl_unlock();
mutex_destroy(&adapter->fw_lock);
device_remove_file(&dev->dev, &dev_attr_failover);
free_netdev(netdev);
dev_set_drvdata(&dev->dev, NULL);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/ibm/ibmvnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,8 @@ struct ibmvnic_adapter {
int init_done_rc;

struct completion fw_done;
/* Used for serialization of device commands */
struct mutex fw_lock;
int fw_done_rc;

struct completion reset_done;
Expand Down

0 comments on commit ff25dcb

Please sign in to comment.