X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fqede%2Fbase%2Fecore_sriov.c;h=b0516782844a20b49f48026ac7a21af16c6e3db8;hb=69ff7477b74f43d790c849e50c9ce951b1db1cff;hp=c2fbee872cdd3010dbc7503e5466cfab4f7db0c2;hpb=b765730bc13e008e2b3452a2e6dffb2d24994035;p=dpdk.git diff --git a/drivers/net/qede/base/ecore_sriov.c b/drivers/net/qede/base/ecore_sriov.c index c2fbee872c..b051678284 100644 --- a/drivers/net/qede/base/ecore_sriov.c +++ b/drivers/net/qede/base/ecore_sriov.c @@ -146,7 +146,7 @@ static enum _ecore_status_t ecore_sp_vf_stop(struct ecore_hwfn *p_hwfn, } bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn, int rel_vf_id, - bool b_enabled_only) + bool b_enabled_only, bool b_non_malicious) { if (!p_hwfn->pf_iov_info) { DP_NOTICE(p_hwfn->p_dev, true, "No iov info\n"); @@ -161,6 +161,10 @@ bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn, int rel_vf_id, b_enabled_only) return false; + if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) && + b_non_malicious) + return false; + return true; } @@ -175,7 +179,8 @@ struct ecore_vf_info *ecore_iov_get_vf_info(struct ecore_hwfn *p_hwfn, return OSAL_NULL; } - if (ecore_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only)) + if (ecore_iov_is_valid_vfid(p_hwfn, relative_vf_id, + b_enabled_only, false)) vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id]; else DP_ERR(p_hwfn, "ecore_iov_get_vf_info: VF[%d] is not enabled\n", @@ -549,7 +554,6 @@ void ecore_iov_free(struct ecore_hwfn *p_hwfn) void ecore_iov_free_hw_info(struct ecore_dev *p_dev) { OSAL_FREE(p_dev, p_dev->p_iov_info); - p_dev->p_iov_info = OSAL_NULL; } enum _ecore_status_t ecore_iov_hw_info(struct ecore_hwfn *p_hwfn) @@ -592,18 +596,33 @@ enum _ecore_status_t ecore_iov_hw_info(struct ecore_hwfn *p_hwfn) DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "IOV capabilities, but no VFs are published\n"); OSAL_FREE(p_dev, p_dev->p_iov_info); - p_dev->p_iov_info = OSAL_NULL; return ECORE_SUCCESS; } - /* Calculate the first VF index - this is a bit tricky; Basically, - * VFs start at offset 16 relative to PF0, and 2nd engine VFs begin - * after the first engine's VFs. + /* First VF index based on offset is tricky: + * - If ARI is supported [likely], offset - (16 - pf_id) would + * provide the number for eng0. 2nd engine Vfs would begin + * after the first engine's VFs. + * - If !ARI, VFs would start on next device. + * so offset - (256 - pf_id) would provide the number. + * Utilize the fact that (256 - pf_id) is achieved only be later + * to diffrentiate between the two. */ - p_dev->p_iov_info->first_vf_in_pf = p_hwfn->p_dev->p_iov_info->offset + - p_hwfn->abs_pf_id - 16; - if (ECORE_PATH_ID(p_hwfn)) - p_dev->p_iov_info->first_vf_in_pf -= MAX_NUM_VFS_BB; + + if (p_hwfn->p_dev->p_iov_info->offset < (256 - p_hwfn->abs_pf_id)) { + u32 first = p_hwfn->p_dev->p_iov_info->offset + + p_hwfn->abs_pf_id - 16; + + p_dev->p_iov_info->first_vf_in_pf = first; + + if (ECORE_PATH_ID(p_hwfn)) + p_dev->p_iov_info->first_vf_in_pf -= MAX_NUM_VFS_BB; + } else { + u32 first = p_hwfn->p_dev->p_iov_info->offset + + p_hwfn->abs_pf_id - 256; + + p_dev->p_iov_info->first_vf_in_pf = first; + } DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "First VF in hwfn 0x%08x\n", @@ -612,7 +631,8 @@ enum _ecore_status_t ecore_iov_hw_info(struct ecore_hwfn *p_hwfn) return ECORE_SUCCESS; } -bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid) +bool _ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid, + bool b_fail_malicious) { /* Check PF supports sriov */ if (IS_VF(p_hwfn->p_dev) || !IS_ECORE_SRIOV(p_hwfn->p_dev) || @@ -620,12 +640,17 @@ bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid) return false; /* Check VF validity */ - if (!ecore_iov_is_valid_vfid(p_hwfn, vfid, true)) + if (!ecore_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious)) return false; return true; } +bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid) +{ + return _ecore_iov_pf_sanity_check(p_hwfn, vfid, true); +} + void ecore_iov_set_vf_to_disable(struct ecore_dev *p_dev, u16 rel_vf_id, u8 to_disable) { @@ -746,6 +771,9 @@ ecore_iov_enable_vf_access(struct ecore_hwfn *p_hwfn, ecore_iov_vf_igu_reset(p_hwfn, p_ptt, vf); + /* It's possible VF was previously considered malicious */ + vf->b_malicious = false; + rc = ecore_mcp_config_vf_msix(p_hwfn, p_ptt, vf->abs_vf_id, vf->num_sbs); if (rc != ECORE_SUCCESS) @@ -1661,11 +1689,9 @@ ecore_iov_reconfigure_unicast_vlan(struct ecore_hwfn *p_hwfn, DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Reconfiguring VLAN [0x%04x] for VF [%04x]\n", filter.vlan, p_vf->relative_vf_id); - rc = ecore_sp_eth_filter_ucast(p_hwfn, - p_vf->opaque_fid, - &filter, - ECORE_SPQ_MODE_CB, - OSAL_NULL); + rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid, + &filter, ECORE_SPQ_MODE_CB, + OSAL_NULL); if (rc) { DP_NOTICE(p_hwfn, true, "Failed to configure VLAN [%04x]" @@ -1693,9 +1719,10 @@ ecore_iov_reconfigure_unicast_shadow(struct ecore_hwfn *p_hwfn, return rc; } -static int ecore_iov_configure_vport_forced(struct ecore_hwfn *p_hwfn, - struct ecore_vf_info *p_vf, - u64 events) +static enum _ecore_status_t +ecore_iov_configure_vport_forced(struct ecore_hwfn *p_hwfn, + struct ecore_vf_info *p_vf, + u64 events) { enum _ecore_status_t rc = ECORE_SUCCESS; struct ecore_filter_ucast filter; @@ -1972,7 +1999,7 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, struct ecore_vf_info *vf) { - struct ecore_queue_start_common_params p_params; + struct ecore_queue_start_common_params params; struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx; u8 status = PFVF_STATUS_NO_RESOURCE; struct vfpf_start_rxq_tlv *req; @@ -1985,13 +2012,13 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn, !ecore_iov_validate_sb(p_hwfn, vf, req->hw_sb)) goto out; - OSAL_MEMSET(&p_params, 0, sizeof(p_params)); - p_params.queue_id = (u8)vf->vf_queues[req->rx_qid].fw_rx_qid; - p_params.vf_qid = req->rx_qid; - p_params.vport_id = vf->vport_id; - p_params.stats_id = vf->abs_vf_id + 0x10, - p_params.sb = req->hw_sb; - p_params.sb_idx = req->sb_index; + OSAL_MEMSET(¶ms, 0, sizeof(params)); + params.queue_id = (u8)vf->vf_queues[req->rx_qid].fw_rx_qid; + params.vf_qid = req->rx_qid; + params.vport_id = vf->vport_id; + params.stats_id = vf->abs_vf_id + 0x10; + params.sb = req->hw_sb; + params.sb_idx = req->sb_index; /* Legacy VFs have their Producers in a different location, which they * calculate on their own and clean the producer prior to this. @@ -2007,7 +2034,7 @@ static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn, rc = ecore_sp_eth_rxq_start_ramrod(p_hwfn, vf->opaque_fid, vf->vf_queues[req->rx_qid].fw_cid, - &p_params, + ¶ms, req->bd_max_bytes, req->rxq_addr, req->cqe_pbl_addr, @@ -2072,7 +2099,7 @@ static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, struct ecore_vf_info *vf) { - struct ecore_queue_start_common_params p_params; + struct ecore_queue_start_common_params params; struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx; u8 status = PFVF_STATUS_NO_RESOURCE; union ecore_qm_pq_params pq_params; @@ -2084,26 +2111,27 @@ static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn, pq_params.eth.is_vf = 1; pq_params.eth.vf_id = vf->relative_vf_id; + OSAL_MEMSET(¶ms, 0, sizeof(params)); req = &mbx->req_virt->start_txq; - OSAL_MEMSET(&p_params, 0, sizeof(p_params)); - p_params.queue_id = (u8)vf->vf_queues[req->tx_qid].fw_tx_qid; - p_params.vport_id = vf->vport_id; - p_params.stats_id = vf->abs_vf_id + 0x10, - p_params.sb = req->hw_sb; - p_params.sb_idx = req->sb_index; if (!ecore_iov_validate_txq(p_hwfn, vf, req->tx_qid) || !ecore_iov_validate_sb(p_hwfn, vf, req->hw_sb)) goto out; - rc = ecore_sp_eth_txq_start_ramrod( - p_hwfn, - vf->opaque_fid, - vf->vf_queues[req->tx_qid].fw_cid, - &p_params, - req->pbl_addr, - req->pbl_size, - &pq_params); + params.queue_id = (u8)vf->vf_queues[req->tx_qid].fw_tx_qid; + params.qzone_id = (u8)vf->vf_queues[req->tx_qid].fw_tx_qid; + params.vport_id = vf->vport_id; + params.stats_id = vf->abs_vf_id + 0x10; + params.sb = req->hw_sb; + params.sb_idx = req->sb_index; + + rc = ecore_sp_eth_txq_start_ramrod(p_hwfn, + vf->opaque_fid, + vf->vf_queues[req->tx_qid].fw_cid, + ¶ms, + req->pbl_addr, + req->pbl_size, + &pq_params); if (rc) status = PFVF_STATUS_FAILURE; @@ -3061,6 +3089,13 @@ ecore_iov_execute_vf_flr_cleanup(struct ecore_hwfn *p_hwfn, return rc; } + /* Workaround to make VF-PF channel ready, as FW + * doesn't do that as a part of FLR. + */ + REG_WR(p_hwfn, + GTT_BAR0_MAP_REG_USDM_RAM + + USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1); + /* VF_STOPPED has to be set only after final cleanup * but prior to re-enabling the VF. */ @@ -3127,9 +3162,10 @@ ecore_iov_single_vf_flr_cleanup(struct ecore_hwfn *p_hwfn, return rc; } -int ecore_iov_mark_vf_flr(struct ecore_hwfn *p_hwfn, u32 *p_disabled_vfs) +bool ecore_iov_mark_vf_flr(struct ecore_hwfn *p_hwfn, u32 *p_disabled_vfs) { - u16 i, found = 0; + bool found = false; + u16 i; DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Marking FLR-ed VFs\n"); for (i = 0; i < (VF_MAX_STATIC / 32); i++) @@ -3139,7 +3175,7 @@ int ecore_iov_mark_vf_flr(struct ecore_hwfn *p_hwfn, u32 *p_disabled_vfs) if (!p_hwfn->p_dev->p_iov_info) { DP_NOTICE(p_hwfn, true, "VF flr but no IOV\n"); - return 0; + return false; } /* Mark VFs */ @@ -3168,7 +3204,7 @@ int ecore_iov_mark_vf_flr(struct ecore_hwfn *p_hwfn, u32 *p_disabled_vfs) * VF flr until ACKs, we're safe. */ p_flr[rel_vf_id / 64] |= 1ULL << (rel_vf_id % 64); - found = 1; + found = true; } } @@ -3227,7 +3263,8 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn, p_vf, mbx->first_tlv.tl.type); /* check if tlv type is known */ - if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) { + if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type) && + !p_vf->b_malicious) { /* switch on the opcode */ switch (mbx->first_tlv.tl.type) { case CHANNEL_TLV_ACQUIRE: @@ -3270,6 +3307,27 @@ void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn, ecore_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf); break; } + } else if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) { + /* If we've received a message from a VF we consider malicious + * we ignore the messasge unless it's one for RELEASE, in which + * case we'll let it have the benefit of doubt, allowing the + * next loaded driver to start again. + */ + if (mbx->first_tlv.tl.type == CHANNEL_TLV_RELEASE) { + /* TODO - initiate FLR, remove malicious indication */ + DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, + "VF [%02x] - considered malicious, but wanted to RELEASE. TODO\n", + p_vf->abs_vf_id); + } else { + DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, + "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n", + p_vf->abs_vf_id, mbx->first_tlv.tl.type); + } + + ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf, + mbx->first_tlv.tl.type, + sizeof(struct pfvf_def_resp_tlv), + PFVF_STATUS_MALICIOUS); } else { /* unknown TLV - this may belong to a VF driver from the future * - a version written after this PF driver was written, which @@ -3334,21 +3392,31 @@ void ecore_iov_pf_get_and_clear_pending_events(struct ecore_hwfn *p_hwfn, sizeof(u64) * ECORE_VF_ARRAY_LENGTH); } -static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn, - u16 abs_vfid, - struct regpair *vf_msg) +static struct ecore_vf_info * +ecore_sriov_get_vf_from_absid(struct ecore_hwfn *p_hwfn, u16 abs_vfid) { u8 min = (u8)p_hwfn->p_dev->p_iov_info->first_vf_in_pf; - struct ecore_vf_info *p_vf; - if (!ecore_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) { + if (!_ecore_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) { DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, - "Got a message from VF [abs 0x%08x] that cannot be" + "Got indication for VF [abs 0x%08x] that cannot be" " handled by PF\n", abs_vfid); - return ECORE_SUCCESS; + return OSAL_NULL; } - p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min]; + + return &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min]; +} + +static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn, + u16 abs_vfid, + struct regpair *vf_msg) +{ + struct ecore_vf_info *p_vf = ecore_sriov_get_vf_from_absid(p_hwfn, + abs_vfid); + + if (!p_vf) + return ECORE_SUCCESS; /* List the physical address of the request so that handler * could later on copy the message from it. @@ -3358,6 +3426,25 @@ static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn, return OSAL_PF_VF_MSG(p_hwfn, p_vf->relative_vf_id); } +static void ecore_sriov_vfpf_malicious(struct ecore_hwfn *p_hwfn, + struct malicious_vf_eqe_data *p_data) +{ + struct ecore_vf_info *p_vf; + + p_vf = ecore_sriov_get_vf_from_absid(p_hwfn, p_data->vfId); + + if (!p_vf) + return; + + DP_INFO(p_hwfn, + "VF [%d] - Malicious behavior [%02x]\n", + p_vf->abs_vf_id, p_data->errId); + + p_vf->b_malicious = true; + + OSAL_PF_VF_MALICIOUS(p_hwfn, p_vf->relative_vf_id); +} + enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn, u8 opcode, __le16 echo, @@ -3371,6 +3458,9 @@ enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn, DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "VF-FLR is still not supported\n"); return ECORE_SUCCESS; + case COMMON_EVENT_MALICIOUS_VF: + ecore_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf); + return ECORE_SUCCESS; default: DP_INFO(p_hwfn->p_dev, "Unknown sriov eqe event 0x%02x\n", opcode); @@ -3393,11 +3483,11 @@ u16 ecore_iov_get_next_active_vf(struct ecore_hwfn *p_hwfn, u16 rel_vf_id) goto out; for (i = rel_vf_id; i < p_iov->total_vfs; i++) - if (ecore_iov_is_valid_vfid(p_hwfn, rel_vf_id, true)) + if (ecore_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false)) return i; out: - return MAX_NUM_VFS; + return E4_MAX_NUM_VFS; } enum _ecore_status_t ecore_iov_copy_vf_msg(struct ecore_hwfn *p_hwfn, @@ -3439,6 +3529,12 @@ void ecore_iov_bulletin_set_forced_mac(struct ecore_hwfn *p_hwfn, "Can not set forced MAC, invalid vfid [%d]\n", vfid); return; } + if (vf_info->b_malicious) { + DP_NOTICE(p_hwfn->p_dev, false, + "Can't set forced MAC to malicious VF [%d]\n", + vfid); + return; + } feature = 1 << MAC_ADDR_FORCED; OSAL_MEMCPY(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN); @@ -3463,6 +3559,12 @@ enum _ecore_status_t ecore_iov_bulletin_set_mac(struct ecore_hwfn *p_hwfn, "Can not set MAC, invalid vfid [%d]\n", vfid); return ECORE_INVAL; } + if (vf_info->b_malicious) { + DP_NOTICE(p_hwfn->p_dev, false, + "Can't set MAC to malicious VF [%d]\n", + vfid); + return ECORE_INVAL; + } if (vf_info->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)) { DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, @@ -3488,7 +3590,14 @@ ecore_iov_bulletin_set_forced_untagged_default(struct ecore_hwfn *p_hwfn, vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true); if (!vf_info) { DP_NOTICE(p_hwfn->p_dev, true, - "Can not set forced MAC, invalid vfid [%d]\n", vfid); + "Can not set untagged default, invalid vfid [%d]\n", + vfid); + return ECORE_INVAL; + } + if (vf_info->b_malicious) { + DP_NOTICE(p_hwfn->p_dev, false, + "Can't set untagged default to malicious VF [%d]\n", + vfid); return ECORE_INVAL; } @@ -3553,6 +3662,12 @@ void ecore_iov_bulletin_set_forced_vlan(struct ecore_hwfn *p_hwfn, vfid); return; } + if (vf_info->b_malicious) { + DP_NOTICE(p_hwfn->p_dev, false, + "Can't set forced vlan to malicious VF [%d]\n", + vfid); + return; + } feature = 1 << VLAN_ADDR_FORCED; vf_info->bulletin.p_virt->pvid = pvid; @@ -3868,7 +3983,20 @@ bool ecore_iov_is_vf_initialized(struct ecore_hwfn *p_hwfn, u16 rel_vf_id) return (p_vf->state == VF_ENABLED); } -int ecore_iov_get_vf_min_rate(struct ecore_hwfn *p_hwfn, int vfid) +bool ecore_iov_is_vf_started(struct ecore_hwfn *p_hwfn, + u16 rel_vf_id) +{ + struct ecore_vf_info *p_vf; + + p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true); + if (!p_vf) + return false; + + return (p_vf->state != VF_FREE && p_vf->state != VF_STOPPED); +} + +enum _ecore_status_t +ecore_iov_get_vf_min_rate(struct ecore_hwfn *p_hwfn, int vfid) { struct ecore_wfq_data *vf_vp_wfq; struct ecore_vf_info *vf_info;