summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2017-04-21 15:39:04 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-24 12:52:13 -0400
commit53da09e92910f675ebb93921007428a3c2a024fb (patch)
tree3ad8d76980d3d1c95b4f257bfa3b0500a3f7048c /drivers
parent5d5e84eb7276d30a21257515a83b34d1ef77f99b (diff)
ibmvnic: Add set_link_state routine for setting adapter link state
Create a common routine for setting the link state for the vnic adapter. This update moves the sending of the crq and waiting for the link state response to a common place. The new routine also adds handling of resending the crq in cases of getting a partial success response. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c71
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.h1
2 files changed, 58 insertions, 14 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 199cccbb577a..115f21694994 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -561,6 +561,51 @@ static void release_resources(struct ibmvnic_adapter *adapter)
release_error_buffers(adapter);
}
+static int set_link_state(struct ibmvnic_adapter *adapter, u8 link_state)
+{
+ struct net_device *netdev = adapter->netdev;
+ unsigned long timeout = msecs_to_jiffies(30000);
+ union ibmvnic_crq crq;
+ bool resend;
+ int rc;
+
+ if (adapter->logical_link_state == link_state) {
+ netdev_dbg(netdev, "Link state already %d\n", link_state);
+ return 0;
+ }
+
+ netdev_err(netdev, "setting link state %d\n", link_state);
+ memset(&crq, 0, sizeof(crq));
+ crq.logical_link_state.first = IBMVNIC_CRQ_CMD;
+ crq.logical_link_state.cmd = LOGICAL_LINK_STATE;
+ crq.logical_link_state.link_state = link_state;
+
+ do {
+ resend = false;
+
+ reinit_completion(&adapter->init_done);
+ rc = ibmvnic_send_crq(adapter, &crq);
+ if (rc) {
+ netdev_err(netdev, "Failed to set link state\n");
+ return rc;
+ }
+
+ if (!wait_for_completion_timeout(&adapter->init_done,
+ timeout)) {
+ netdev_err(netdev, "timeout setting link state\n");
+ return -1;
+ }
+
+ if (adapter->init_done_rc == 1) {
+ /* Partuial success, delay and re-send */
+ mdelay(1000);
+ resend = true;
+ }
+ } while (resend);
+
+ return 0;
+}
+
static int set_real_num_queues(struct net_device *netdev)
{
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
@@ -583,7 +628,6 @@ static int ibmvnic_open(struct net_device *netdev)
{
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
struct device *dev = &adapter->vdev->dev;
- union ibmvnic_crq crq;
int rc = 0;
int i;
@@ -643,11 +687,9 @@ static int ibmvnic_open(struct net_device *netdev)
for (i = 0; i < adapter->req_tx_queues; i++)
enable_scrq_irq(adapter, adapter->tx_scrq[i]);
- memset(&crq, 0, sizeof(crq));
- crq.logical_link_state.first = IBMVNIC_CRQ_CMD;
- crq.logical_link_state.cmd = LOGICAL_LINK_STATE;
- crq.logical_link_state.link_state = IBMVNIC_LOGICAL_LNK_UP;
- ibmvnic_send_crq(adapter, &crq);
+ rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
+ if (rc)
+ goto ibmvnic_open_fail;
netif_tx_start_all_queues(netdev);
adapter->is_closed = false;
@@ -681,7 +723,7 @@ static void disable_sub_crqs(struct ibmvnic_adapter *adapter)
static int ibmvnic_close(struct net_device *netdev)
{
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
- union ibmvnic_crq crq;
+ int rc = 0;
int i;
adapter->closing = true;
@@ -693,17 +735,13 @@ static int ibmvnic_close(struct net_device *netdev)
if (!adapter->failover)
netif_tx_stop_all_queues(netdev);
- memset(&crq, 0, sizeof(crq));
- crq.logical_link_state.first = IBMVNIC_CRQ_CMD;
- crq.logical_link_state.cmd = LOGICAL_LINK_STATE;
- crq.logical_link_state.link_state = IBMVNIC_LOGICAL_LNK_DN;
- ibmvnic_send_crq(adapter, &crq);
+ rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN);
release_resources(adapter);
adapter->is_closed = true;
adapter->closing = false;
- return 0;
+ return rc;
}
/**
@@ -2945,9 +2983,14 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
handle_login_rsp(crq, adapter);
break;
case LOGICAL_LINK_STATE_RSP:
- netdev_dbg(netdev, "Got Logical Link State Response\n");
+ netdev_dbg(netdev,
+ "Got Logical Link State Response, state: %d rc: %d\n",
+ crq->logical_link_state_rsp.link_state,
+ crq->logical_link_state_rsp.rc.code);
adapter->logical_link_state =
crq->logical_link_state_rsp.link_state;
+ adapter->init_done_rc = crq->logical_link_state_rsp.rc.code;
+ complete(&adapter->init_done);
break;
case LINK_STATE_INDICATION:
netdev_dbg(netdev, "Got Logical Link State Indication\n");
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
index 387c84303b7f..a69979f6f19d 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h
@@ -964,6 +964,7 @@ struct ibmvnic_adapter {
struct ibmvnic_tx_pool *tx_pool;
bool closing;
struct completion init_done;
+ int init_done_rc;
struct list_head errors;
spinlock_t error_list_lock;