diff options
author | Denis Bolotin <denis.bolotin@cavium.com> | 2018-11-08 09:46:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-11-08 22:38:19 -0500 |
commit | fb5e7438e7a3c8966e04ccb0760170e9e06f3699 (patch) | |
tree | 11d41b49089637ac6161d5b9d4e145300d24d7df | |
parent | 2632f22ebd08da249c2017962a199a0cfb2324bf (diff) |
qed: Fix SPQ entries not returned to pool in error flows
qed_sp_destroy_request() API was added for SPQ users that need to
free/return the entry they acquired in their error flows.
Signed-off-by: Denis Bolotin <denis.bolotin@cavium.com>
Signed-off-by: Michal Kalderon <michal.kalderon@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_fcoe.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_iscsi.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_l2.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_rdma.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_roce.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_sp.h | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_sp_commands.c | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_sriov.c | 1 |
8 files changed, 45 insertions, 15 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c index cc1b373c0ace..46dc93d3b9b5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c +++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c | |||
@@ -147,7 +147,8 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn, | |||
147 | "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n", | 147 | "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n", |
148 | fcoe_pf_params->num_cqs, | 148 | fcoe_pf_params->num_cqs, |
149 | p_hwfn->hw_info.feat_num[QED_FCOE_CQ]); | 149 | p_hwfn->hw_info.feat_num[QED_FCOE_CQ]); |
150 | return -EINVAL; | 150 | rc = -EINVAL; |
151 | goto err; | ||
151 | } | 152 | } |
152 | 153 | ||
153 | p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu); | 154 | p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu); |
@@ -156,14 +157,14 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn, | |||
156 | 157 | ||
157 | rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid); | 158 | rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid); |
158 | if (rc) | 159 | if (rc) |
159 | return rc; | 160 | goto err; |
160 | 161 | ||
161 | cxt_info.iid = dummy_cid; | 162 | cxt_info.iid = dummy_cid; |
162 | rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info); | 163 | rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info); |
163 | if (rc) { | 164 | if (rc) { |
164 | DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n", | 165 | DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n", |
165 | dummy_cid); | 166 | dummy_cid); |
166 | return rc; | 167 | goto err; |
167 | } | 168 | } |
168 | p_cxt = cxt_info.p_cxt; | 169 | p_cxt = cxt_info.p_cxt; |
169 | SET_FIELD(p_cxt->tstorm_ag_context.flags3, | 170 | SET_FIELD(p_cxt->tstorm_ag_context.flags3, |
@@ -240,6 +241,10 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn, | |||
240 | rc = qed_spq_post(p_hwfn, p_ent, NULL); | 241 | rc = qed_spq_post(p_hwfn, p_ent, NULL); |
241 | 242 | ||
242 | return rc; | 243 | return rc; |
244 | |||
245 | err: | ||
246 | qed_sp_destroy_request(p_hwfn, p_ent); | ||
247 | return rc; | ||
243 | } | 248 | } |
244 | 249 | ||
245 | static int | 250 | static int |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c index 1135387bd99d..4f8a685d1a55 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c | |||
@@ -200,6 +200,7 @@ qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn, | |||
200 | "Cannot satisfy CQ amount. Queues requested %d, CQs available %d. Aborting function start\n", | 200 | "Cannot satisfy CQ amount. Queues requested %d, CQs available %d. Aborting function start\n", |
201 | p_params->num_queues, | 201 | p_params->num_queues, |
202 | p_hwfn->hw_info.feat_num[QED_ISCSI_CQ]); | 202 | p_hwfn->hw_info.feat_num[QED_ISCSI_CQ]); |
203 | qed_sp_destroy_request(p_hwfn, p_ent); | ||
203 | return -EINVAL; | 204 | return -EINVAL; |
204 | } | 205 | } |
205 | 206 | ||
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 82a1bd1f8a8c..67c02ea93906 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c | |||
@@ -740,8 +740,7 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn, | |||
740 | 740 | ||
741 | rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params); | 741 | rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params); |
742 | if (rc) { | 742 | if (rc) { |
743 | /* Return spq entry which is taken in qed_sp_init_request()*/ | 743 | qed_sp_destroy_request(p_hwfn, p_ent); |
744 | qed_spq_return_entry(p_hwfn, p_ent); | ||
745 | return rc; | 744 | return rc; |
746 | } | 745 | } |
747 | 746 | ||
@@ -1355,6 +1354,7 @@ qed_filter_ucast_common(struct qed_hwfn *p_hwfn, | |||
1355 | DP_NOTICE(p_hwfn, | 1354 | DP_NOTICE(p_hwfn, |
1356 | "%d is not supported yet\n", | 1355 | "%d is not supported yet\n", |
1357 | p_filter_cmd->opcode); | 1356 | p_filter_cmd->opcode); |
1357 | qed_sp_destroy_request(p_hwfn, *pp_ent); | ||
1358 | return -EINVAL; | 1358 | return -EINVAL; |
1359 | } | 1359 | } |
1360 | 1360 | ||
@@ -2056,13 +2056,13 @@ qed_configure_rfs_ntuple_filter(struct qed_hwfn *p_hwfn, | |||
2056 | } else { | 2056 | } else { |
2057 | rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); | 2057 | rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); |
2058 | if (rc) | 2058 | if (rc) |
2059 | return rc; | 2059 | goto err; |
2060 | 2060 | ||
2061 | if (p_params->qid != QED_RFS_NTUPLE_QID_RSS) { | 2061 | if (p_params->qid != QED_RFS_NTUPLE_QID_RSS) { |
2062 | rc = qed_fw_l2_queue(p_hwfn, p_params->qid, | 2062 | rc = qed_fw_l2_queue(p_hwfn, p_params->qid, |
2063 | &abs_rx_q_id); | 2063 | &abs_rx_q_id); |
2064 | if (rc) | 2064 | if (rc) |
2065 | return rc; | 2065 | goto err; |
2066 | 2066 | ||
2067 | p_ramrod->rx_qid_valid = 1; | 2067 | p_ramrod->rx_qid_valid = 1; |
2068 | p_ramrod->rx_qid = cpu_to_le16(abs_rx_q_id); | 2068 | p_ramrod->rx_qid = cpu_to_le16(abs_rx_q_id); |
@@ -2083,6 +2083,10 @@ qed_configure_rfs_ntuple_filter(struct qed_hwfn *p_hwfn, | |||
2083 | (u64)p_params->addr, p_params->length); | 2083 | (u64)p_params->addr, p_params->length); |
2084 | 2084 | ||
2085 | return qed_spq_post(p_hwfn, p_ent, NULL); | 2085 | return qed_spq_post(p_hwfn, p_ent, NULL); |
2086 | |||
2087 | err: | ||
2088 | qed_sp_destroy_request(p_hwfn, p_ent); | ||
2089 | return rc; | ||
2086 | } | 2090 | } |
2087 | 2091 | ||
2088 | int qed_get_rxq_coalesce(struct qed_hwfn *p_hwfn, | 2092 | int qed_get_rxq_coalesce(struct qed_hwfn *p_hwfn, |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c index c71391b9c757..62113438c880 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_rdma.c +++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.c | |||
@@ -1514,6 +1514,7 @@ qed_rdma_register_tid(void *rdma_cxt, | |||
1514 | default: | 1514 | default: |
1515 | rc = -EINVAL; | 1515 | rc = -EINVAL; |
1516 | DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "rc = %d\n", rc); | 1516 | DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "rc = %d\n", rc); |
1517 | qed_sp_destroy_request(p_hwfn, p_ent); | ||
1517 | return rc; | 1518 | return rc; |
1518 | } | 1519 | } |
1519 | SET_FIELD(p_ramrod->flags1, | 1520 | SET_FIELD(p_ramrod->flags1, |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c index f9167d1354bb..e49fada85410 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.c +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c | |||
@@ -745,6 +745,7 @@ static int qed_roce_sp_destroy_qp_responder(struct qed_hwfn *p_hwfn, | |||
745 | DP_NOTICE(p_hwfn, | 745 | DP_NOTICE(p_hwfn, |
746 | "qed destroy responder failed: cannot allocate memory (ramrod). rc = %d\n", | 746 | "qed destroy responder failed: cannot allocate memory (ramrod). rc = %d\n", |
747 | rc); | 747 | rc); |
748 | qed_sp_destroy_request(p_hwfn, p_ent); | ||
748 | return rc; | 749 | return rc; |
749 | } | 750 | } |
750 | 751 | ||
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index 04259df8a5c2..3157c0d99441 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h | |||
@@ -399,6 +399,17 @@ struct qed_sp_init_data { | |||
399 | struct qed_spq_comp_cb *p_comp_data; | 399 | struct qed_spq_comp_cb *p_comp_data; |
400 | }; | 400 | }; |
401 | 401 | ||
402 | /** | ||
403 | * @brief Returns a SPQ entry to the pool / frees the entry if allocated. | ||
404 | * Should be called on in error flows after initializing the SPQ entry | ||
405 | * and before posting it. | ||
406 | * | ||
407 | * @param p_hwfn | ||
408 | * @param p_ent | ||
409 | */ | ||
410 | void qed_sp_destroy_request(struct qed_hwfn *p_hwfn, | ||
411 | struct qed_spq_entry *p_ent); | ||
412 | |||
402 | int qed_sp_init_request(struct qed_hwfn *p_hwfn, | 413 | int qed_sp_init_request(struct qed_hwfn *p_hwfn, |
403 | struct qed_spq_entry **pp_ent, | 414 | struct qed_spq_entry **pp_ent, |
404 | u8 cmd, | 415 | u8 cmd, |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c index e86a1ea23613..888274fa208b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c | |||
@@ -47,6 +47,19 @@ | |||
47 | #include "qed_sp.h" | 47 | #include "qed_sp.h" |
48 | #include "qed_sriov.h" | 48 | #include "qed_sriov.h" |
49 | 49 | ||
50 | void qed_sp_destroy_request(struct qed_hwfn *p_hwfn, | ||
51 | struct qed_spq_entry *p_ent) | ||
52 | { | ||
53 | /* qed_spq_get_entry() can either get an entry from the free_pool, | ||
54 | * or, if no entries are left, allocate a new entry and add it to | ||
55 | * the unlimited_pending list. | ||
56 | */ | ||
57 | if (p_ent->queue == &p_hwfn->p_spq->unlimited_pending) | ||
58 | kfree(p_ent); | ||
59 | else | ||
60 | qed_spq_return_entry(p_hwfn, p_ent); | ||
61 | } | ||
62 | |||
50 | int qed_sp_init_request(struct qed_hwfn *p_hwfn, | 63 | int qed_sp_init_request(struct qed_hwfn *p_hwfn, |
51 | struct qed_spq_entry **pp_ent, | 64 | struct qed_spq_entry **pp_ent, |
52 | u8 cmd, u8 protocol, struct qed_sp_init_data *p_data) | 65 | u8 cmd, u8 protocol, struct qed_sp_init_data *p_data) |
@@ -111,14 +124,7 @@ int qed_sp_init_request(struct qed_hwfn *p_hwfn, | |||
111 | return 0; | 124 | return 0; |
112 | 125 | ||
113 | err: | 126 | err: |
114 | /* qed_spq_get_entry() can either get an entry from the free_pool, | 127 | qed_sp_destroy_request(p_hwfn, p_ent); |
115 | * or, if no entries are left, allocate a new entry and add it to | ||
116 | * the unlimited_pending list. | ||
117 | */ | ||
118 | if (p_ent->queue == &p_hwfn->p_spq->unlimited_pending) | ||
119 | kfree(p_ent); | ||
120 | else | ||
121 | qed_spq_return_entry(p_hwfn, p_ent); | ||
122 | 128 | ||
123 | return -EINVAL; | 129 | return -EINVAL; |
124 | } | 130 | } |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 9b08a9d9e151..ca6290fa0f30 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c | |||
@@ -101,6 +101,7 @@ static int qed_sp_vf_start(struct qed_hwfn *p_hwfn, struct qed_vf_info *p_vf) | |||
101 | default: | 101 | default: |
102 | DP_NOTICE(p_hwfn, "Unknown VF personality %d\n", | 102 | DP_NOTICE(p_hwfn, "Unknown VF personality %d\n", |
103 | p_hwfn->hw_info.personality); | 103 | p_hwfn->hw_info.personality); |
104 | qed_sp_destroy_request(p_hwfn, p_ent); | ||
104 | return -EINVAL; | 105 | return -EINVAL; |
105 | } | 106 | } |
106 | 107 | ||