diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 262b2ba13e793d783a930d5acb962d32ef295a02..150a8e9354b7c941f7c90ea1bdcb5fb4c307b355 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -155,7 +155,8 @@ 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)) + if ((p_cid->vfid == QED_QUEUE_CID_SELF) && + IS_PF(p_hwfn->cdev)) qed_cxt_release_cid(p_hwfn, p_cid->cid); vfree(p_cid); } @@ -163,14 +164,13 @@ void qed_eth_queue_cid_release(struct qed_hwfn *p_hwfn, /* The internal is only meant to be directly called by PFs initializeing CIDs * for their VFs. */ -struct qed_queue_cid * +static 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) + struct qed_queue_start_common_params *p_params, + struct qed_queue_cid_vf_params *p_vf_params) { - bool b_is_same = (p_hwfn->hw_info.opaque_fid == opaque_fid); struct qed_queue_cid *p_cid; int rc; @@ -181,7 +181,6 @@ _qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, p_cid->opaque_fid = opaque_fid; p_cid->cid = cid; - p_cid->vf_qid = vf_qid; p_cid->p_owner = p_hwfn; /* Fill in parameters */ @@ -191,6 +190,15 @@ _qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, p_cid->sb_igu_id = p_params->p_sb->igu_sb_id; p_cid->sb_idx = p_params->sb_idx; + /* Fill-in bits related to VFs' queues if information was provided */ + if (p_vf_params) { + p_cid->vfid = p_vf_params->vfid; + p_cid->vf_qid = p_vf_params->vf_qid; + p_cid->b_legacy_vf = p_vf_params->vf_legacy; + } else { + p_cid->vfid = QED_QUEUE_CID_SELF; + } + /* Don't try calculating the absolute indices for VFs */ if (IS_VF(p_hwfn->cdev)) { p_cid->abs = p_cid->rel; @@ -212,7 +220,7 @@ _qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, /* 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) { + if (p_cid->vfid == QED_QUEUE_CID_SELF) { rc = qed_fw_vport(p_hwfn, p_cid->rel.stats_id, &p_cid->abs.stats_id); if (rc) @@ -221,11 +229,6 @@ _qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, p_cid->abs.stats_id = p_cid->rel.stats_id; } - /* 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, @@ -246,32 +249,47 @@ _qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, 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 * +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_vf_params *p_vf_params) { struct qed_queue_cid *p_cid; + bool b_legacy_vf = false; u32 cid = 0; + /* Currently, PF doesn't need to allocate CIDs for any VF */ + if (p_vf_params) + b_legacy_vf = true; /* 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 (IS_PF(p_hwfn->cdev) && !b_legacy_vf) { 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)) + p_cid = _qed_eth_queue_to_cid(p_hwfn, opaque_fid, cid, + p_params, p_vf_params); + if (!p_cid && IS_PF(p_hwfn->cdev) && !b_legacy_vf) qed_cxt_release_cid(p_hwfn, cid); return p_cid; } +static struct qed_queue_cid * +qed_eth_queue_to_cid_pf(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + struct qed_queue_start_common_params *p_params) +{ + return qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params, + NULL); +} + int qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn, struct qed_sp_vport_start_params *p_params) { @@ -799,7 +817,7 @@ int qed_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_cid->is_vf) { + if (p_cid->vfid != QED_QUEUE_CID_SELF) { 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", @@ -849,7 +867,7 @@ qed_eth_rx_queue_start(struct qed_hwfn *p_hwfn, int rc; /* Allocate a CID for the queue */ - p_cid = qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params); + p_cid = qed_eth_queue_to_cid_pf(p_hwfn, opaque_fid, p_params); if (!p_cid) return -ENOMEM; @@ -951,10 +969,11 @@ qed_eth_pf_rx_queue_stop(struct qed_hwfn *p_hwfn, /* 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_cid->is_vf && + p_ramrod->complete_cqe_flg = ((p_cid->vfid == QED_QUEUE_CID_SELF) && !b_eq_completion_only) || b_cqe_completion; - p_ramrod->complete_event_flg = p_cid->is_vf || b_eq_completion_only; + p_ramrod->complete_event_flg = (p_cid->vfid != QED_QUEUE_CID_SELF) || + b_eq_completion_only; return qed_spq_post(p_hwfn, p_ent, NULL); } @@ -1053,7 +1072,7 @@ qed_eth_tx_queue_start(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid; int rc; - p_cid = qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params); + p_cid = qed_eth_queue_to_cid_pf(p_hwfn, opaque_fid, p_params); if (!p_cid) return -EINVAL; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h index 6ad36449dae97afbf858f5baa94a44a4e5e83d54..43aeaa8828289a500edf4aea1d12cae3f6b13561 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.h +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h @@ -278,6 +278,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats); void qed_reset_vport_stats(struct qed_dev *cdev); #define MAX_QUEUES_PER_QZONE (sizeof(unsigned long) * 8) +#define QED_QUEUE_CID_SELF (0xff) /* Almost identical to the qed_queue_start_common_params, * but here we maintain the SB index in IGU CAM. @@ -288,6 +289,25 @@ struct qed_queue_cid_params { u8 stats_id; }; +/* Additional parameters required for initialization of the queue_cid + * and are relevant only for a PF initializing one for its VFs. + */ +struct qed_queue_cid_vf_params { + /* Should match the VF's relative index */ + u8 vfid; + + /* 0-based queue index. Should reflect the relative qzone the + * VF thinks is associated with it [in its range]. + */ + u8 vf_qid; + + /* Indicates a VF is legacy, making it differ in: + * - Producers would be placed in a different place. + */ + bool vf_legacy; + +}; + struct qed_queue_cid { /* For stats-id, the `rel' is actually absolute as well */ struct qed_queue_cid_params rel; @@ -305,7 +325,7 @@ struct qed_queue_cid { * Notice this is relevant on the *PF* queue-cid of its VF's queues, * and not on the VF itself. */ - bool is_vf; + u8 vfid; u8 vf_qid; /* Legacy VFs might have Rx producer located elsewhere */ @@ -321,12 +341,11 @@ void qed_l2_free(struct qed_hwfn *p_hwfn); void qed_eth_queue_cid_release(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid); -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); +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_vf_params *p_vf_params); int qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn, diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 498c83ebc385ec18b9c638e4f0bef00231247ead..7ea00bf3e9b8953901d2cd3dc6e44aae068d10ff 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -1947,6 +1947,7 @@ static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn, struct qed_vf_info *vf) { struct qed_queue_start_common_params params; + struct qed_queue_cid_vf_params vf_params; struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; u8 status = PFVF_STATUS_NO_RESOURCE; struct qed_vf_q_info *p_queue; @@ -1965,6 +1966,10 @@ static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn, /* Acquire a new queue-cid */ p_queue = &vf->vf_queues[req->rx_qid]; + if (vf->acquire.vfdev_info.eth_fp_hsi_minor == + ETH_HSI_VER_NO_PKT_LEN_TUNN) + b_legacy_vf = true; + memset(¶ms, 0, sizeof(params)); params.queue_id = p_queue->fw_rx_qid; params.vport_id = vf->vport_id; @@ -1975,26 +1980,23 @@ static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn, params.p_sb = &sb_dummy; params.sb_idx = req->sb_index; - p_queue->p_rx_cid = _qed_eth_queue_to_cid(p_hwfn, - vf->opaque_fid, - p_queue->fw_cid, - req->rx_qid, ¶ms); + memset(&vf_params, 0, sizeof(vf_params)); + vf_params.vfid = vf->relative_vf_id; + vf_params.vf_qid = (u8)req->rx_qid; + vf_params.vf_legacy = b_legacy_vf; + p_queue->p_rx_cid = qed_eth_queue_to_cid(p_hwfn, vf->opaque_fid, + ¶ms, &vf_params); if (!p_queue->p_rx_cid) goto out; /* Legacy VFs have their Producers in a different location, which they * calculate on their own and clean the producer prior to this. */ - if (vf->acquire.vfdev_info.eth_fp_hsi_minor == - ETH_HSI_VER_NO_PKT_LEN_TUNN) { - b_legacy_vf = true; - } else { + if (!b_legacy_vf) REG_WR(p_hwfn, GTT_BAR0_MAP_REG_MSDM_RAM + MSTORM_ETH_VF_PRODS_OFFSET(vf->abs_vf_id, req->rx_qid), 0); - } - p_queue->p_rx_cid->b_legacy_vf = b_legacy_vf; rc = qed_eth_rxq_start_ramrod(p_hwfn, p_queue->p_rx_cid, @@ -2273,11 +2275,13 @@ static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn, struct qed_vf_info *vf) { struct qed_queue_start_common_params params; + struct qed_queue_cid_vf_params vf_params; struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; u8 status = PFVF_STATUS_NO_RESOURCE; struct vfpf_start_txq_tlv *req; struct qed_vf_q_info *p_queue; struct qed_sb_info sb_dummy; + bool b_vf_legacy = false; int rc; u16 pq; @@ -2292,6 +2296,10 @@ static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn, /* Acquire a new queue-cid */ p_queue = &vf->vf_queues[req->tx_qid]; + if (vf->acquire.vfdev_info.eth_fp_hsi_minor == + ETH_HSI_VER_NO_PKT_LEN_TUNN) + b_vf_legacy = true; + params.queue_id = p_queue->fw_tx_qid; params.vport_id = vf->vport_id; params.stats_id = vf->abs_vf_id + 0x10; @@ -2302,10 +2310,14 @@ static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn, params.p_sb = &sb_dummy; params.sb_idx = req->sb_index; - p_queue->p_tx_cid = _qed_eth_queue_to_cid(p_hwfn, - vf->opaque_fid, - p_queue->fw_cid, - req->tx_qid, ¶ms); + memset(&vf_params, 0, sizeof(vf_params)); + vf_params.vfid = vf->relative_vf_id; + vf_params.vf_qid = (u8)req->tx_qid; + vf_params.vf_legacy = b_vf_legacy; + + p_queue->p_tx_cid = qed_eth_queue_to_cid(p_hwfn, + vf->opaque_fid, + ¶ms, &vf_params); if (!p_queue->p_tx_cid) goto out;