|
|
@@ -23,6 +23,7 @@
|
|
|
#include <linux/workqueue.h>
|
|
|
#include <linux/bitops.h>
|
|
|
#include <linux/bug.h>
|
|
|
+#include <linux/vmalloc.h>
|
|
|
#include "qed.h"
|
|
|
#include <linux/qed/qed_chain.h>
|
|
|
#include "qed_cxt.h"
|
|
|
@@ -41,6 +42,124 @@
|
|
|
#define QED_MAX_SGES_NUM 16
|
|
|
#define CRC32_POLY 0x1edc6f41
|
|
|
|
|
|
+void qed_eth_queue_cid_release(struct qed_hwfn *p_hwfn,
|
|
|
+ struct qed_queue_cid *p_cid)
|
|
|
+{
|
|
|
+ /* VFs' CIDs are 0-based in PF-view, and uninitialized on VF */
|
|
|
+ if (!p_cid->is_vf && IS_PF(p_hwfn->cdev))
|
|
|
+ qed_cxt_release_cid(p_hwfn, p_cid->cid);
|
|
|
+ vfree(p_cid);
|
|
|
+}
|
|
|
+
|
|
|
+/* The internal is only meant to be directly called by PFs initializeing CIDs
|
|
|
+ * for their VFs.
|
|
|
+ */
|
|
|
+struct qed_queue_cid *
|
|
|
+_qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn,
|
|
|
+ u16 opaque_fid,
|
|
|
+ u32 cid,
|
|
|
+ u8 vf_qid,
|
|
|
+ struct qed_queue_start_common_params *p_params)
|
|
|
+{
|
|
|
+ bool b_is_same = (p_hwfn->hw_info.opaque_fid == opaque_fid);
|
|
|
+ struct qed_queue_cid *p_cid;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ p_cid = vmalloc(sizeof(*p_cid));
|
|
|
+ if (!p_cid)
|
|
|
+ return NULL;
|
|
|
+ memset(p_cid, 0, sizeof(*p_cid));
|
|
|
+
|
|
|
+ p_cid->opaque_fid = opaque_fid;
|
|
|
+ p_cid->cid = cid;
|
|
|
+ p_cid->vf_qid = vf_qid;
|
|
|
+ p_cid->rel = *p_params;
|
|
|
+
|
|
|
+ /* Don't try calculating the absolute indices for VFs */
|
|
|
+ if (IS_VF(p_hwfn->cdev)) {
|
|
|
+ p_cid->abs = p_cid->rel;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Calculate the engine-absolute indices of the resources.
|
|
|
+ * This would guarantee they're valid later on.
|
|
|
+ * In some cases [SBs] we already have the right values.
|
|
|
+ */
|
|
|
+ rc = qed_fw_vport(p_hwfn, p_cid->rel.vport_id, &p_cid->abs.vport_id);
|
|
|
+ if (rc)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
+ rc = qed_fw_l2_queue(p_hwfn, p_cid->rel.queue_id, &p_cid->abs.queue_id);
|
|
|
+ if (rc)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
+ /* In case of a PF configuring its VF's queues, the stats-id is already
|
|
|
+ * absolute [since there's a single index that's suitable per-VF].
|
|
|
+ */
|
|
|
+ if (b_is_same) {
|
|
|
+ rc = qed_fw_vport(p_hwfn, p_cid->rel.stats_id,
|
|
|
+ &p_cid->abs.stats_id);
|
|
|
+ if (rc)
|
|
|
+ goto fail;
|
|
|
+ } else {
|
|
|
+ p_cid->abs.stats_id = p_cid->rel.stats_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* SBs relevant information was already provided as absolute */
|
|
|
+ p_cid->abs.sb = p_cid->rel.sb;
|
|
|
+ p_cid->abs.sb_idx = p_cid->rel.sb_idx;
|
|
|
+
|
|
|
+ /* This is tricky - we're actually interested in whehter this is a PF
|
|
|
+ * entry meant for the VF.
|
|
|
+ */
|
|
|
+ if (!b_is_same)
|
|
|
+ p_cid->is_vf = true;
|
|
|
+out:
|
|
|
+ DP_VERBOSE(p_hwfn,
|
|
|
+ QED_MSG_SP,
|
|
|
+ "opaque_fid: %04x CID %08x vport %02x [%02x] qzone %04x [%04x] stats %02x [%02x] SB %04x PI %02x\n",
|
|
|
+ p_cid->opaque_fid,
|
|
|
+ p_cid->cid,
|
|
|
+ p_cid->rel.vport_id,
|
|
|
+ p_cid->abs.vport_id,
|
|
|
+ p_cid->rel.queue_id,
|
|
|
+ p_cid->abs.queue_id,
|
|
|
+ p_cid->rel.stats_id,
|
|
|
+ p_cid->abs.stats_id, p_cid->abs.sb, p_cid->abs.sb_idx);
|
|
|
+
|
|
|
+ return p_cid;
|
|
|
+
|
|
|
+fail:
|
|
|
+ vfree(p_cid);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static struct qed_queue_cid *qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn,
|
|
|
+ u16 opaque_fid, struct
|
|
|
+ qed_queue_start_common_params
|
|
|
+ *p_params)
|
|
|
+{
|
|
|
+ struct qed_queue_cid *p_cid;
|
|
|
+ u32 cid = 0;
|
|
|
+
|
|
|
+ /* Get a unique firmware CID for this queue, in case it's a PF.
|
|
|
+ * VF's don't need a CID as the queue configuration will be done
|
|
|
+ * by PF.
|
|
|
+ */
|
|
|
+ if (IS_PF(p_hwfn->cdev)) {
|
|
|
+ if (qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, &cid)) {
|
|
|
+ DP_NOTICE(p_hwfn, "Failed to acquire cid\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ p_cid = _qed_eth_queue_to_cid(p_hwfn, opaque_fid, cid, 0, p_params);
|
|
|
+ if (!p_cid && IS_PF(p_hwfn->cdev))
|
|
|
+ qed_cxt_release_cid(p_hwfn, cid);
|
|
|
+
|
|
|
+ return p_cid;
|
|
|
+}
|
|
|
+
|
|
|
int qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn,
|
|
|
struct qed_sp_vport_start_params *p_params)
|
|
|
{
|
|
|
@@ -496,61 +615,26 @@ static int qed_filter_accept_cmd(struct qed_dev *cdev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int qed_sp_release_queue_cid(
|
|
|
- struct qed_hwfn *p_hwfn,
|
|
|
- struct qed_hw_cid_data *p_cid_data)
|
|
|
-{
|
|
|
- if (!p_cid_data->b_cid_allocated)
|
|
|
- return 0;
|
|
|
-
|
|
|
- qed_cxt_release_cid(p_hwfn, p_cid_data->cid);
|
|
|
-
|
|
|
- p_cid_data->b_cid_allocated = false;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-int qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
- u16 opaque_fid,
|
|
|
- u32 cid,
|
|
|
- struct qed_queue_start_common_params *p_params,
|
|
|
- u8 stats_id,
|
|
|
- u16 bd_max_bytes,
|
|
|
- dma_addr_t bd_chain_phys_addr,
|
|
|
- dma_addr_t cqe_pbl_addr,
|
|
|
- u16 cqe_pbl_size, bool b_use_zone_a_prod)
|
|
|
+int qed_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
+ struct qed_queue_cid *p_cid,
|
|
|
+ u16 bd_max_bytes,
|
|
|
+ dma_addr_t bd_chain_phys_addr,
|
|
|
+ dma_addr_t cqe_pbl_addr, u16 cqe_pbl_size)
|
|
|
{
|
|
|
struct rx_queue_start_ramrod_data *p_ramrod = NULL;
|
|
|
struct qed_spq_entry *p_ent = NULL;
|
|
|
struct qed_sp_init_data init_data;
|
|
|
- struct qed_hw_cid_data *p_rx_cid;
|
|
|
- u16 abs_rx_q_id = 0;
|
|
|
- u8 abs_vport_id = 0;
|
|
|
int rc = -EINVAL;
|
|
|
|
|
|
- /* Store information for the stop */
|
|
|
- p_rx_cid = &p_hwfn->p_rx_cids[p_params->queue_id];
|
|
|
- p_rx_cid->cid = cid;
|
|
|
- p_rx_cid->opaque_fid = opaque_fid;
|
|
|
- p_rx_cid->vport_id = p_params->vport_id;
|
|
|
-
|
|
|
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
-
|
|
|
- rc = qed_fw_l2_queue(p_hwfn, p_params->queue_id, &abs_rx_q_id);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
-
|
|
|
DP_VERBOSE(p_hwfn, QED_MSG_SP,
|
|
|
- "opaque_fid=0x%x, cid=0x%x, rx_qid=0x%x, vport_id=0x%x, sb_id=0x%x\n",
|
|
|
- opaque_fid,
|
|
|
- cid, p_params->queue_id, p_params->vport_id, p_params->sb);
|
|
|
+ "opaque_fid=0x%x, cid=0x%x, rx_qzone=0x%x, vport_id=0x%x, sb_id=0x%x\n",
|
|
|
+ p_cid->opaque_fid, p_cid->cid,
|
|
|
+ p_cid->abs.queue_id, p_cid->abs.vport_id, p_cid->abs.sb);
|
|
|
|
|
|
/* Get SPQ entry */
|
|
|
memset(&init_data, 0, sizeof(init_data));
|
|
|
- init_data.cid = cid;
|
|
|
- init_data.opaque_fid = opaque_fid;
|
|
|
+ init_data.cid = p_cid->cid;
|
|
|
+ init_data.opaque_fid = p_cid->opaque_fid;
|
|
|
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
|
|
|
|
|
|
rc = qed_sp_init_request(p_hwfn, &p_ent,
|
|
|
@@ -561,11 +645,11 @@ int qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
|
|
|
p_ramrod = &p_ent->ramrod.rx_queue_start;
|
|
|
|
|
|
- p_ramrod->sb_id = cpu_to_le16(p_params->sb);
|
|
|
- p_ramrod->sb_index = p_params->sb_idx;
|
|
|
- p_ramrod->vport_id = abs_vport_id;
|
|
|
- p_ramrod->stats_counter_id = stats_id;
|
|
|
- p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id);
|
|
|
+ p_ramrod->sb_id = cpu_to_le16(p_cid->abs.sb);
|
|
|
+ p_ramrod->sb_index = p_cid->abs.sb_idx;
|
|
|
+ p_ramrod->vport_id = p_cid->abs.vport_id;
|
|
|
+ p_ramrod->stats_counter_id = p_cid->abs.stats_id;
|
|
|
+ p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id);
|
|
|
p_ramrod->complete_cqe_flg = 0;
|
|
|
p_ramrod->complete_event_flg = 1;
|
|
|
|
|
|
@@ -575,85 +659,85 @@ int qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size);
|
|
|
DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr, cqe_pbl_addr);
|
|
|
|
|
|
- if (p_params->vf_qid || b_use_zone_a_prod) {
|
|
|
- p_ramrod->vf_rx_prod_index = p_params->vf_qid;
|
|
|
+ if (p_cid->is_vf) {
|
|
|
+ p_ramrod->vf_rx_prod_index = p_cid->vf_qid;
|
|
|
DP_VERBOSE(p_hwfn, QED_MSG_SP,
|
|
|
"Queue%s is meant for VF rxq[%02x]\n",
|
|
|
- b_use_zone_a_prod ? " [legacy]" : "",
|
|
|
- p_params->vf_qid);
|
|
|
- p_ramrod->vf_rx_prod_use_zone_a = b_use_zone_a_prod;
|
|
|
+ !!p_cid->b_legacy_vf ? " [legacy]" : "",
|
|
|
+ p_cid->vf_qid);
|
|
|
+ p_ramrod->vf_rx_prod_use_zone_a = !!p_cid->b_legacy_vf;
|
|
|
}
|
|
|
|
|
|
return qed_spq_post(p_hwfn, p_ent, NULL);
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-qed_sp_eth_rx_queue_start(struct qed_hwfn *p_hwfn,
|
|
|
- u16 opaque_fid,
|
|
|
- struct qed_queue_start_common_params *p_params,
|
|
|
+qed_eth_pf_rx_queue_start(struct qed_hwfn *p_hwfn,
|
|
|
+ struct qed_queue_cid *p_cid,
|
|
|
u16 bd_max_bytes,
|
|
|
dma_addr_t bd_chain_phys_addr,
|
|
|
dma_addr_t cqe_pbl_addr,
|
|
|
u16 cqe_pbl_size, void __iomem **pp_prod)
|
|
|
{
|
|
|
- struct qed_hw_cid_data *p_rx_cid;
|
|
|
u32 init_prod_val = 0;
|
|
|
- u16 abs_l2_queue = 0;
|
|
|
- u8 abs_stats_id = 0;
|
|
|
- int rc;
|
|
|
|
|
|
- if (IS_VF(p_hwfn->cdev)) {
|
|
|
- return qed_vf_pf_rxq_start(p_hwfn,
|
|
|
- p_params->queue_id,
|
|
|
- p_params->sb,
|
|
|
- (u8)p_params->sb_idx,
|
|
|
- bd_max_bytes,
|
|
|
- bd_chain_phys_addr,
|
|
|
- cqe_pbl_addr, cqe_pbl_size, pp_prod);
|
|
|
- }
|
|
|
-
|
|
|
- rc = qed_fw_l2_queue(p_hwfn, p_params->queue_id, &abs_l2_queue);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
-
|
|
|
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_stats_id);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
-
|
|
|
- *pp_prod = (u8 __iomem *)p_hwfn->regview +
|
|
|
- GTT_BAR0_MAP_REG_MSDM_RAM +
|
|
|
- MSTORM_ETH_PF_PRODS_OFFSET(abs_l2_queue);
|
|
|
+ *pp_prod = p_hwfn->regview +
|
|
|
+ GTT_BAR0_MAP_REG_MSDM_RAM +
|
|
|
+ MSTORM_ETH_PF_PRODS_OFFSET(p_cid->abs.queue_id);
|
|
|
|
|
|
/* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
|
|
|
__internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
|
|
|
(u32 *)(&init_prod_val));
|
|
|
|
|
|
+ return qed_eth_rxq_start_ramrod(p_hwfn, p_cid,
|
|
|
+ bd_max_bytes,
|
|
|
+ bd_chain_phys_addr,
|
|
|
+ cqe_pbl_addr, cqe_pbl_size);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+qed_eth_rx_queue_start(struct qed_hwfn *p_hwfn,
|
|
|
+ u16 opaque_fid,
|
|
|
+ struct qed_queue_start_common_params *p_params,
|
|
|
+ u16 bd_max_bytes,
|
|
|
+ dma_addr_t bd_chain_phys_addr,
|
|
|
+ dma_addr_t cqe_pbl_addr,
|
|
|
+ u16 cqe_pbl_size,
|
|
|
+ struct qed_rxq_start_ret_params *p_ret_params)
|
|
|
+{
|
|
|
+ struct qed_queue_cid *p_cid;
|
|
|
+ int rc;
|
|
|
+
|
|
|
/* Allocate a CID for the queue */
|
|
|
- p_rx_cid = &p_hwfn->p_rx_cids[p_params->queue_id];
|
|
|
- rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, &p_rx_cid->cid);
|
|
|
- if (rc) {
|
|
|
- DP_NOTICE(p_hwfn, "Failed to acquire cid\n");
|
|
|
- return rc;
|
|
|
- }
|
|
|
- p_rx_cid->b_cid_allocated = true;
|
|
|
+ p_cid = qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params);
|
|
|
+ if (!p_cid)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- rc = qed_sp_eth_rxq_start_ramrod(p_hwfn,
|
|
|
- opaque_fid,
|
|
|
- p_rx_cid->cid,
|
|
|
- p_params,
|
|
|
- abs_stats_id,
|
|
|
+ if (IS_PF(p_hwfn->cdev)) {
|
|
|
+ rc = qed_eth_pf_rx_queue_start(p_hwfn, p_cid,
|
|
|
+ bd_max_bytes,
|
|
|
+ bd_chain_phys_addr,
|
|
|
+ cqe_pbl_addr, cqe_pbl_size,
|
|
|
+ &p_ret_params->p_prod);
|
|
|
+ } else {
|
|
|
+ rc = qed_vf_pf_rxq_start(p_hwfn, p_cid,
|
|
|
bd_max_bytes,
|
|
|
bd_chain_phys_addr,
|
|
|
- cqe_pbl_addr, cqe_pbl_size, false);
|
|
|
+ cqe_pbl_addr,
|
|
|
+ cqe_pbl_size, &p_ret_params->p_prod);
|
|
|
+ }
|
|
|
|
|
|
+ /* Provide the caller with a reference to as handler */
|
|
|
if (rc)
|
|
|
- qed_sp_release_queue_cid(p_hwfn, p_rx_cid);
|
|
|
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
|
|
|
+ else
|
|
|
+ p_ret_params->p_handle = (void *)p_cid;
|
|
|
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
|
|
|
- u16 rx_queue_id,
|
|
|
+ void **pp_rxq_handles,
|
|
|
u8 num_rxqs,
|
|
|
u8 complete_cqe_flg,
|
|
|
u8 complete_event_flg,
|
|
|
@@ -663,8 +747,7 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
|
|
|
struct rx_queue_update_ramrod_data *p_ramrod = NULL;
|
|
|
struct qed_spq_entry *p_ent = NULL;
|
|
|
struct qed_sp_init_data init_data;
|
|
|
- struct qed_hw_cid_data *p_rx_cid;
|
|
|
- u16 qid, abs_rx_q_id = 0;
|
|
|
+ struct qed_queue_cid *p_cid;
|
|
|
int rc = -EINVAL;
|
|
|
u8 i;
|
|
|
|
|
|
@@ -673,12 +756,11 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
|
|
|
init_data.p_comp_data = p_comp_data;
|
|
|
|
|
|
for (i = 0; i < num_rxqs; i++) {
|
|
|
- qid = rx_queue_id + i;
|
|
|
- p_rx_cid = &p_hwfn->p_rx_cids[qid];
|
|
|
+ p_cid = ((struct qed_queue_cid **)pp_rxq_handles)[i];
|
|
|
|
|
|
/* Get SPQ entry */
|
|
|
- init_data.cid = p_rx_cid->cid;
|
|
|
- init_data.opaque_fid = p_rx_cid->opaque_fid;
|
|
|
+ init_data.cid = p_cid->cid;
|
|
|
+ init_data.opaque_fid = p_cid->opaque_fid;
|
|
|
|
|
|
rc = qed_sp_init_request(p_hwfn, &p_ent,
|
|
|
ETH_RAMROD_RX_QUEUE_UPDATE,
|
|
|
@@ -687,10 +769,9 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
|
|
|
return rc;
|
|
|
|
|
|
p_ramrod = &p_ent->ramrod.rx_queue_update;
|
|
|
+ p_ramrod->vport_id = p_cid->abs.vport_id;
|
|
|
|
|
|
- qed_fw_vport(p_hwfn, p_rx_cid->vport_id, &p_ramrod->vport_id);
|
|
|
- qed_fw_l2_queue(p_hwfn, qid, &abs_rx_q_id);
|
|
|
- p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id);
|
|
|
+ p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id);
|
|
|
p_ramrod->complete_cqe_flg = complete_cqe_flg;
|
|
|
p_ramrod->complete_event_flg = complete_event_flg;
|
|
|
|
|
|
@@ -702,24 +783,19 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
|
|
|
- u16 rx_queue_id,
|
|
|
- bool eq_completion_only, bool cqe_completion)
|
|
|
+static int
|
|
|
+qed_eth_pf_rx_queue_stop(struct qed_hwfn *p_hwfn,
|
|
|
+ struct qed_queue_cid *p_cid,
|
|
|
+ bool b_eq_completion_only, bool b_cqe_completion)
|
|
|
{
|
|
|
- struct qed_hw_cid_data *p_rx_cid = &p_hwfn->p_rx_cids[rx_queue_id];
|
|
|
struct rx_queue_stop_ramrod_data *p_ramrod = NULL;
|
|
|
struct qed_spq_entry *p_ent = NULL;
|
|
|
struct qed_sp_init_data init_data;
|
|
|
- u16 abs_rx_q_id = 0;
|
|
|
- int rc = -EINVAL;
|
|
|
-
|
|
|
- if (IS_VF(p_hwfn->cdev))
|
|
|
- return qed_vf_pf_rxq_stop(p_hwfn, rx_queue_id, cqe_completion);
|
|
|
+ int rc;
|
|
|
|
|
|
- /* Get SPQ entry */
|
|
|
memset(&init_data, 0, sizeof(init_data));
|
|
|
- init_data.cid = p_rx_cid->cid;
|
|
|
- init_data.opaque_fid = p_rx_cid->opaque_fid;
|
|
|
+ init_data.cid = p_cid->cid;
|
|
|
+ init_data.opaque_fid = p_cid->opaque_fid;
|
|
|
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
|
|
|
|
|
|
rc = qed_sp_init_request(p_hwfn, &p_ent,
|
|
|
@@ -729,62 +805,53 @@ int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
|
|
|
return rc;
|
|
|
|
|
|
p_ramrod = &p_ent->ramrod.rx_queue_stop;
|
|
|
-
|
|
|
- qed_fw_vport(p_hwfn, p_rx_cid->vport_id, &p_ramrod->vport_id);
|
|
|
- qed_fw_l2_queue(p_hwfn, rx_queue_id, &abs_rx_q_id);
|
|
|
- p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id);
|
|
|
+ p_ramrod->vport_id = p_cid->abs.vport_id;
|
|
|
+ p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id);
|
|
|
|
|
|
/* Cleaning the queue requires the completion to arrive there.
|
|
|
* In addition, VFs require the answer to come as eqe to PF.
|
|
|
*/
|
|
|
- p_ramrod->complete_cqe_flg =
|
|
|
- (!!(p_rx_cid->opaque_fid == p_hwfn->hw_info.opaque_fid) &&
|
|
|
- !eq_completion_only) || cqe_completion;
|
|
|
- p_ramrod->complete_event_flg =
|
|
|
- !(p_rx_cid->opaque_fid == p_hwfn->hw_info.opaque_fid) ||
|
|
|
- eq_completion_only;
|
|
|
+ p_ramrod->complete_cqe_flg = (!p_cid->is_vf &&
|
|
|
+ !b_eq_completion_only) ||
|
|
|
+ b_cqe_completion;
|
|
|
+ p_ramrod->complete_event_flg = p_cid->is_vf || b_eq_completion_only;
|
|
|
|
|
|
- rc = qed_spq_post(p_hwfn, p_ent, NULL);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
+ return qed_spq_post(p_hwfn, p_ent, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+int qed_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
|
|
|
+ void *p_rxq,
|
|
|
+ bool eq_completion_only, bool cqe_completion)
|
|
|
+{
|
|
|
+ struct qed_queue_cid *p_cid = (struct qed_queue_cid *)p_rxq;
|
|
|
+ int rc = -EINVAL;
|
|
|
|
|
|
- return qed_sp_release_queue_cid(p_hwfn, p_rx_cid);
|
|
|
+ if (IS_PF(p_hwfn->cdev))
|
|
|
+ rc = qed_eth_pf_rx_queue_stop(p_hwfn, p_cid,
|
|
|
+ eq_completion_only,
|
|
|
+ cqe_completion);
|
|
|
+ else
|
|
|
+ rc = qed_vf_pf_rxq_stop(p_hwfn, p_cid, cqe_completion);
|
|
|
+
|
|
|
+ if (!rc)
|
|
|
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
|
|
|
+ return rc;
|
|
|
}
|
|
|
|
|
|
-int qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
- u16 opaque_fid,
|
|
|
- u32 cid,
|
|
|
- struct qed_queue_start_common_params *p_params,
|
|
|
- u8 stats_id,
|
|
|
- dma_addr_t pbl_addr,
|
|
|
- u16 pbl_size,
|
|
|
- union qed_qm_pq_params *p_pq_params)
|
|
|
+int
|
|
|
+qed_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
+ struct qed_queue_cid *p_cid,
|
|
|
+ dma_addr_t pbl_addr, u16 pbl_size, u16 pq_id)
|
|
|
{
|
|
|
struct tx_queue_start_ramrod_data *p_ramrod = NULL;
|
|
|
struct qed_spq_entry *p_ent = NULL;
|
|
|
struct qed_sp_init_data init_data;
|
|
|
- struct qed_hw_cid_data *p_tx_cid;
|
|
|
- u16 pq_id, abs_tx_q_id = 0;
|
|
|
int rc = -EINVAL;
|
|
|
- u8 abs_vport_id;
|
|
|
-
|
|
|
- /* Store information for the stop */
|
|
|
- p_tx_cid = &p_hwfn->p_tx_cids[p_params->queue_id];
|
|
|
- p_tx_cid->cid = cid;
|
|
|
- p_tx_cid->opaque_fid = opaque_fid;
|
|
|
-
|
|
|
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
-
|
|
|
- rc = qed_fw_l2_queue(p_hwfn, p_params->queue_id, &abs_tx_q_id);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
|
|
|
/* Get SPQ entry */
|
|
|
memset(&init_data, 0, sizeof(init_data));
|
|
|
- init_data.cid = cid;
|
|
|
- init_data.opaque_fid = opaque_fid;
|
|
|
+ init_data.cid = p_cid->cid;
|
|
|
+ init_data.opaque_fid = p_cid->opaque_fid;
|
|
|
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
|
|
|
|
|
|
rc = qed_sp_init_request(p_hwfn, &p_ent,
|
|
|
@@ -794,96 +861,92 @@ int qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
|
|
|
return rc;
|
|
|
|
|
|
p_ramrod = &p_ent->ramrod.tx_queue_start;
|
|
|
- p_ramrod->vport_id = abs_vport_id;
|
|
|
+ p_ramrod->vport_id = p_cid->abs.vport_id;
|
|
|
|
|
|
- p_ramrod->sb_id = cpu_to_le16(p_params->sb);
|
|
|
- p_ramrod->sb_index = p_params->sb_idx;
|
|
|
- p_ramrod->stats_counter_id = stats_id;
|
|
|
+ p_ramrod->sb_id = cpu_to_le16(p_cid->abs.sb);
|
|
|
+ p_ramrod->sb_index = p_cid->abs.sb_idx;
|
|
|
+ p_ramrod->stats_counter_id = p_cid->abs.stats_id;
|
|
|
|
|
|
- p_ramrod->queue_zone_id = cpu_to_le16(abs_tx_q_id);
|
|
|
+ p_ramrod->queue_zone_id = cpu_to_le16(p_cid->abs.queue_id);
|
|
|
+ p_ramrod->same_as_last_id = cpu_to_le16(p_cid->abs.queue_id);
|
|
|
|
|
|
p_ramrod->pbl_size = cpu_to_le16(pbl_size);
|
|
|
DMA_REGPAIR_LE(p_ramrod->pbl_base_addr, pbl_addr);
|
|
|
|
|
|
- pq_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_ETH, p_pq_params);
|
|
|
p_ramrod->qm_pq_id = cpu_to_le16(pq_id);
|
|
|
|
|
|
return qed_spq_post(p_hwfn, p_ent, NULL);
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-qed_sp_eth_tx_queue_start(struct qed_hwfn *p_hwfn,
|
|
|
- u16 opaque_fid,
|
|
|
- struct qed_queue_start_common_params *p_params,
|
|
|
+qed_eth_pf_tx_queue_start(struct qed_hwfn *p_hwfn,
|
|
|
+ struct qed_queue_cid *p_cid,
|
|
|
+ u8 tc,
|
|
|
dma_addr_t pbl_addr,
|
|
|
u16 pbl_size, void __iomem **pp_doorbell)
|
|
|
{
|
|
|
- struct qed_hw_cid_data *p_tx_cid;
|
|
|
union qed_qm_pq_params pq_params;
|
|
|
- u8 abs_stats_id = 0;
|
|
|
int rc;
|
|
|
|
|
|
- if (IS_VF(p_hwfn->cdev)) {
|
|
|
- return qed_vf_pf_txq_start(p_hwfn,
|
|
|
- p_params->queue_id,
|
|
|
- p_params->sb,
|
|
|
- p_params->sb_idx,
|
|
|
- pbl_addr, pbl_size, pp_doorbell);
|
|
|
- }
|
|
|
+ memset(&pq_params, 0, sizeof(pq_params));
|
|
|
|
|
|
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_stats_id);
|
|
|
+ rc = qed_eth_txq_start_ramrod(p_hwfn, p_cid,
|
|
|
+ pbl_addr, pbl_size,
|
|
|
+ qed_get_qm_pq(p_hwfn, PROTOCOLID_ETH,
|
|
|
+ &pq_params));
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- p_tx_cid = &p_hwfn->p_tx_cids[p_params->queue_id];
|
|
|
- memset(p_tx_cid, 0, sizeof(*p_tx_cid));
|
|
|
- memset(&pq_params, 0, sizeof(pq_params));
|
|
|
+ /* Provide the caller with the necessary return values */
|
|
|
+ *pp_doorbell = p_hwfn->doorbells +
|
|
|
+ qed_db_addr(p_cid->cid, DQ_DEMS_LEGACY);
|
|
|
|
|
|
- /* Allocate a CID for the queue */
|
|
|
- rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, &p_tx_cid->cid);
|
|
|
- if (rc) {
|
|
|
- DP_NOTICE(p_hwfn, "Failed to acquire cid\n");
|
|
|
- return rc;
|
|
|
- }
|
|
|
- p_tx_cid->b_cid_allocated = true;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
- DP_VERBOSE(p_hwfn, QED_MSG_SP,
|
|
|
- "opaque_fid=0x%x, cid=0x%x, tx_qid=0x%x, vport_id=0x%x, sb_id=0x%x\n",
|
|
|
- opaque_fid, p_tx_cid->cid,
|
|
|
- p_params->queue_id, p_params->vport_id, p_params->sb);
|
|
|
-
|
|
|
- rc = qed_sp_eth_txq_start_ramrod(p_hwfn,
|
|
|
- opaque_fid,
|
|
|
- p_tx_cid->cid,
|
|
|
- p_params,
|
|
|
- abs_stats_id,
|
|
|
- pbl_addr,
|
|
|
- pbl_size,
|
|
|
- &pq_params);
|
|
|
-
|
|
|
- *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
|
|
|
- qed_db_addr(p_tx_cid->cid, DQ_DEMS_LEGACY);
|
|
|
+static int
|
|
|
+qed_eth_tx_queue_start(struct qed_hwfn *p_hwfn,
|
|
|
+ u16 opaque_fid,
|
|
|
+ struct qed_queue_start_common_params *p_params,
|
|
|
+ u8 tc,
|
|
|
+ dma_addr_t pbl_addr,
|
|
|
+ u16 pbl_size,
|
|
|
+ struct qed_txq_start_ret_params *p_ret_params)
|
|
|
+{
|
|
|
+ struct qed_queue_cid *p_cid;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ p_cid = qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params);
|
|
|
+ if (!p_cid)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (IS_PF(p_hwfn->cdev))
|
|
|
+ rc = qed_eth_pf_tx_queue_start(p_hwfn, p_cid, tc,
|
|
|
+ pbl_addr, pbl_size,
|
|
|
+ &p_ret_params->p_doorbell);
|
|
|
+ else
|
|
|
+ rc = qed_vf_pf_txq_start(p_hwfn, p_cid,
|
|
|
+ pbl_addr, pbl_size,
|
|
|
+ &p_ret_params->p_doorbell);
|
|
|
|
|
|
if (rc)
|
|
|
- qed_sp_release_queue_cid(p_hwfn, p_tx_cid);
|
|
|
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
|
|
|
+ else
|
|
|
+ p_ret_params->p_handle = (void *)p_cid;
|
|
|
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, u16 tx_queue_id)
|
|
|
+static int
|
|
|
+qed_eth_pf_tx_queue_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid)
|
|
|
{
|
|
|
- struct qed_hw_cid_data *p_tx_cid = &p_hwfn->p_tx_cids[tx_queue_id];
|
|
|
struct qed_spq_entry *p_ent = NULL;
|
|
|
struct qed_sp_init_data init_data;
|
|
|
- int rc = -EINVAL;
|
|
|
-
|
|
|
- if (IS_VF(p_hwfn->cdev))
|
|
|
- return qed_vf_pf_txq_stop(p_hwfn, tx_queue_id);
|
|
|
+ int rc;
|
|
|
|
|
|
- /* Get SPQ entry */
|
|
|
memset(&init_data, 0, sizeof(init_data));
|
|
|
- init_data.cid = p_tx_cid->cid;
|
|
|
- init_data.opaque_fid = p_tx_cid->opaque_fid;
|
|
|
+ init_data.cid = p_cid->cid;
|
|
|
+ init_data.opaque_fid = p_cid->opaque_fid;
|
|
|
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
|
|
|
|
|
|
rc = qed_sp_init_request(p_hwfn, &p_ent,
|
|
|
@@ -892,11 +955,22 @@ int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, u16 tx_queue_id)
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- rc = qed_spq_post(p_hwfn, p_ent, NULL);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
+ return qed_spq_post(p_hwfn, p_ent, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+int qed_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, void *p_handle)
|
|
|
+{
|
|
|
+ struct qed_queue_cid *p_cid = (struct qed_queue_cid *)p_handle;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (IS_PF(p_hwfn->cdev))
|
|
|
+ rc = qed_eth_pf_tx_queue_stop(p_hwfn, p_cid);
|
|
|
+ else
|
|
|
+ rc = qed_vf_pf_txq_stop(p_hwfn, p_cid);
|
|
|
|
|
|
- return qed_sp_release_queue_cid(p_hwfn, p_tx_cid);
|
|
|
+ if (!rc)
|
|
|
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
|
|
|
+ return rc;
|
|
|
}
|
|
|
|
|
|
static enum eth_filter_action qed_filter_action(enum qed_filter_opcode opcode)
|
|
|
@@ -1880,58 +1954,53 @@ static int qed_update_vport(struct qed_dev *cdev,
|
|
|
}
|
|
|
|
|
|
static int qed_start_rxq(struct qed_dev *cdev,
|
|
|
- struct qed_queue_start_common_params *params,
|
|
|
+ u8 rss_num,
|
|
|
+ struct qed_queue_start_common_params *p_params,
|
|
|
u16 bd_max_bytes,
|
|
|
dma_addr_t bd_chain_phys_addr,
|
|
|
dma_addr_t cqe_pbl_addr,
|
|
|
u16 cqe_pbl_size,
|
|
|
- void __iomem **pp_prod)
|
|
|
+ struct qed_rxq_start_ret_params *ret_params)
|
|
|
{
|
|
|
struct qed_hwfn *p_hwfn;
|
|
|
int rc, hwfn_index;
|
|
|
|
|
|
- hwfn_index = params->rss_id % cdev->num_hwfns;
|
|
|
+ hwfn_index = rss_num % cdev->num_hwfns;
|
|
|
p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
|
|
|
- /* Fix queue ID in 100g mode */
|
|
|
- params->queue_id /= cdev->num_hwfns;
|
|
|
-
|
|
|
- rc = qed_sp_eth_rx_queue_start(p_hwfn,
|
|
|
- p_hwfn->hw_info.opaque_fid,
|
|
|
- params,
|
|
|
- bd_max_bytes,
|
|
|
- bd_chain_phys_addr,
|
|
|
- cqe_pbl_addr,
|
|
|
- cqe_pbl_size,
|
|
|
- pp_prod);
|
|
|
+ p_params->queue_id = p_params->queue_id / cdev->num_hwfns;
|
|
|
+ p_params->stats_id = p_params->vport_id;
|
|
|
|
|
|
+ rc = qed_eth_rx_queue_start(p_hwfn,
|
|
|
+ p_hwfn->hw_info.opaque_fid,
|
|
|
+ p_params,
|
|
|
+ bd_max_bytes,
|
|
|
+ bd_chain_phys_addr,
|
|
|
+ cqe_pbl_addr, cqe_pbl_size, ret_params);
|
|
|
if (rc) {
|
|
|
- DP_ERR(cdev, "Failed to start RXQ#%d\n", params->queue_id);
|
|
|
+ DP_ERR(cdev, "Failed to start RXQ#%d\n", p_params->queue_id);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
|
|
|
- "Started RX-Q %d [rss %d] on V-PORT %d and SB %d\n",
|
|
|
- params->queue_id, params->rss_id, params->vport_id,
|
|
|
- params->sb);
|
|
|
+ "Started RX-Q %d [rss_num %d] on V-PORT %d and SB %d\n",
|
|
|
+ p_params->queue_id, rss_num, p_params->vport_id,
|
|
|
+ p_params->sb);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int qed_stop_rxq(struct qed_dev *cdev,
|
|
|
- struct qed_stop_rxq_params *params)
|
|
|
+static int qed_stop_rxq(struct qed_dev *cdev, u8 rss_id, void *handle)
|
|
|
{
|
|
|
int rc, hwfn_index;
|
|
|
struct qed_hwfn *p_hwfn;
|
|
|
|
|
|
- hwfn_index = params->rss_id % cdev->num_hwfns;
|
|
|
- p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
+ hwfn_index = rss_id % cdev->num_hwfns;
|
|
|
+ p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
|
|
|
- rc = qed_sp_eth_rx_queue_stop(p_hwfn,
|
|
|
- params->rx_queue_id / cdev->num_hwfns,
|
|
|
- params->eq_completion_only, false);
|
|
|
+ rc = qed_eth_rx_queue_stop(p_hwfn, handle, false, false);
|
|
|
if (rc) {
|
|
|
- DP_ERR(cdev, "Failed to stop RXQ#%d\n", params->rx_queue_id);
|
|
|
+ DP_ERR(cdev, "Failed to stop RXQ#%02x\n", rss_id);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
@@ -1939,26 +2008,24 @@ static int qed_stop_rxq(struct qed_dev *cdev,
|
|
|
}
|
|
|
|
|
|
static int qed_start_txq(struct qed_dev *cdev,
|
|
|
+ u8 rss_num,
|
|
|
struct qed_queue_start_common_params *p_params,
|
|
|
dma_addr_t pbl_addr,
|
|
|
u16 pbl_size,
|
|
|
- void __iomem **pp_doorbell)
|
|
|
+ struct qed_txq_start_ret_params *ret_params)
|
|
|
{
|
|
|
struct qed_hwfn *p_hwfn;
|
|
|
int rc, hwfn_index;
|
|
|
|
|
|
- hwfn_index = p_params->rss_id % cdev->num_hwfns;
|
|
|
- p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
-
|
|
|
- /* Fix queue ID in 100g mode */
|
|
|
- p_params->queue_id /= cdev->num_hwfns;
|
|
|
+ hwfn_index = rss_num % cdev->num_hwfns;
|
|
|
+ p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
+ p_params->queue_id = p_params->queue_id / cdev->num_hwfns;
|
|
|
+ p_params->stats_id = p_params->vport_id;
|
|
|
|
|
|
- rc = qed_sp_eth_tx_queue_start(p_hwfn,
|
|
|
- p_hwfn->hw_info.opaque_fid,
|
|
|
- p_params,
|
|
|
- pbl_addr,
|
|
|
- pbl_size,
|
|
|
- pp_doorbell);
|
|
|
+ rc = qed_eth_tx_queue_start(p_hwfn,
|
|
|
+ p_hwfn->hw_info.opaque_fid,
|
|
|
+ p_params, 0,
|
|
|
+ pbl_addr, pbl_size, ret_params);
|
|
|
|
|
|
if (rc) {
|
|
|
DP_ERR(cdev, "Failed to start TXQ#%d\n", p_params->queue_id);
|
|
|
@@ -1966,8 +2033,8 @@ static int qed_start_txq(struct qed_dev *cdev,
|
|
|
}
|
|
|
|
|
|
DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
|
|
|
- "Started TX-Q %d [rss %d] on V-PORT %d and SB %d\n",
|
|
|
- p_params->queue_id, p_params->rss_id, p_params->vport_id,
|
|
|
+ "Started TX-Q %d [rss_num %d] on V-PORT %d and SB %d\n",
|
|
|
+ p_params->queue_id, rss_num, p_params->vport_id,
|
|
|
p_params->sb);
|
|
|
|
|
|
return 0;
|
|
|
@@ -1981,19 +2048,17 @@ static int qed_fastpath_stop(struct qed_dev *cdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int qed_stop_txq(struct qed_dev *cdev,
|
|
|
- struct qed_stop_txq_params *params)
|
|
|
+static int qed_stop_txq(struct qed_dev *cdev, u8 rss_id, void *handle)
|
|
|
{
|
|
|
struct qed_hwfn *p_hwfn;
|
|
|
int rc, hwfn_index;
|
|
|
|
|
|
- hwfn_index = params->rss_id % cdev->num_hwfns;
|
|
|
- p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
+ hwfn_index = rss_id % cdev->num_hwfns;
|
|
|
+ p_hwfn = &cdev->hwfns[hwfn_index];
|
|
|
|
|
|
- rc = qed_sp_eth_tx_queue_stop(p_hwfn,
|
|
|
- params->tx_queue_id / cdev->num_hwfns);
|
|
|
+ rc = qed_eth_tx_queue_stop(p_hwfn, handle);
|
|
|
if (rc) {
|
|
|
- DP_ERR(cdev, "Failed to stop TXQ#%d\n", params->tx_queue_id);
|
|
|
+ DP_ERR(cdev, "Failed to stop TXQ#%02x\n", rss_id);
|
|
|
return rc;
|
|
|
}
|
|
|
|