be2net: remove BUG_ON() when be2net runs out of mccq wrbs
The driver can run out of mccq wrbs when completions don't arrive
due to an unresponsive card. This must not hit a BUG_ON(); instead
log a msg and return an error.
Signed-off-by: Sathya Perla <sathyap@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 2af87f1..8bd5315 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -349,7 +349,11 @@
struct be_queue_info *mccq = &adapter->mcc_obj.q;
struct be_mcc_wrb *wrb;
- BUG_ON(atomic_read(&mccq->used) >= mccq->len);
+ if (atomic_read(&mccq->used) >= mccq->len) {
+ dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
+ return NULL;
+ }
+
wrb = queue_head_node(mccq);
queue_head_inc(mccq);
atomic_inc(&mccq->used);
@@ -499,6 +503,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -515,6 +523,7 @@
*pmac_id = le32_to_cpu(resp->pmac_id);
}
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -529,6 +538,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -541,8 +554,8 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
-
return status;
}
@@ -861,10 +874,15 @@
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_stats *req;
struct be_sge *sge;
+ int status = 0;
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = nonemb_cmd->va;
sge = nonembedded_sgl(wrb);
@@ -879,8 +897,9 @@
be_mcc_notify(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
- return 0;
+ return status;
}
/* Uses synchronous mcc */
@@ -894,6 +913,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
*link_up = false;
@@ -913,6 +936,7 @@
}
}
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -951,10 +975,15 @@
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_modify_eq_delay *req;
+ int status = 0;
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -969,8 +998,9 @@
be_mcc_notify(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
- return 0;
+ return status;
}
/* Uses sycnhronous mcc */
@@ -984,6 +1014,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1002,6 +1036,7 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1018,6 +1053,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1032,6 +1071,7 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1052,6 +1092,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
sge = nonembedded_sgl(wrb);
memset(req, 0, sizeof(*req));
@@ -1078,6 +1122,7 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1092,6 +1137,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1104,6 +1153,7 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1118,6 +1168,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1133,6 +1187,7 @@
*rx_fc = le16_to_cpu(resp->rx_flow_control);
}
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1199,6 +1254,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1213,6 +1272,7 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1227,6 +1287,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1243,6 +1307,7 @@
*state = resp->beacon_state;
}
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1258,6 +1323,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(struct be_cmd_resp_port_type), true, 0);
@@ -1273,6 +1342,7 @@
*connector = resp->data.connector;
}
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1288,6 +1358,11 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = cmd->va;
sge = nonembedded_sgl(wrb);
be_wrb_hdr_prepare(wrb, cmd->size, false, 1);
@@ -1304,6 +1379,7 @@
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1317,6 +1393,10 @@
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req)+4, true, 0);
@@ -1333,6 +1413,7 @@
if (!status)
memcpy(flashed_crc, req->params.data_buf, 4);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}