Commit 095d3701 authored by David S. Miller's avatar David S. Miller

Merge branch 'ibmvnic-Fix-parameter-change-request-handling'

Nathan Fontenot says:

====================
ibmvnic: Fix parameter change request handling

When updating parameters for the ibmvnic driver there is a possibility
of entering an infinite loop if a return value other that a partial
success is received from sending the login CRQ.

Also, a deadlock can occur on the rtnl lock if netdev_notify_peers()
is called during driver reset for a parameter change reset.

This patch set corrects both of these issues by updating the return
code handling in ibmvnic_login() nand gaurding against calling
netdev_notify_peers() for parameter change requests.

Updates for V2: Correct spelling mistakes in commit messages.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7dd07c14 ebc701b7
...@@ -794,46 +794,61 @@ static int ibmvnic_login(struct net_device *netdev) ...@@ -794,46 +794,61 @@ static int ibmvnic_login(struct net_device *netdev)
{ {
struct ibmvnic_adapter *adapter = netdev_priv(netdev); struct ibmvnic_adapter *adapter = netdev_priv(netdev);
unsigned long timeout = msecs_to_jiffies(30000); unsigned long timeout = msecs_to_jiffies(30000);
struct device *dev = &adapter->vdev->dev; int retry_count = 0;
int rc; int rc;
do { do {
if (adapter->renegotiate) { if (retry_count > IBMVNIC_MAX_QUEUES) {
adapter->renegotiate = false; netdev_warn(netdev, "Login attempts exceeded\n");
return -1;
}
adapter->init_done_rc = 0;
reinit_completion(&adapter->init_done);
rc = send_login(adapter);
if (rc) {
netdev_warn(netdev, "Unable to login\n");
return rc;
}
if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) {
netdev_warn(netdev, "Login timed out\n");
return -1;
}
if (adapter->init_done_rc == PARTIALSUCCESS) {
retry_count++;
release_sub_crqs(adapter, 1); release_sub_crqs(adapter, 1);
adapter->init_done_rc = 0;
reinit_completion(&adapter->init_done); reinit_completion(&adapter->init_done);
send_cap_queries(adapter); send_cap_queries(adapter);
if (!wait_for_completion_timeout(&adapter->init_done, if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) { timeout)) {
dev_err(dev, "Capabilities query timeout\n"); netdev_warn(netdev,
"Capabilities query timed out\n");
return -1; return -1;
} }
rc = init_sub_crqs(adapter); rc = init_sub_crqs(adapter);
if (rc) { if (rc) {
dev_err(dev, netdev_warn(netdev,
"Initialization of SCRQ's failed\n"); "SCRQ initialization failed\n");
return -1; return -1;
} }
rc = init_sub_crq_irqs(adapter); rc = init_sub_crq_irqs(adapter);
if (rc) { if (rc) {
dev_err(dev, netdev_warn(netdev,
"Initialization of SCRQ's irqs failed\n"); "SCRQ irq initialization failed\n");
return -1; return -1;
} }
} } else if (adapter->init_done_rc) {
netdev_warn(netdev, "Adapter login failed\n");
reinit_completion(&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; return -1;
} }
} while (adapter->renegotiate); } while (adapter->init_done_rc == PARTIALSUCCESS);
/* handle pending MAC address changes after successful login */ /* handle pending MAC address changes after successful login */
if (adapter->mac_change_pending) { if (adapter->mac_change_pending) {
...@@ -1828,7 +1843,8 @@ static int do_reset(struct ibmvnic_adapter *adapter, ...@@ -1828,7 +1843,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
for (i = 0; i < adapter->req_rx_queues; i++) for (i = 0; i < adapter->req_rx_queues; i++)
napi_schedule(&adapter->napi[i]); napi_schedule(&adapter->napi[i]);
if (adapter->reset_reason != VNIC_RESET_FAILOVER) if (adapter->reset_reason != VNIC_RESET_FAILOVER &&
adapter->reset_reason != VNIC_RESET_CHANGE_PARAM)
netdev_notify_peers(netdev); netdev_notify_peers(netdev);
netif_carrier_on(netdev); netif_carrier_on(netdev);
...@@ -3942,7 +3958,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, ...@@ -3942,7 +3958,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
* to resend the login buffer with fewer queues requested. * to resend the login buffer with fewer queues requested.
*/ */
if (login_rsp_crq->generic.rc.code) { if (login_rsp_crq->generic.rc.code) {
adapter->renegotiate = true; adapter->init_done_rc = login_rsp_crq->generic.rc.code;
complete(&adapter->init_done); complete(&adapter->init_done);
return 0; return 0;
} }
......
...@@ -1035,7 +1035,6 @@ struct ibmvnic_adapter { ...@@ -1035,7 +1035,6 @@ struct ibmvnic_adapter {
struct ibmvnic_sub_crq_queue **tx_scrq; struct ibmvnic_sub_crq_queue **tx_scrq;
struct ibmvnic_sub_crq_queue **rx_scrq; struct ibmvnic_sub_crq_queue **rx_scrq;
bool renegotiate;
/* rx structs */ /* rx structs */
struct napi_struct *napi; struct napi_struct *napi;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment