132a47e72SYuval Mintz /* QLogic qed NIC Driver 2e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 332a47e72SYuval Mintz * 4e8f1cb50SMintz, Yuval * This software is available to you under a choice of one of two 5e8f1cb50SMintz, Yuval * licenses. You may choose to be licensed under the terms of the GNU 6e8f1cb50SMintz, Yuval * General Public License (GPL) Version 2, available from the file 7e8f1cb50SMintz, Yuval * COPYING in the main directory of this source tree, or the 8e8f1cb50SMintz, Yuval * OpenIB.org BSD license below: 9e8f1cb50SMintz, Yuval * 10e8f1cb50SMintz, Yuval * Redistribution and use in source and binary forms, with or 11e8f1cb50SMintz, Yuval * without modification, are permitted provided that the following 12e8f1cb50SMintz, Yuval * conditions are met: 13e8f1cb50SMintz, Yuval * 14e8f1cb50SMintz, Yuval * - Redistributions of source code must retain the above 15e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 16e8f1cb50SMintz, Yuval * disclaimer. 17e8f1cb50SMintz, Yuval * 18e8f1cb50SMintz, Yuval * - Redistributions in binary form must reproduce the above 19e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 20e8f1cb50SMintz, Yuval * disclaimer in the documentation and /or other materials 21e8f1cb50SMintz, Yuval * provided with the distribution. 22e8f1cb50SMintz, Yuval * 23e8f1cb50SMintz, Yuval * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e8f1cb50SMintz, Yuval * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e8f1cb50SMintz, Yuval * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e8f1cb50SMintz, Yuval * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e8f1cb50SMintz, Yuval * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e8f1cb50SMintz, Yuval * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e8f1cb50SMintz, Yuval * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e8f1cb50SMintz, Yuval * SOFTWARE. 3132a47e72SYuval Mintz */ 3232a47e72SYuval Mintz 33dacd88d6SYuval Mintz #include <linux/etherdevice.h> 3436558c3dSYuval Mintz #include <linux/crc32.h> 35f29ffdb6SMintz, Yuval #include <linux/vmalloc.h> 360b55e27dSYuval Mintz #include <linux/qed/qed_iov_if.h> 371408cc1fSYuval Mintz #include "qed_cxt.h" 381408cc1fSYuval Mintz #include "qed_hsi.h" 3932a47e72SYuval Mintz #include "qed_hw.h" 401408cc1fSYuval Mintz #include "qed_init_ops.h" 4132a47e72SYuval Mintz #include "qed_int.h" 421408cc1fSYuval Mintz #include "qed_mcp.h" 4332a47e72SYuval Mintz #include "qed_reg_addr.h" 441408cc1fSYuval Mintz #include "qed_sp.h" 4532a47e72SYuval Mintz #include "qed_sriov.h" 4632a47e72SYuval Mintz #include "qed_vf.h" 4732a47e72SYuval Mintz 481408cc1fSYuval Mintz /* IOV ramrods */ 491fe614d1SYuval Mintz static int qed_sp_vf_start(struct qed_hwfn *p_hwfn, struct qed_vf_info *p_vf) 501408cc1fSYuval Mintz { 511408cc1fSYuval Mintz struct vf_start_ramrod_data *p_ramrod = NULL; 521408cc1fSYuval Mintz struct qed_spq_entry *p_ent = NULL; 531408cc1fSYuval Mintz struct qed_sp_init_data init_data; 541408cc1fSYuval Mintz int rc = -EINVAL; 551fe614d1SYuval Mintz u8 fp_minor; 561408cc1fSYuval Mintz 571408cc1fSYuval Mintz /* Get SPQ entry */ 581408cc1fSYuval Mintz memset(&init_data, 0, sizeof(init_data)); 591408cc1fSYuval Mintz init_data.cid = qed_spq_get_cid(p_hwfn); 601fe614d1SYuval Mintz init_data.opaque_fid = p_vf->opaque_fid; 611408cc1fSYuval Mintz init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 621408cc1fSYuval Mintz 631408cc1fSYuval Mintz rc = qed_sp_init_request(p_hwfn, &p_ent, 641408cc1fSYuval Mintz COMMON_RAMROD_VF_START, 651408cc1fSYuval Mintz PROTOCOLID_COMMON, &init_data); 661408cc1fSYuval Mintz if (rc) 671408cc1fSYuval Mintz return rc; 681408cc1fSYuval Mintz 691408cc1fSYuval Mintz p_ramrod = &p_ent->ramrod.vf_start; 701408cc1fSYuval Mintz 711fe614d1SYuval Mintz p_ramrod->vf_id = GET_FIELD(p_vf->concrete_fid, PXP_CONCRETE_FID_VFID); 721fe614d1SYuval Mintz p_ramrod->opaque_fid = cpu_to_le16(p_vf->opaque_fid); 731408cc1fSYuval Mintz 741fe614d1SYuval Mintz switch (p_hwfn->hw_info.personality) { 751fe614d1SYuval Mintz case QED_PCI_ETH: 761408cc1fSYuval Mintz p_ramrod->personality = PERSONALITY_ETH; 771fe614d1SYuval Mintz break; 781fe614d1SYuval Mintz case QED_PCI_ETH_ROCE: 791fe614d1SYuval Mintz p_ramrod->personality = PERSONALITY_RDMA_AND_ETH; 801fe614d1SYuval Mintz break; 811fe614d1SYuval Mintz default: 821fe614d1SYuval Mintz DP_NOTICE(p_hwfn, "Unknown VF personality %d\n", 831fe614d1SYuval Mintz p_hwfn->hw_info.personality); 841fe614d1SYuval Mintz return -EINVAL; 851fe614d1SYuval Mintz } 861fe614d1SYuval Mintz 871fe614d1SYuval Mintz fp_minor = p_vf->acquire.vfdev_info.eth_fp_hsi_minor; 88a044df83SYuval Mintz if (fp_minor > ETH_HSI_VER_MINOR && 89a044df83SYuval Mintz fp_minor != ETH_HSI_VER_NO_PKT_LEN_TUNN) { 901fe614d1SYuval Mintz DP_VERBOSE(p_hwfn, 911fe614d1SYuval Mintz QED_MSG_IOV, 921fe614d1SYuval Mintz "VF [%d] - Requested fp hsi %02x.%02x which is slightly newer than PF's %02x.%02x; Configuring PFs version\n", 931fe614d1SYuval Mintz p_vf->abs_vf_id, 941fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, 951fe614d1SYuval Mintz fp_minor, ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR); 961fe614d1SYuval Mintz fp_minor = ETH_HSI_VER_MINOR; 971fe614d1SYuval Mintz } 981fe614d1SYuval Mintz 99351a4dedSYuval Mintz p_ramrod->hsi_fp_ver.major_ver_arr[ETH_VER_KEY] = ETH_HSI_VER_MAJOR; 1001fe614d1SYuval Mintz p_ramrod->hsi_fp_ver.minor_ver_arr[ETH_VER_KEY] = fp_minor; 1011fe614d1SYuval Mintz 1021fe614d1SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1031fe614d1SYuval Mintz "VF[%d] - Starting using HSI %02x.%02x\n", 1041fe614d1SYuval Mintz p_vf->abs_vf_id, ETH_HSI_VER_MAJOR, fp_minor); 1051408cc1fSYuval Mintz 1061408cc1fSYuval Mintz return qed_spq_post(p_hwfn, p_ent, NULL); 1071408cc1fSYuval Mintz } 1081408cc1fSYuval Mintz 1090b55e27dSYuval Mintz static int qed_sp_vf_stop(struct qed_hwfn *p_hwfn, 1100b55e27dSYuval Mintz u32 concrete_vfid, u16 opaque_vfid) 1110b55e27dSYuval Mintz { 1120b55e27dSYuval Mintz struct vf_stop_ramrod_data *p_ramrod = NULL; 1130b55e27dSYuval Mintz struct qed_spq_entry *p_ent = NULL; 1140b55e27dSYuval Mintz struct qed_sp_init_data init_data; 1150b55e27dSYuval Mintz int rc = -EINVAL; 1160b55e27dSYuval Mintz 1170b55e27dSYuval Mintz /* Get SPQ entry */ 1180b55e27dSYuval Mintz memset(&init_data, 0, sizeof(init_data)); 1190b55e27dSYuval Mintz init_data.cid = qed_spq_get_cid(p_hwfn); 1200b55e27dSYuval Mintz init_data.opaque_fid = opaque_vfid; 1210b55e27dSYuval Mintz init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 1220b55e27dSYuval Mintz 1230b55e27dSYuval Mintz rc = qed_sp_init_request(p_hwfn, &p_ent, 1240b55e27dSYuval Mintz COMMON_RAMROD_VF_STOP, 1250b55e27dSYuval Mintz PROTOCOLID_COMMON, &init_data); 1260b55e27dSYuval Mintz if (rc) 1270b55e27dSYuval Mintz return rc; 1280b55e27dSYuval Mintz 1290b55e27dSYuval Mintz p_ramrod = &p_ent->ramrod.vf_stop; 1300b55e27dSYuval Mintz 1310b55e27dSYuval Mintz p_ramrod->vf_id = GET_FIELD(concrete_vfid, PXP_CONCRETE_FID_VFID); 1320b55e27dSYuval Mintz 1330b55e27dSYuval Mintz return qed_spq_post(p_hwfn, p_ent, NULL); 1340b55e27dSYuval Mintz } 1350b55e27dSYuval Mintz 136ba56947aSBaoyou Xie static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn, 1377eff82b0SYuval Mintz int rel_vf_id, 1387eff82b0SYuval Mintz bool b_enabled_only, bool b_non_malicious) 13932a47e72SYuval Mintz { 14032a47e72SYuval Mintz if (!p_hwfn->pf_iov_info) { 14132a47e72SYuval Mintz DP_NOTICE(p_hwfn->cdev, "No iov info\n"); 14232a47e72SYuval Mintz return false; 14332a47e72SYuval Mintz } 14432a47e72SYuval Mintz 14532a47e72SYuval Mintz if ((rel_vf_id >= p_hwfn->cdev->p_iov_info->total_vfs) || 14632a47e72SYuval Mintz (rel_vf_id < 0)) 14732a47e72SYuval Mintz return false; 14832a47e72SYuval Mintz 14932a47e72SYuval Mintz if ((!p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_init) && 15032a47e72SYuval Mintz b_enabled_only) 15132a47e72SYuval Mintz return false; 15232a47e72SYuval Mintz 1537eff82b0SYuval Mintz if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) && 1547eff82b0SYuval Mintz b_non_malicious) 1557eff82b0SYuval Mintz return false; 1567eff82b0SYuval Mintz 15732a47e72SYuval Mintz return true; 15832a47e72SYuval Mintz } 15932a47e72SYuval Mintz 16037bff2b9SYuval Mintz static struct qed_vf_info *qed_iov_get_vf_info(struct qed_hwfn *p_hwfn, 16137bff2b9SYuval Mintz u16 relative_vf_id, 16237bff2b9SYuval Mintz bool b_enabled_only) 16337bff2b9SYuval Mintz { 16437bff2b9SYuval Mintz struct qed_vf_info *vf = NULL; 16537bff2b9SYuval Mintz 16637bff2b9SYuval Mintz if (!p_hwfn->pf_iov_info) { 16737bff2b9SYuval Mintz DP_NOTICE(p_hwfn->cdev, "No iov info\n"); 16837bff2b9SYuval Mintz return NULL; 16937bff2b9SYuval Mintz } 17037bff2b9SYuval Mintz 1717eff82b0SYuval Mintz if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, 1727eff82b0SYuval Mintz b_enabled_only, false)) 17337bff2b9SYuval Mintz vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id]; 17437bff2b9SYuval Mintz else 17537bff2b9SYuval Mintz DP_ERR(p_hwfn, "qed_iov_get_vf_info: VF[%d] is not enabled\n", 17637bff2b9SYuval Mintz relative_vf_id); 17737bff2b9SYuval Mintz 17837bff2b9SYuval Mintz return vf; 17937bff2b9SYuval Mintz } 18037bff2b9SYuval Mintz 181f109c240SMintz, Yuval enum qed_iov_validate_q_mode { 182f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_NA, 183f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE, 184f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_DISABLE, 185f109c240SMintz, Yuval }; 186f109c240SMintz, Yuval 187f109c240SMintz, Yuval static bool qed_iov_validate_queue_mode(struct qed_hwfn *p_hwfn, 188f109c240SMintz, Yuval struct qed_vf_info *p_vf, 189f109c240SMintz, Yuval u16 qid, 190f109c240SMintz, Yuval enum qed_iov_validate_q_mode mode, 191f109c240SMintz, Yuval bool b_is_tx) 19241086467SYuval Mintz { 193f109c240SMintz, Yuval if (mode == QED_IOV_VALIDATE_Q_NA) 194f109c240SMintz, Yuval return true; 195f109c240SMintz, Yuval 196f109c240SMintz, Yuval if ((b_is_tx && p_vf->vf_queues[qid].p_tx_cid) || 197f109c240SMintz, Yuval (!b_is_tx && p_vf->vf_queues[qid].p_rx_cid)) 198f109c240SMintz, Yuval return mode == QED_IOV_VALIDATE_Q_ENABLE; 199f109c240SMintz, Yuval 200f109c240SMintz, Yuval /* In case we haven't found any valid cid, then its disabled */ 201f109c240SMintz, Yuval return mode == QED_IOV_VALIDATE_Q_DISABLE; 202f109c240SMintz, Yuval } 203f109c240SMintz, Yuval 204f109c240SMintz, Yuval static bool qed_iov_validate_rxq(struct qed_hwfn *p_hwfn, 205f109c240SMintz, Yuval struct qed_vf_info *p_vf, 206f109c240SMintz, Yuval u16 rx_qid, 207f109c240SMintz, Yuval enum qed_iov_validate_q_mode mode) 208f109c240SMintz, Yuval { 209f109c240SMintz, Yuval if (rx_qid >= p_vf->num_rxqs) { 21041086467SYuval Mintz DP_VERBOSE(p_hwfn, 21141086467SYuval Mintz QED_MSG_IOV, 21241086467SYuval Mintz "VF[0x%02x] - can't touch Rx queue[%04x]; Only 0x%04x are allocated\n", 21341086467SYuval Mintz p_vf->abs_vf_id, rx_qid, p_vf->num_rxqs); 214f109c240SMintz, Yuval return false; 215f109c240SMintz, Yuval } 216f109c240SMintz, Yuval 217f109c240SMintz, Yuval return qed_iov_validate_queue_mode(p_hwfn, p_vf, rx_qid, mode, false); 21841086467SYuval Mintz } 21941086467SYuval Mintz 22041086467SYuval Mintz static bool qed_iov_validate_txq(struct qed_hwfn *p_hwfn, 221f109c240SMintz, Yuval struct qed_vf_info *p_vf, 222f109c240SMintz, Yuval u16 tx_qid, 223f109c240SMintz, Yuval enum qed_iov_validate_q_mode mode) 22441086467SYuval Mintz { 225f109c240SMintz, Yuval if (tx_qid >= p_vf->num_txqs) { 22641086467SYuval Mintz DP_VERBOSE(p_hwfn, 22741086467SYuval Mintz QED_MSG_IOV, 22841086467SYuval Mintz "VF[0x%02x] - can't touch Tx queue[%04x]; Only 0x%04x are allocated\n", 22941086467SYuval Mintz p_vf->abs_vf_id, tx_qid, p_vf->num_txqs); 230f109c240SMintz, Yuval return false; 231f109c240SMintz, Yuval } 232f109c240SMintz, Yuval 233f109c240SMintz, Yuval return qed_iov_validate_queue_mode(p_hwfn, p_vf, tx_qid, mode, true); 23441086467SYuval Mintz } 23541086467SYuval Mintz 23641086467SYuval Mintz static bool qed_iov_validate_sb(struct qed_hwfn *p_hwfn, 23741086467SYuval Mintz struct qed_vf_info *p_vf, u16 sb_idx) 23841086467SYuval Mintz { 23941086467SYuval Mintz int i; 24041086467SYuval Mintz 24141086467SYuval Mintz for (i = 0; i < p_vf->num_sbs; i++) 24241086467SYuval Mintz if (p_vf->igu_sbs[i] == sb_idx) 24341086467SYuval Mintz return true; 24441086467SYuval Mintz 24541086467SYuval Mintz DP_VERBOSE(p_hwfn, 24641086467SYuval Mintz QED_MSG_IOV, 24741086467SYuval Mintz "VF[0%02x] - tried using sb_idx %04x which doesn't exist as one of its 0x%02x SBs\n", 24841086467SYuval Mintz p_vf->abs_vf_id, sb_idx, p_vf->num_sbs); 24941086467SYuval Mintz 25041086467SYuval Mintz return false; 25141086467SYuval Mintz } 25241086467SYuval Mintz 253f109c240SMintz, Yuval static bool qed_iov_validate_active_rxq(struct qed_hwfn *p_hwfn, 254f109c240SMintz, Yuval struct qed_vf_info *p_vf) 255f109c240SMintz, Yuval { 256f109c240SMintz, Yuval u8 i; 257f109c240SMintz, Yuval 258f109c240SMintz, Yuval for (i = 0; i < p_vf->num_rxqs; i++) 259f109c240SMintz, Yuval if (qed_iov_validate_queue_mode(p_hwfn, p_vf, i, 260f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE, 261f109c240SMintz, Yuval false)) 262f109c240SMintz, Yuval return true; 263f109c240SMintz, Yuval 264f109c240SMintz, Yuval return false; 265f109c240SMintz, Yuval } 266f109c240SMintz, Yuval 267f109c240SMintz, Yuval static bool qed_iov_validate_active_txq(struct qed_hwfn *p_hwfn, 268f109c240SMintz, Yuval struct qed_vf_info *p_vf) 269f109c240SMintz, Yuval { 270f109c240SMintz, Yuval u8 i; 271f109c240SMintz, Yuval 272f109c240SMintz, Yuval for (i = 0; i < p_vf->num_txqs; i++) 273f109c240SMintz, Yuval if (qed_iov_validate_queue_mode(p_hwfn, p_vf, i, 274f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE, 275f109c240SMintz, Yuval true)) 276f109c240SMintz, Yuval return true; 277f109c240SMintz, Yuval 278f109c240SMintz, Yuval return false; 279f109c240SMintz, Yuval } 280f109c240SMintz, Yuval 281ba56947aSBaoyou Xie static int qed_iov_post_vf_bulletin(struct qed_hwfn *p_hwfn, 28236558c3dSYuval Mintz int vfid, struct qed_ptt *p_ptt) 28336558c3dSYuval Mintz { 28436558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin; 28536558c3dSYuval Mintz int crc_size = sizeof(p_bulletin->crc); 28636558c3dSYuval Mintz struct qed_dmae_params params; 28736558c3dSYuval Mintz struct qed_vf_info *p_vf; 28836558c3dSYuval Mintz 28936558c3dSYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 29036558c3dSYuval Mintz if (!p_vf) 29136558c3dSYuval Mintz return -EINVAL; 29236558c3dSYuval Mintz 29336558c3dSYuval Mintz if (!p_vf->vf_bulletin) 29436558c3dSYuval Mintz return -EINVAL; 29536558c3dSYuval Mintz 29636558c3dSYuval Mintz p_bulletin = p_vf->bulletin.p_virt; 29736558c3dSYuval Mintz 29836558c3dSYuval Mintz /* Increment bulletin board version and compute crc */ 29936558c3dSYuval Mintz p_bulletin->version++; 30036558c3dSYuval Mintz p_bulletin->crc = crc32(0, (u8 *)p_bulletin + crc_size, 30136558c3dSYuval Mintz p_vf->bulletin.size - crc_size); 30236558c3dSYuval Mintz 30336558c3dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 30436558c3dSYuval Mintz "Posting Bulletin 0x%08x to VF[%d] (CRC 0x%08x)\n", 30536558c3dSYuval Mintz p_bulletin->version, p_vf->relative_vf_id, p_bulletin->crc); 30636558c3dSYuval Mintz 30736558c3dSYuval Mintz /* propagate bulletin board via dmae to vm memory */ 30836558c3dSYuval Mintz memset(¶ms, 0, sizeof(params)); 30936558c3dSYuval Mintz params.flags = QED_DMAE_FLAG_VF_DST; 31036558c3dSYuval Mintz params.dst_vfid = p_vf->abs_vf_id; 31136558c3dSYuval Mintz return qed_dmae_host2host(p_hwfn, p_ptt, p_vf->bulletin.phys, 31236558c3dSYuval Mintz p_vf->vf_bulletin, p_vf->bulletin.size / 4, 31336558c3dSYuval Mintz ¶ms); 31436558c3dSYuval Mintz } 31536558c3dSYuval Mintz 31632a47e72SYuval Mintz static int qed_iov_pci_cfg_info(struct qed_dev *cdev) 31732a47e72SYuval Mintz { 31832a47e72SYuval Mintz struct qed_hw_sriov_info *iov = cdev->p_iov_info; 31932a47e72SYuval Mintz int pos = iov->pos; 32032a47e72SYuval Mintz 32132a47e72SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, "sriov ext pos %d\n", pos); 32232a47e72SYuval Mintz pci_read_config_word(cdev->pdev, pos + PCI_SRIOV_CTRL, &iov->ctrl); 32332a47e72SYuval Mintz 32432a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 32532a47e72SYuval Mintz pos + PCI_SRIOV_TOTAL_VF, &iov->total_vfs); 32632a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 32732a47e72SYuval Mintz pos + PCI_SRIOV_INITIAL_VF, &iov->initial_vfs); 32832a47e72SYuval Mintz 32932a47e72SYuval Mintz pci_read_config_word(cdev->pdev, pos + PCI_SRIOV_NUM_VF, &iov->num_vfs); 33032a47e72SYuval Mintz if (iov->num_vfs) { 33132a47e72SYuval Mintz DP_VERBOSE(cdev, 33232a47e72SYuval Mintz QED_MSG_IOV, 33332a47e72SYuval Mintz "Number of VFs are already set to non-zero value. Ignoring PCI configuration value\n"); 33432a47e72SYuval Mintz iov->num_vfs = 0; 33532a47e72SYuval Mintz } 33632a47e72SYuval Mintz 33732a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 33832a47e72SYuval Mintz pos + PCI_SRIOV_VF_OFFSET, &iov->offset); 33932a47e72SYuval Mintz 34032a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 34132a47e72SYuval Mintz pos + PCI_SRIOV_VF_STRIDE, &iov->stride); 34232a47e72SYuval Mintz 34332a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 34432a47e72SYuval Mintz pos + PCI_SRIOV_VF_DID, &iov->vf_device_id); 34532a47e72SYuval Mintz 34632a47e72SYuval Mintz pci_read_config_dword(cdev->pdev, 34732a47e72SYuval Mintz pos + PCI_SRIOV_SUP_PGSIZE, &iov->pgsz); 34832a47e72SYuval Mintz 34932a47e72SYuval Mintz pci_read_config_dword(cdev->pdev, pos + PCI_SRIOV_CAP, &iov->cap); 35032a47e72SYuval Mintz 35132a47e72SYuval Mintz pci_read_config_byte(cdev->pdev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); 35232a47e72SYuval Mintz 35332a47e72SYuval Mintz DP_VERBOSE(cdev, 35432a47e72SYuval Mintz QED_MSG_IOV, 35532a47e72SYuval Mintz "IOV info: nres %d, cap 0x%x, ctrl 0x%x, total %d, initial %d, num vfs %d, offset %d, stride %d, page size 0x%x\n", 35632a47e72SYuval Mintz iov->nres, 35732a47e72SYuval Mintz iov->cap, 35832a47e72SYuval Mintz iov->ctrl, 35932a47e72SYuval Mintz iov->total_vfs, 36032a47e72SYuval Mintz iov->initial_vfs, 36132a47e72SYuval Mintz iov->nr_virtfn, iov->offset, iov->stride, iov->pgsz); 36232a47e72SYuval Mintz 36332a47e72SYuval Mintz /* Some sanity checks */ 36432a47e72SYuval Mintz if (iov->num_vfs > NUM_OF_VFS(cdev) || 36532a47e72SYuval Mintz iov->total_vfs > NUM_OF_VFS(cdev)) { 36632a47e72SYuval Mintz /* This can happen only due to a bug. In this case we set 36732a47e72SYuval Mintz * num_vfs to zero to avoid memory corruption in the code that 36832a47e72SYuval Mintz * assumes max number of vfs 36932a47e72SYuval Mintz */ 37032a47e72SYuval Mintz DP_NOTICE(cdev, 37132a47e72SYuval Mintz "IOV: Unexpected number of vfs set: %d setting num_vf to zero\n", 37232a47e72SYuval Mintz iov->num_vfs); 37332a47e72SYuval Mintz 37432a47e72SYuval Mintz iov->num_vfs = 0; 37532a47e72SYuval Mintz iov->total_vfs = 0; 37632a47e72SYuval Mintz } 37732a47e72SYuval Mintz 37832a47e72SYuval Mintz return 0; 37932a47e72SYuval Mintz } 38032a47e72SYuval Mintz 38132a47e72SYuval Mintz static void qed_iov_setup_vfdb(struct qed_hwfn *p_hwfn) 38232a47e72SYuval Mintz { 38332a47e72SYuval Mintz struct qed_hw_sriov_info *p_iov = p_hwfn->cdev->p_iov_info; 38432a47e72SYuval Mintz struct qed_pf_iov *p_iov_info = p_hwfn->pf_iov_info; 38532a47e72SYuval Mintz struct qed_bulletin_content *p_bulletin_virt; 38632a47e72SYuval Mintz dma_addr_t req_p, rply_p, bulletin_p; 38732a47e72SYuval Mintz union pfvf_tlvs *p_reply_virt_addr; 38832a47e72SYuval Mintz union vfpf_tlvs *p_req_virt_addr; 38932a47e72SYuval Mintz u8 idx = 0; 39032a47e72SYuval Mintz 39132a47e72SYuval Mintz memset(p_iov_info->vfs_array, 0, sizeof(p_iov_info->vfs_array)); 39232a47e72SYuval Mintz 39332a47e72SYuval Mintz p_req_virt_addr = p_iov_info->mbx_msg_virt_addr; 39432a47e72SYuval Mintz req_p = p_iov_info->mbx_msg_phys_addr; 39532a47e72SYuval Mintz p_reply_virt_addr = p_iov_info->mbx_reply_virt_addr; 39632a47e72SYuval Mintz rply_p = p_iov_info->mbx_reply_phys_addr; 39732a47e72SYuval Mintz p_bulletin_virt = p_iov_info->p_bulletins; 39832a47e72SYuval Mintz bulletin_p = p_iov_info->bulletins_phys; 39932a47e72SYuval Mintz if (!p_req_virt_addr || !p_reply_virt_addr || !p_bulletin_virt) { 40032a47e72SYuval Mintz DP_ERR(p_hwfn, 40132a47e72SYuval Mintz "qed_iov_setup_vfdb called without allocating mem first\n"); 40232a47e72SYuval Mintz return; 40332a47e72SYuval Mintz } 40432a47e72SYuval Mintz 40532a47e72SYuval Mintz for (idx = 0; idx < p_iov->total_vfs; idx++) { 40632a47e72SYuval Mintz struct qed_vf_info *vf = &p_iov_info->vfs_array[idx]; 40732a47e72SYuval Mintz u32 concrete; 40832a47e72SYuval Mintz 40932a47e72SYuval Mintz vf->vf_mbx.req_virt = p_req_virt_addr + idx; 41032a47e72SYuval Mintz vf->vf_mbx.req_phys = req_p + idx * sizeof(union vfpf_tlvs); 41132a47e72SYuval Mintz vf->vf_mbx.reply_virt = p_reply_virt_addr + idx; 41232a47e72SYuval Mintz vf->vf_mbx.reply_phys = rply_p + idx * sizeof(union pfvf_tlvs); 41332a47e72SYuval Mintz 41432a47e72SYuval Mintz vf->state = VF_STOPPED; 41532a47e72SYuval Mintz vf->b_init = false; 41632a47e72SYuval Mintz 41732a47e72SYuval Mintz vf->bulletin.phys = idx * 41832a47e72SYuval Mintz sizeof(struct qed_bulletin_content) + 41932a47e72SYuval Mintz bulletin_p; 42032a47e72SYuval Mintz vf->bulletin.p_virt = p_bulletin_virt + idx; 42132a47e72SYuval Mintz vf->bulletin.size = sizeof(struct qed_bulletin_content); 42232a47e72SYuval Mintz 42332a47e72SYuval Mintz vf->relative_vf_id = idx; 42432a47e72SYuval Mintz vf->abs_vf_id = idx + p_iov->first_vf_in_pf; 42532a47e72SYuval Mintz concrete = qed_vfid_to_concrete(p_hwfn, vf->abs_vf_id); 42632a47e72SYuval Mintz vf->concrete_fid = concrete; 42732a47e72SYuval Mintz vf->opaque_fid = (p_hwfn->hw_info.opaque_fid & 0xff) | 42832a47e72SYuval Mintz (vf->abs_vf_id << 8); 42932a47e72SYuval Mintz vf->vport_id = idx + 1; 4301cf2b1a9SYuval Mintz 4311cf2b1a9SYuval Mintz vf->num_mac_filters = QED_ETH_VF_NUM_MAC_FILTERS; 4321cf2b1a9SYuval Mintz vf->num_vlan_filters = QED_ETH_VF_NUM_VLAN_FILTERS; 43332a47e72SYuval Mintz } 43432a47e72SYuval Mintz } 43532a47e72SYuval Mintz 43632a47e72SYuval Mintz static int qed_iov_allocate_vfdb(struct qed_hwfn *p_hwfn) 43732a47e72SYuval Mintz { 43832a47e72SYuval Mintz struct qed_pf_iov *p_iov_info = p_hwfn->pf_iov_info; 43932a47e72SYuval Mintz void **p_v_addr; 44032a47e72SYuval Mintz u16 num_vfs = 0; 44132a47e72SYuval Mintz 44232a47e72SYuval Mintz num_vfs = p_hwfn->cdev->p_iov_info->total_vfs; 44332a47e72SYuval Mintz 44432a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 44532a47e72SYuval Mintz "qed_iov_allocate_vfdb for %d VFs\n", num_vfs); 44632a47e72SYuval Mintz 44732a47e72SYuval Mintz /* Allocate PF Mailbox buffer (per-VF) */ 44832a47e72SYuval Mintz p_iov_info->mbx_msg_size = sizeof(union vfpf_tlvs) * num_vfs; 44932a47e72SYuval Mintz p_v_addr = &p_iov_info->mbx_msg_virt_addr; 45032a47e72SYuval Mintz *p_v_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 45132a47e72SYuval Mintz p_iov_info->mbx_msg_size, 45232a47e72SYuval Mintz &p_iov_info->mbx_msg_phys_addr, 45332a47e72SYuval Mintz GFP_KERNEL); 45432a47e72SYuval Mintz if (!*p_v_addr) 45532a47e72SYuval Mintz return -ENOMEM; 45632a47e72SYuval Mintz 45732a47e72SYuval Mintz /* Allocate PF Mailbox Reply buffer (per-VF) */ 45832a47e72SYuval Mintz p_iov_info->mbx_reply_size = sizeof(union pfvf_tlvs) * num_vfs; 45932a47e72SYuval Mintz p_v_addr = &p_iov_info->mbx_reply_virt_addr; 46032a47e72SYuval Mintz *p_v_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 46132a47e72SYuval Mintz p_iov_info->mbx_reply_size, 46232a47e72SYuval Mintz &p_iov_info->mbx_reply_phys_addr, 46332a47e72SYuval Mintz GFP_KERNEL); 46432a47e72SYuval Mintz if (!*p_v_addr) 46532a47e72SYuval Mintz return -ENOMEM; 46632a47e72SYuval Mintz 46732a47e72SYuval Mintz p_iov_info->bulletins_size = sizeof(struct qed_bulletin_content) * 46832a47e72SYuval Mintz num_vfs; 46932a47e72SYuval Mintz p_v_addr = &p_iov_info->p_bulletins; 47032a47e72SYuval Mintz *p_v_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 47132a47e72SYuval Mintz p_iov_info->bulletins_size, 47232a47e72SYuval Mintz &p_iov_info->bulletins_phys, 47332a47e72SYuval Mintz GFP_KERNEL); 47432a47e72SYuval Mintz if (!*p_v_addr) 47532a47e72SYuval Mintz return -ENOMEM; 47632a47e72SYuval Mintz 47732a47e72SYuval Mintz DP_VERBOSE(p_hwfn, 47832a47e72SYuval Mintz QED_MSG_IOV, 47932a47e72SYuval Mintz "PF's Requests mailbox [%p virt 0x%llx phys], Response mailbox [%p virt 0x%llx phys] Bulletins [%p virt 0x%llx phys]\n", 48032a47e72SYuval Mintz p_iov_info->mbx_msg_virt_addr, 48132a47e72SYuval Mintz (u64) p_iov_info->mbx_msg_phys_addr, 48232a47e72SYuval Mintz p_iov_info->mbx_reply_virt_addr, 48332a47e72SYuval Mintz (u64) p_iov_info->mbx_reply_phys_addr, 48432a47e72SYuval Mintz p_iov_info->p_bulletins, (u64) p_iov_info->bulletins_phys); 48532a47e72SYuval Mintz 48632a47e72SYuval Mintz return 0; 48732a47e72SYuval Mintz } 48832a47e72SYuval Mintz 48932a47e72SYuval Mintz static void qed_iov_free_vfdb(struct qed_hwfn *p_hwfn) 49032a47e72SYuval Mintz { 49132a47e72SYuval Mintz struct qed_pf_iov *p_iov_info = p_hwfn->pf_iov_info; 49232a47e72SYuval Mintz 49332a47e72SYuval Mintz if (p_hwfn->pf_iov_info->mbx_msg_virt_addr) 49432a47e72SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 49532a47e72SYuval Mintz p_iov_info->mbx_msg_size, 49632a47e72SYuval Mintz p_iov_info->mbx_msg_virt_addr, 49732a47e72SYuval Mintz p_iov_info->mbx_msg_phys_addr); 49832a47e72SYuval Mintz 49932a47e72SYuval Mintz if (p_hwfn->pf_iov_info->mbx_reply_virt_addr) 50032a47e72SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 50132a47e72SYuval Mintz p_iov_info->mbx_reply_size, 50232a47e72SYuval Mintz p_iov_info->mbx_reply_virt_addr, 50332a47e72SYuval Mintz p_iov_info->mbx_reply_phys_addr); 50432a47e72SYuval Mintz 50532a47e72SYuval Mintz if (p_iov_info->p_bulletins) 50632a47e72SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 50732a47e72SYuval Mintz p_iov_info->bulletins_size, 50832a47e72SYuval Mintz p_iov_info->p_bulletins, 50932a47e72SYuval Mintz p_iov_info->bulletins_phys); 51032a47e72SYuval Mintz } 51132a47e72SYuval Mintz 51232a47e72SYuval Mintz int qed_iov_alloc(struct qed_hwfn *p_hwfn) 51332a47e72SYuval Mintz { 51432a47e72SYuval Mintz struct qed_pf_iov *p_sriov; 51532a47e72SYuval Mintz 51632a47e72SYuval Mintz if (!IS_PF_SRIOV(p_hwfn)) { 51732a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 51832a47e72SYuval Mintz "No SR-IOV - no need for IOV db\n"); 51932a47e72SYuval Mintz return 0; 52032a47e72SYuval Mintz } 52132a47e72SYuval Mintz 52232a47e72SYuval Mintz p_sriov = kzalloc(sizeof(*p_sriov), GFP_KERNEL); 5232591c280SJoe Perches if (!p_sriov) 52432a47e72SYuval Mintz return -ENOMEM; 52532a47e72SYuval Mintz 52632a47e72SYuval Mintz p_hwfn->pf_iov_info = p_sriov; 52732a47e72SYuval Mintz 52832a47e72SYuval Mintz return qed_iov_allocate_vfdb(p_hwfn); 52932a47e72SYuval Mintz } 53032a47e72SYuval Mintz 5311ee240e3SMintz, Yuval void qed_iov_setup(struct qed_hwfn *p_hwfn) 53232a47e72SYuval Mintz { 53332a47e72SYuval Mintz if (!IS_PF_SRIOV(p_hwfn) || !IS_PF_SRIOV_ALLOC(p_hwfn)) 53432a47e72SYuval Mintz return; 53532a47e72SYuval Mintz 53632a47e72SYuval Mintz qed_iov_setup_vfdb(p_hwfn); 53732a47e72SYuval Mintz } 53832a47e72SYuval Mintz 53932a47e72SYuval Mintz void qed_iov_free(struct qed_hwfn *p_hwfn) 54032a47e72SYuval Mintz { 54132a47e72SYuval Mintz if (IS_PF_SRIOV_ALLOC(p_hwfn)) { 54232a47e72SYuval Mintz qed_iov_free_vfdb(p_hwfn); 54332a47e72SYuval Mintz kfree(p_hwfn->pf_iov_info); 54432a47e72SYuval Mintz } 54532a47e72SYuval Mintz } 54632a47e72SYuval Mintz 54732a47e72SYuval Mintz void qed_iov_free_hw_info(struct qed_dev *cdev) 54832a47e72SYuval Mintz { 54932a47e72SYuval Mintz kfree(cdev->p_iov_info); 55032a47e72SYuval Mintz cdev->p_iov_info = NULL; 55132a47e72SYuval Mintz } 55232a47e72SYuval Mintz 55332a47e72SYuval Mintz int qed_iov_hw_info(struct qed_hwfn *p_hwfn) 55432a47e72SYuval Mintz { 55532a47e72SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 55632a47e72SYuval Mintz int pos; 55732a47e72SYuval Mintz int rc; 55832a47e72SYuval Mintz 5591408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev)) 5601408cc1fSYuval Mintz return 0; 5611408cc1fSYuval Mintz 56232a47e72SYuval Mintz /* Learn the PCI configuration */ 56332a47e72SYuval Mintz pos = pci_find_ext_capability(p_hwfn->cdev->pdev, 56432a47e72SYuval Mintz PCI_EXT_CAP_ID_SRIOV); 56532a47e72SYuval Mintz if (!pos) { 56632a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "No PCIe IOV support\n"); 56732a47e72SYuval Mintz return 0; 56832a47e72SYuval Mintz } 56932a47e72SYuval Mintz 57032a47e72SYuval Mintz /* Allocate a new struct for IOV information */ 57132a47e72SYuval Mintz cdev->p_iov_info = kzalloc(sizeof(*cdev->p_iov_info), GFP_KERNEL); 5722591c280SJoe Perches if (!cdev->p_iov_info) 57332a47e72SYuval Mintz return -ENOMEM; 5742591c280SJoe Perches 57532a47e72SYuval Mintz cdev->p_iov_info->pos = pos; 57632a47e72SYuval Mintz 57732a47e72SYuval Mintz rc = qed_iov_pci_cfg_info(cdev); 57832a47e72SYuval Mintz if (rc) 57932a47e72SYuval Mintz return rc; 58032a47e72SYuval Mintz 58132a47e72SYuval Mintz /* We want PF IOV to be synonemous with the existance of p_iov_info; 58232a47e72SYuval Mintz * In case the capability is published but there are no VFs, simply 58332a47e72SYuval Mintz * de-allocate the struct. 58432a47e72SYuval Mintz */ 58532a47e72SYuval Mintz if (!cdev->p_iov_info->total_vfs) { 58632a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 58732a47e72SYuval Mintz "IOV capabilities, but no VFs are published\n"); 58832a47e72SYuval Mintz kfree(cdev->p_iov_info); 58932a47e72SYuval Mintz cdev->p_iov_info = NULL; 59032a47e72SYuval Mintz return 0; 59132a47e72SYuval Mintz } 59232a47e72SYuval Mintz 5939c79ddaaSMintz, Yuval /* First VF index based on offset is tricky: 5949c79ddaaSMintz, Yuval * - If ARI is supported [likely], offset - (16 - pf_id) would 5959c79ddaaSMintz, Yuval * provide the number for eng0. 2nd engine Vfs would begin 59632a47e72SYuval Mintz * after the first engine's VFs. 5979c79ddaaSMintz, Yuval * - If !ARI, VFs would start on next device. 5989c79ddaaSMintz, Yuval * so offset - (256 - pf_id) would provide the number. 5999c79ddaaSMintz, Yuval * Utilize the fact that (256 - pf_id) is achieved only by later 6008ac1ed79SJoe Perches * to differentiate between the two. 60132a47e72SYuval Mintz */ 6029c79ddaaSMintz, Yuval 6039c79ddaaSMintz, Yuval if (p_hwfn->cdev->p_iov_info->offset < (256 - p_hwfn->abs_pf_id)) { 6049c79ddaaSMintz, Yuval u32 first = p_hwfn->cdev->p_iov_info->offset + 60532a47e72SYuval Mintz p_hwfn->abs_pf_id - 16; 6069c79ddaaSMintz, Yuval 6079c79ddaaSMintz, Yuval cdev->p_iov_info->first_vf_in_pf = first; 6089c79ddaaSMintz, Yuval 60932a47e72SYuval Mintz if (QED_PATH_ID(p_hwfn)) 61032a47e72SYuval Mintz cdev->p_iov_info->first_vf_in_pf -= MAX_NUM_VFS_BB; 6119c79ddaaSMintz, Yuval } else { 6129c79ddaaSMintz, Yuval u32 first = p_hwfn->cdev->p_iov_info->offset + 6139c79ddaaSMintz, Yuval p_hwfn->abs_pf_id - 256; 6149c79ddaaSMintz, Yuval 6159c79ddaaSMintz, Yuval cdev->p_iov_info->first_vf_in_pf = first; 6169c79ddaaSMintz, Yuval } 61732a47e72SYuval Mintz 61832a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 61932a47e72SYuval Mintz "First VF in hwfn 0x%08x\n", 62032a47e72SYuval Mintz cdev->p_iov_info->first_vf_in_pf); 62132a47e72SYuval Mintz 62232a47e72SYuval Mintz return 0; 62332a47e72SYuval Mintz } 62432a47e72SYuval Mintz 6257eff82b0SYuval Mintz bool _qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, 6267eff82b0SYuval Mintz int vfid, bool b_fail_malicious) 62737bff2b9SYuval Mintz { 62837bff2b9SYuval Mintz /* Check PF supports sriov */ 629b0409fa0SYuval Mintz if (IS_VF(p_hwfn->cdev) || !IS_QED_SRIOV(p_hwfn->cdev) || 630b0409fa0SYuval Mintz !IS_PF_SRIOV_ALLOC(p_hwfn)) 63137bff2b9SYuval Mintz return false; 63237bff2b9SYuval Mintz 63337bff2b9SYuval Mintz /* Check VF validity */ 6347eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious)) 63537bff2b9SYuval Mintz return false; 63637bff2b9SYuval Mintz 63737bff2b9SYuval Mintz return true; 63837bff2b9SYuval Mintz } 63937bff2b9SYuval Mintz 6407eff82b0SYuval Mintz bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid) 6417eff82b0SYuval Mintz { 6427eff82b0SYuval Mintz return _qed_iov_pf_sanity_check(p_hwfn, vfid, true); 6437eff82b0SYuval Mintz } 6447eff82b0SYuval Mintz 6450b55e27dSYuval Mintz static void qed_iov_set_vf_to_disable(struct qed_dev *cdev, 6460b55e27dSYuval Mintz u16 rel_vf_id, u8 to_disable) 6470b55e27dSYuval Mintz { 6480b55e27dSYuval Mintz struct qed_vf_info *vf; 6490b55e27dSYuval Mintz int i; 6500b55e27dSYuval Mintz 6510b55e27dSYuval Mintz for_each_hwfn(cdev, i) { 6520b55e27dSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 6530b55e27dSYuval Mintz 6540b55e27dSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, false); 6550b55e27dSYuval Mintz if (!vf) 6560b55e27dSYuval Mintz continue; 6570b55e27dSYuval Mintz 6580b55e27dSYuval Mintz vf->to_disable = to_disable; 6590b55e27dSYuval Mintz } 6600b55e27dSYuval Mintz } 6610b55e27dSYuval Mintz 662ba56947aSBaoyou Xie static void qed_iov_set_vfs_to_disable(struct qed_dev *cdev, u8 to_disable) 6630b55e27dSYuval Mintz { 6640b55e27dSYuval Mintz u16 i; 6650b55e27dSYuval Mintz 6660b55e27dSYuval Mintz if (!IS_QED_SRIOV(cdev)) 6670b55e27dSYuval Mintz return; 6680b55e27dSYuval Mintz 6690b55e27dSYuval Mintz for (i = 0; i < cdev->p_iov_info->total_vfs; i++) 6700b55e27dSYuval Mintz qed_iov_set_vf_to_disable(cdev, i, to_disable); 6710b55e27dSYuval Mintz } 6720b55e27dSYuval Mintz 6731408cc1fSYuval Mintz static void qed_iov_vf_pglue_clear_err(struct qed_hwfn *p_hwfn, 6741408cc1fSYuval Mintz struct qed_ptt *p_ptt, u8 abs_vfid) 6751408cc1fSYuval Mintz { 6761408cc1fSYuval Mintz qed_wr(p_hwfn, p_ptt, 6771408cc1fSYuval Mintz PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR + (abs_vfid >> 5) * 4, 6781408cc1fSYuval Mintz 1 << (abs_vfid & 0x1f)); 6791408cc1fSYuval Mintz } 6801408cc1fSYuval Mintz 681dacd88d6SYuval Mintz static void qed_iov_vf_igu_reset(struct qed_hwfn *p_hwfn, 682dacd88d6SYuval Mintz struct qed_ptt *p_ptt, struct qed_vf_info *vf) 683dacd88d6SYuval Mintz { 684dacd88d6SYuval Mintz int i; 685dacd88d6SYuval Mintz 686dacd88d6SYuval Mintz /* Set VF masks and configuration - pretend */ 687dacd88d6SYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) vf->concrete_fid); 688dacd88d6SYuval Mintz 689dacd88d6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_STATISTIC_NUM_VF_MSG_SENT, 0); 690dacd88d6SYuval Mintz 691dacd88d6SYuval Mintz /* unpretend */ 692dacd88d6SYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 693dacd88d6SYuval Mintz 694dacd88d6SYuval Mintz /* iterate over all queues, clear sb consumer */ 695b2b897ebSYuval Mintz for (i = 0; i < vf->num_sbs; i++) 696b2b897ebSYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, 697b2b897ebSYuval Mintz vf->igu_sbs[i], 698b2b897ebSYuval Mintz vf->opaque_fid, true); 699dacd88d6SYuval Mintz } 700dacd88d6SYuval Mintz 7010b55e27dSYuval Mintz static void qed_iov_vf_igu_set_int(struct qed_hwfn *p_hwfn, 7020b55e27dSYuval Mintz struct qed_ptt *p_ptt, 7030b55e27dSYuval Mintz struct qed_vf_info *vf, bool enable) 7040b55e27dSYuval Mintz { 7050b55e27dSYuval Mintz u32 igu_vf_conf; 7060b55e27dSYuval Mintz 7070b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) vf->concrete_fid); 7080b55e27dSYuval Mintz 7090b55e27dSYuval Mintz igu_vf_conf = qed_rd(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION); 7100b55e27dSYuval Mintz 7110b55e27dSYuval Mintz if (enable) 7120b55e27dSYuval Mintz igu_vf_conf |= IGU_VF_CONF_MSI_MSIX_EN; 7130b55e27dSYuval Mintz else 7140b55e27dSYuval Mintz igu_vf_conf &= ~IGU_VF_CONF_MSI_MSIX_EN; 7150b55e27dSYuval Mintz 7160b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION, igu_vf_conf); 7170b55e27dSYuval Mintz 7180b55e27dSYuval Mintz /* unpretend */ 7190b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 7200b55e27dSYuval Mintz } 7210b55e27dSYuval Mintz 72288072fd4SMintz, Yuval static int 72388072fd4SMintz, Yuval qed_iov_enable_vf_access_msix(struct qed_hwfn *p_hwfn, 72488072fd4SMintz, Yuval struct qed_ptt *p_ptt, u8 abs_vf_id, u8 num_sbs) 72588072fd4SMintz, Yuval { 72688072fd4SMintz, Yuval u8 current_max = 0; 72788072fd4SMintz, Yuval int i; 72888072fd4SMintz, Yuval 72988072fd4SMintz, Yuval /* For AH onward, configuration is per-PF. Find maximum of all 73088072fd4SMintz, Yuval * the currently enabled child VFs, and set the number to be that. 73188072fd4SMintz, Yuval */ 73288072fd4SMintz, Yuval if (!QED_IS_BB(p_hwfn->cdev)) { 73388072fd4SMintz, Yuval qed_for_each_vf(p_hwfn, i) { 73488072fd4SMintz, Yuval struct qed_vf_info *p_vf; 73588072fd4SMintz, Yuval 73688072fd4SMintz, Yuval p_vf = qed_iov_get_vf_info(p_hwfn, (u16)i, true); 73788072fd4SMintz, Yuval if (!p_vf) 73888072fd4SMintz, Yuval continue; 73988072fd4SMintz, Yuval 74088072fd4SMintz, Yuval current_max = max_t(u8, current_max, p_vf->num_sbs); 74188072fd4SMintz, Yuval } 74288072fd4SMintz, Yuval } 74388072fd4SMintz, Yuval 74488072fd4SMintz, Yuval if (num_sbs > current_max) 74588072fd4SMintz, Yuval return qed_mcp_config_vf_msix(p_hwfn, p_ptt, 74688072fd4SMintz, Yuval abs_vf_id, num_sbs); 74788072fd4SMintz, Yuval 74888072fd4SMintz, Yuval return 0; 74988072fd4SMintz, Yuval } 75088072fd4SMintz, Yuval 7511408cc1fSYuval Mintz static int qed_iov_enable_vf_access(struct qed_hwfn *p_hwfn, 7521408cc1fSYuval Mintz struct qed_ptt *p_ptt, 7531408cc1fSYuval Mintz struct qed_vf_info *vf) 7541408cc1fSYuval Mintz { 7551408cc1fSYuval Mintz u32 igu_vf_conf = IGU_VF_CONF_FUNC_EN; 7561408cc1fSYuval Mintz int rc; 7571408cc1fSYuval Mintz 7584e9b2a67SMintz, Yuval /* It's possible VF was previously considered malicious - 7594e9b2a67SMintz, Yuval * clear the indication even if we're only going to disable VF. 7604e9b2a67SMintz, Yuval */ 7614e9b2a67SMintz, Yuval vf->b_malicious = false; 7624e9b2a67SMintz, Yuval 7630b55e27dSYuval Mintz if (vf->to_disable) 7640b55e27dSYuval Mintz return 0; 7650b55e27dSYuval Mintz 7661408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 7671408cc1fSYuval Mintz QED_MSG_IOV, 7681408cc1fSYuval Mintz "Enable internal access for vf %x [abs %x]\n", 7691408cc1fSYuval Mintz vf->abs_vf_id, QED_VF_ABS_ID(p_hwfn, vf)); 7701408cc1fSYuval Mintz 7711408cc1fSYuval Mintz qed_iov_vf_pglue_clear_err(p_hwfn, p_ptt, QED_VF_ABS_ID(p_hwfn, vf)); 7721408cc1fSYuval Mintz 773b2b897ebSYuval Mintz qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf); 774b2b897ebSYuval Mintz 77588072fd4SMintz, Yuval rc = qed_iov_enable_vf_access_msix(p_hwfn, p_ptt, 77688072fd4SMintz, Yuval vf->abs_vf_id, vf->num_sbs); 7771408cc1fSYuval Mintz if (rc) 7781408cc1fSYuval Mintz return rc; 7791408cc1fSYuval Mintz 7801408cc1fSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) vf->concrete_fid); 7811408cc1fSYuval Mintz 7821408cc1fSYuval Mintz SET_FIELD(igu_vf_conf, IGU_VF_CONF_PARENT, p_hwfn->rel_pf_id); 7831408cc1fSYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_VF_CONFIGURATION_RT_OFFSET, igu_vf_conf); 7841408cc1fSYuval Mintz 7851408cc1fSYuval Mintz qed_init_run(p_hwfn, p_ptt, PHASE_VF, vf->abs_vf_id, 7861408cc1fSYuval Mintz p_hwfn->hw_info.hw_mode); 7871408cc1fSYuval Mintz 7881408cc1fSYuval Mintz /* unpretend */ 7891408cc1fSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 7901408cc1fSYuval Mintz 7911408cc1fSYuval Mintz vf->state = VF_FREE; 7921408cc1fSYuval Mintz 7931408cc1fSYuval Mintz return rc; 7941408cc1fSYuval Mintz } 7951408cc1fSYuval Mintz 7960b55e27dSYuval Mintz /** 7970b55e27dSYuval Mintz * @brief qed_iov_config_perm_table - configure the permission 7980b55e27dSYuval Mintz * zone table. 7990b55e27dSYuval Mintz * In E4, queue zone permission table size is 320x9. There 8000b55e27dSYuval Mintz * are 320 VF queues for single engine device (256 for dual 8010b55e27dSYuval Mintz * engine device), and each entry has the following format: 8020b55e27dSYuval Mintz * {Valid, VF[7:0]} 8030b55e27dSYuval Mintz * @param p_hwfn 8040b55e27dSYuval Mintz * @param p_ptt 8050b55e27dSYuval Mintz * @param vf 8060b55e27dSYuval Mintz * @param enable 8070b55e27dSYuval Mintz */ 8080b55e27dSYuval Mintz static void qed_iov_config_perm_table(struct qed_hwfn *p_hwfn, 8090b55e27dSYuval Mintz struct qed_ptt *p_ptt, 8100b55e27dSYuval Mintz struct qed_vf_info *vf, u8 enable) 8110b55e27dSYuval Mintz { 8120b55e27dSYuval Mintz u32 reg_addr, val; 8130b55e27dSYuval Mintz u16 qzone_id = 0; 8140b55e27dSYuval Mintz int qid; 8150b55e27dSYuval Mintz 8160b55e27dSYuval Mintz for (qid = 0; qid < vf->num_rxqs; qid++) { 8170b55e27dSYuval Mintz qed_fw_l2_queue(p_hwfn, vf->vf_queues[qid].fw_rx_qid, 8180b55e27dSYuval Mintz &qzone_id); 8190b55e27dSYuval Mintz 8200b55e27dSYuval Mintz reg_addr = PSWHST_REG_ZONE_PERMISSION_TABLE + qzone_id * 4; 8211a635e48SYuval Mintz val = enable ? (vf->abs_vf_id | BIT(8)) : 0; 8220b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, reg_addr, val); 8230b55e27dSYuval Mintz } 8240b55e27dSYuval Mintz } 8250b55e27dSYuval Mintz 826dacd88d6SYuval Mintz static void qed_iov_enable_vf_traffic(struct qed_hwfn *p_hwfn, 827dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 828dacd88d6SYuval Mintz struct qed_vf_info *vf) 829dacd88d6SYuval Mintz { 830dacd88d6SYuval Mintz /* Reset vf in IGU - interrupts are still disabled */ 831dacd88d6SYuval Mintz qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf); 832dacd88d6SYuval Mintz 833dacd88d6SYuval Mintz qed_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 1); 834dacd88d6SYuval Mintz 835dacd88d6SYuval Mintz /* Permission Table */ 836dacd88d6SYuval Mintz qed_iov_config_perm_table(p_hwfn, p_ptt, vf, true); 837dacd88d6SYuval Mintz } 838dacd88d6SYuval Mintz 8391408cc1fSYuval Mintz static u8 qed_iov_alloc_vf_igu_sbs(struct qed_hwfn *p_hwfn, 8401408cc1fSYuval Mintz struct qed_ptt *p_ptt, 8411408cc1fSYuval Mintz struct qed_vf_info *vf, u16 num_rx_queues) 8421408cc1fSYuval Mintz { 84309b6b147SMintz, Yuval struct qed_igu_block *p_block; 84409b6b147SMintz, Yuval struct cau_sb_entry sb_entry; 84509b6b147SMintz, Yuval int qid = 0; 8461408cc1fSYuval Mintz u32 val = 0; 8471408cc1fSYuval Mintz 848726fdbe9SMintz, Yuval if (num_rx_queues > p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov) 849726fdbe9SMintz, Yuval num_rx_queues = p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov; 850726fdbe9SMintz, Yuval p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov -= num_rx_queues; 8511408cc1fSYuval Mintz 8521408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER, vf->abs_vf_id); 8531408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VALID, 1); 8541408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, 0); 8551408cc1fSYuval Mintz 85609b6b147SMintz, Yuval for (qid = 0; qid < num_rx_queues; qid++) { 85709b6b147SMintz, Yuval p_block = qed_get_igu_free_sb(p_hwfn, false); 85809b6b147SMintz, Yuval vf->igu_sbs[qid] = p_block->igu_sb_id; 85909b6b147SMintz, Yuval p_block->status &= ~QED_IGU_STATUS_FREE; 8601408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER, qid); 8611408cc1fSYuval Mintz 8621408cc1fSYuval Mintz qed_wr(p_hwfn, p_ptt, 86309b6b147SMintz, Yuval IGU_REG_MAPPING_MEMORY + 86409b6b147SMintz, Yuval sizeof(u32) * p_block->igu_sb_id, val); 8651408cc1fSYuval Mintz 8661408cc1fSYuval Mintz /* Configure igu sb in CAU which were marked valid */ 8671408cc1fSYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, 86809b6b147SMintz, Yuval p_hwfn->rel_pf_id, vf->abs_vf_id, 1); 8691408cc1fSYuval Mintz qed_dmae_host2grc(p_hwfn, p_ptt, 8701408cc1fSYuval Mintz (u64)(uintptr_t)&sb_entry, 8711408cc1fSYuval Mintz CAU_REG_SB_VAR_MEMORY + 87209b6b147SMintz, Yuval p_block->igu_sb_id * sizeof(u64), 2, 0); 8731408cc1fSYuval Mintz } 8741408cc1fSYuval Mintz 8751408cc1fSYuval Mintz vf->num_sbs = (u8) num_rx_queues; 8761408cc1fSYuval Mintz 8771408cc1fSYuval Mintz return vf->num_sbs; 8781408cc1fSYuval Mintz } 8791408cc1fSYuval Mintz 8800b55e27dSYuval Mintz static void qed_iov_free_vf_igu_sbs(struct qed_hwfn *p_hwfn, 8810b55e27dSYuval Mintz struct qed_ptt *p_ptt, 8820b55e27dSYuval Mintz struct qed_vf_info *vf) 8830b55e27dSYuval Mintz { 8840b55e27dSYuval Mintz struct qed_igu_info *p_info = p_hwfn->hw_info.p_igu_info; 8850b55e27dSYuval Mintz int idx, igu_id; 8860b55e27dSYuval Mintz u32 addr, val; 8870b55e27dSYuval Mintz 8880b55e27dSYuval Mintz /* Invalidate igu CAM lines and mark them as free */ 8890b55e27dSYuval Mintz for (idx = 0; idx < vf->num_sbs; idx++) { 8900b55e27dSYuval Mintz igu_id = vf->igu_sbs[idx]; 8910b55e27dSYuval Mintz addr = IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_id; 8920b55e27dSYuval Mintz 8930b55e27dSYuval Mintz val = qed_rd(p_hwfn, p_ptt, addr); 8940b55e27dSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0); 8950b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, addr, val); 8960b55e27dSYuval Mintz 897d749dd0dSMintz, Yuval p_info->entry[igu_id].status |= QED_IGU_STATUS_FREE; 898726fdbe9SMintz, Yuval p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov++; 8990b55e27dSYuval Mintz } 9000b55e27dSYuval Mintz 9010b55e27dSYuval Mintz vf->num_sbs = 0; 9020b55e27dSYuval Mintz } 9030b55e27dSYuval Mintz 90433b2fbd0SMintz, Yuval static void qed_iov_set_link(struct qed_hwfn *p_hwfn, 90533b2fbd0SMintz, Yuval u16 vfid, 90633b2fbd0SMintz, Yuval struct qed_mcp_link_params *params, 90733b2fbd0SMintz, Yuval struct qed_mcp_link_state *link, 90833b2fbd0SMintz, Yuval struct qed_mcp_link_capabilities *p_caps) 90933b2fbd0SMintz, Yuval { 91033b2fbd0SMintz, Yuval struct qed_vf_info *p_vf = qed_iov_get_vf_info(p_hwfn, 91133b2fbd0SMintz, Yuval vfid, 91233b2fbd0SMintz, Yuval false); 91333b2fbd0SMintz, Yuval struct qed_bulletin_content *p_bulletin; 91433b2fbd0SMintz, Yuval 91533b2fbd0SMintz, Yuval if (!p_vf) 91633b2fbd0SMintz, Yuval return; 91733b2fbd0SMintz, Yuval 91833b2fbd0SMintz, Yuval p_bulletin = p_vf->bulletin.p_virt; 91933b2fbd0SMintz, Yuval p_bulletin->req_autoneg = params->speed.autoneg; 92033b2fbd0SMintz, Yuval p_bulletin->req_adv_speed = params->speed.advertised_speeds; 92133b2fbd0SMintz, Yuval p_bulletin->req_forced_speed = params->speed.forced_speed; 92233b2fbd0SMintz, Yuval p_bulletin->req_autoneg_pause = params->pause.autoneg; 92333b2fbd0SMintz, Yuval p_bulletin->req_forced_rx = params->pause.forced_rx; 92433b2fbd0SMintz, Yuval p_bulletin->req_forced_tx = params->pause.forced_tx; 92533b2fbd0SMintz, Yuval p_bulletin->req_loopback = params->loopback_mode; 92633b2fbd0SMintz, Yuval 92733b2fbd0SMintz, Yuval p_bulletin->link_up = link->link_up; 92833b2fbd0SMintz, Yuval p_bulletin->speed = link->speed; 92933b2fbd0SMintz, Yuval p_bulletin->full_duplex = link->full_duplex; 93033b2fbd0SMintz, Yuval p_bulletin->autoneg = link->an; 93133b2fbd0SMintz, Yuval p_bulletin->autoneg_complete = link->an_complete; 93233b2fbd0SMintz, Yuval p_bulletin->parallel_detection = link->parallel_detection; 93333b2fbd0SMintz, Yuval p_bulletin->pfc_enabled = link->pfc_enabled; 93433b2fbd0SMintz, Yuval p_bulletin->partner_adv_speed = link->partner_adv_speed; 93533b2fbd0SMintz, Yuval p_bulletin->partner_tx_flow_ctrl_en = link->partner_tx_flow_ctrl_en; 93633b2fbd0SMintz, Yuval p_bulletin->partner_rx_flow_ctrl_en = link->partner_rx_flow_ctrl_en; 93733b2fbd0SMintz, Yuval p_bulletin->partner_adv_pause = link->partner_adv_pause; 93833b2fbd0SMintz, Yuval p_bulletin->sfp_tx_fault = link->sfp_tx_fault; 93933b2fbd0SMintz, Yuval 94033b2fbd0SMintz, Yuval p_bulletin->capability_speed = p_caps->speed_capabilities; 94133b2fbd0SMintz, Yuval } 94233b2fbd0SMintz, Yuval 9431408cc1fSYuval Mintz static int qed_iov_init_hw_for_vf(struct qed_hwfn *p_hwfn, 9441408cc1fSYuval Mintz struct qed_ptt *p_ptt, 9453da7a37aSMintz, Yuval struct qed_iov_vf_init_params *p_params) 9461408cc1fSYuval Mintz { 94733b2fbd0SMintz, Yuval struct qed_mcp_link_capabilities link_caps; 94833b2fbd0SMintz, Yuval struct qed_mcp_link_params link_params; 94933b2fbd0SMintz, Yuval struct qed_mcp_link_state link_state; 9501408cc1fSYuval Mintz u8 num_of_vf_avaiable_chains = 0; 9511408cc1fSYuval Mintz struct qed_vf_info *vf = NULL; 9523da7a37aSMintz, Yuval u16 qid, num_irqs; 9531408cc1fSYuval Mintz int rc = 0; 9541408cc1fSYuval Mintz u32 cids; 9551408cc1fSYuval Mintz u8 i; 9561408cc1fSYuval Mintz 9573da7a37aSMintz, Yuval vf = qed_iov_get_vf_info(p_hwfn, p_params->rel_vf_id, false); 9581408cc1fSYuval Mintz if (!vf) { 9591408cc1fSYuval Mintz DP_ERR(p_hwfn, "qed_iov_init_hw_for_vf : vf is NULL\n"); 9601408cc1fSYuval Mintz return -EINVAL; 9611408cc1fSYuval Mintz } 9621408cc1fSYuval Mintz 9631408cc1fSYuval Mintz if (vf->b_init) { 9643da7a37aSMintz, Yuval DP_NOTICE(p_hwfn, "VF[%d] is already active.\n", 9653da7a37aSMintz, Yuval p_params->rel_vf_id); 9661408cc1fSYuval Mintz return -EINVAL; 9671408cc1fSYuval Mintz } 9681408cc1fSYuval Mintz 9693da7a37aSMintz, Yuval /* Perform sanity checking on the requested queue_id */ 9703da7a37aSMintz, Yuval for (i = 0; i < p_params->num_queues; i++) { 9713da7a37aSMintz, Yuval u16 min_vf_qzone = FEAT_NUM(p_hwfn, QED_PF_L2_QUE); 9723da7a37aSMintz, Yuval u16 max_vf_qzone = min_vf_qzone + 9733da7a37aSMintz, Yuval FEAT_NUM(p_hwfn, QED_VF_L2_QUE) - 1; 9743da7a37aSMintz, Yuval 9753da7a37aSMintz, Yuval qid = p_params->req_rx_queue[i]; 9763da7a37aSMintz, Yuval if (qid < min_vf_qzone || qid > max_vf_qzone) { 9773da7a37aSMintz, Yuval DP_NOTICE(p_hwfn, 9783da7a37aSMintz, Yuval "Can't enable Rx qid [%04x] for VF[%d]: qids [0x%04x,...,0x%04x] available\n", 9793da7a37aSMintz, Yuval qid, 9803da7a37aSMintz, Yuval p_params->rel_vf_id, 9813da7a37aSMintz, Yuval min_vf_qzone, max_vf_qzone); 9823da7a37aSMintz, Yuval return -EINVAL; 9833da7a37aSMintz, Yuval } 9843da7a37aSMintz, Yuval 9853da7a37aSMintz, Yuval qid = p_params->req_tx_queue[i]; 9863da7a37aSMintz, Yuval if (qid > max_vf_qzone) { 9873da7a37aSMintz, Yuval DP_NOTICE(p_hwfn, 9883da7a37aSMintz, Yuval "Can't enable Tx qid [%04x] for VF[%d]: max qid 0x%04x\n", 9893da7a37aSMintz, Yuval qid, p_params->rel_vf_id, max_vf_qzone); 9903da7a37aSMintz, Yuval return -EINVAL; 9913da7a37aSMintz, Yuval } 9923da7a37aSMintz, Yuval 9933da7a37aSMintz, Yuval /* If client *really* wants, Tx qid can be shared with PF */ 9943da7a37aSMintz, Yuval if (qid < min_vf_qzone) 9953da7a37aSMintz, Yuval DP_VERBOSE(p_hwfn, 9963da7a37aSMintz, Yuval QED_MSG_IOV, 9973da7a37aSMintz, Yuval "VF[%d] is using PF qid [0x%04x] for Txq[0x%02x]\n", 9983da7a37aSMintz, Yuval p_params->rel_vf_id, qid, i); 9993da7a37aSMintz, Yuval } 10003da7a37aSMintz, Yuval 10011408cc1fSYuval Mintz /* Limit number of queues according to number of CIDs */ 10021408cc1fSYuval Mintz qed_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH, &cids); 10031408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 10041408cc1fSYuval Mintz QED_MSG_IOV, 10051408cc1fSYuval Mintz "VF[%d] - requesting to initialize for 0x%04x queues [0x%04x CIDs available]\n", 10063da7a37aSMintz, Yuval vf->relative_vf_id, p_params->num_queues, (u16)cids); 10073da7a37aSMintz, Yuval num_irqs = min_t(u16, p_params->num_queues, ((u16)cids)); 10081408cc1fSYuval Mintz 10091408cc1fSYuval Mintz num_of_vf_avaiable_chains = qed_iov_alloc_vf_igu_sbs(p_hwfn, 10101408cc1fSYuval Mintz p_ptt, 10113da7a37aSMintz, Yuval vf, num_irqs); 10121408cc1fSYuval Mintz if (!num_of_vf_avaiable_chains) { 10131408cc1fSYuval Mintz DP_ERR(p_hwfn, "no available igu sbs\n"); 10141408cc1fSYuval Mintz return -ENOMEM; 10151408cc1fSYuval Mintz } 10161408cc1fSYuval Mintz 10171408cc1fSYuval Mintz /* Choose queue number and index ranges */ 10181408cc1fSYuval Mintz vf->num_rxqs = num_of_vf_avaiable_chains; 10191408cc1fSYuval Mintz vf->num_txqs = num_of_vf_avaiable_chains; 10201408cc1fSYuval Mintz 10211408cc1fSYuval Mintz for (i = 0; i < vf->num_rxqs; i++) { 10223da7a37aSMintz, Yuval struct qed_vf_q_info *p_queue = &vf->vf_queues[i]; 10231408cc1fSYuval Mintz 10243da7a37aSMintz, Yuval p_queue->fw_rx_qid = p_params->req_rx_queue[i]; 10253da7a37aSMintz, Yuval p_queue->fw_tx_qid = p_params->req_tx_queue[i]; 10261408cc1fSYuval Mintz 10271408cc1fSYuval Mintz /* CIDs are per-VF, so no problem having them 0-based. */ 10283da7a37aSMintz, Yuval p_queue->fw_cid = i; 10291408cc1fSYuval Mintz 10301408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 10313da7a37aSMintz, Yuval "VF[%d] - Q[%d] SB %04x, qid [Rx %04x Tx %04x] CID %04x\n", 10323da7a37aSMintz, Yuval vf->relative_vf_id, 10333da7a37aSMintz, Yuval i, vf->igu_sbs[i], 10343da7a37aSMintz, Yuval p_queue->fw_rx_qid, 10353da7a37aSMintz, Yuval p_queue->fw_tx_qid, p_queue->fw_cid); 10361408cc1fSYuval Mintz } 10373da7a37aSMintz, Yuval 103833b2fbd0SMintz, Yuval /* Update the link configuration in bulletin */ 103933b2fbd0SMintz, Yuval memcpy(&link_params, qed_mcp_get_link_params(p_hwfn), 104033b2fbd0SMintz, Yuval sizeof(link_params)); 104133b2fbd0SMintz, Yuval memcpy(&link_state, qed_mcp_get_link_state(p_hwfn), sizeof(link_state)); 104233b2fbd0SMintz, Yuval memcpy(&link_caps, qed_mcp_get_link_capabilities(p_hwfn), 104333b2fbd0SMintz, Yuval sizeof(link_caps)); 104433b2fbd0SMintz, Yuval qed_iov_set_link(p_hwfn, p_params->rel_vf_id, 104533b2fbd0SMintz, Yuval &link_params, &link_state, &link_caps); 104633b2fbd0SMintz, Yuval 10471408cc1fSYuval Mintz rc = qed_iov_enable_vf_access(p_hwfn, p_ptt, vf); 10481408cc1fSYuval Mintz if (!rc) { 10491408cc1fSYuval Mintz vf->b_init = true; 10501408cc1fSYuval Mintz 10511408cc1fSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) 10521408cc1fSYuval Mintz p_hwfn->cdev->p_iov_info->num_vfs++; 10531408cc1fSYuval Mintz } 10541408cc1fSYuval Mintz 10551408cc1fSYuval Mintz return rc; 10561408cc1fSYuval Mintz } 10571408cc1fSYuval Mintz 10580b55e27dSYuval Mintz static int qed_iov_release_hw_for_vf(struct qed_hwfn *p_hwfn, 10590b55e27dSYuval Mintz struct qed_ptt *p_ptt, u16 rel_vf_id) 10600b55e27dSYuval Mintz { 1061079d20a6SManish Chopra struct qed_mcp_link_capabilities caps; 1062079d20a6SManish Chopra struct qed_mcp_link_params params; 1063079d20a6SManish Chopra struct qed_mcp_link_state link; 10640b55e27dSYuval Mintz struct qed_vf_info *vf = NULL; 10650b55e27dSYuval Mintz 10660b55e27dSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true); 10670b55e27dSYuval Mintz if (!vf) { 10680b55e27dSYuval Mintz DP_ERR(p_hwfn, "qed_iov_release_hw_for_vf : vf is NULL\n"); 10690b55e27dSYuval Mintz return -EINVAL; 10700b55e27dSYuval Mintz } 10710b55e27dSYuval Mintz 107236558c3dSYuval Mintz if (vf->bulletin.p_virt) 107336558c3dSYuval Mintz memset(vf->bulletin.p_virt, 0, sizeof(*vf->bulletin.p_virt)); 107436558c3dSYuval Mintz 107536558c3dSYuval Mintz memset(&vf->p_vf_info, 0, sizeof(vf->p_vf_info)); 107636558c3dSYuval Mintz 1077079d20a6SManish Chopra /* Get the link configuration back in bulletin so 1078079d20a6SManish Chopra * that when VFs are re-enabled they get the actual 1079079d20a6SManish Chopra * link configuration. 1080079d20a6SManish Chopra */ 1081079d20a6SManish Chopra memcpy(¶ms, qed_mcp_get_link_params(p_hwfn), sizeof(params)); 1082079d20a6SManish Chopra memcpy(&link, qed_mcp_get_link_state(p_hwfn), sizeof(link)); 1083079d20a6SManish Chopra memcpy(&caps, qed_mcp_get_link_capabilities(p_hwfn), sizeof(caps)); 1084079d20a6SManish Chopra qed_iov_set_link(p_hwfn, rel_vf_id, ¶ms, &link, &caps); 1085079d20a6SManish Chopra 10861fe614d1SYuval Mintz /* Forget the VF's acquisition message */ 10871fe614d1SYuval Mintz memset(&vf->acquire, 0, sizeof(vf->acquire)); 10880b55e27dSYuval Mintz 10890b55e27dSYuval Mintz /* disablng interrupts and resetting permission table was done during 10900b55e27dSYuval Mintz * vf-close, however, we could get here without going through vf_close 10910b55e27dSYuval Mintz */ 10920b55e27dSYuval Mintz /* Disable Interrupts for VF */ 10930b55e27dSYuval Mintz qed_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0); 10940b55e27dSYuval Mintz 10950b55e27dSYuval Mintz /* Reset Permission table */ 10960b55e27dSYuval Mintz qed_iov_config_perm_table(p_hwfn, p_ptt, vf, 0); 10970b55e27dSYuval Mintz 10980b55e27dSYuval Mintz vf->num_rxqs = 0; 10990b55e27dSYuval Mintz vf->num_txqs = 0; 11000b55e27dSYuval Mintz qed_iov_free_vf_igu_sbs(p_hwfn, p_ptt, vf); 11010b55e27dSYuval Mintz 11020b55e27dSYuval Mintz if (vf->b_init) { 11030b55e27dSYuval Mintz vf->b_init = false; 11040b55e27dSYuval Mintz 11050b55e27dSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) 11060b55e27dSYuval Mintz p_hwfn->cdev->p_iov_info->num_vfs--; 11070b55e27dSYuval Mintz } 11080b55e27dSYuval Mintz 11090b55e27dSYuval Mintz return 0; 11100b55e27dSYuval Mintz } 11110b55e27dSYuval Mintz 111237bff2b9SYuval Mintz static bool qed_iov_tlv_supported(u16 tlvtype) 111337bff2b9SYuval Mintz { 111437bff2b9SYuval Mintz return CHANNEL_TLV_NONE < tlvtype && tlvtype < CHANNEL_TLV_MAX; 111537bff2b9SYuval Mintz } 111637bff2b9SYuval Mintz 111737bff2b9SYuval Mintz /* place a given tlv on the tlv buffer, continuing current tlv list */ 111837bff2b9SYuval Mintz void *qed_add_tlv(struct qed_hwfn *p_hwfn, u8 **offset, u16 type, u16 length) 111937bff2b9SYuval Mintz { 112037bff2b9SYuval Mintz struct channel_tlv *tl = (struct channel_tlv *)*offset; 112137bff2b9SYuval Mintz 112237bff2b9SYuval Mintz tl->type = type; 112337bff2b9SYuval Mintz tl->length = length; 112437bff2b9SYuval Mintz 112537bff2b9SYuval Mintz /* Offset should keep pointing to next TLV (the end of the last) */ 112637bff2b9SYuval Mintz *offset += length; 112737bff2b9SYuval Mintz 112837bff2b9SYuval Mintz /* Return a pointer to the start of the added tlv */ 112937bff2b9SYuval Mintz return *offset - length; 113037bff2b9SYuval Mintz } 113137bff2b9SYuval Mintz 113237bff2b9SYuval Mintz /* list the types and lengths of the tlvs on the buffer */ 113337bff2b9SYuval Mintz void qed_dp_tlv_list(struct qed_hwfn *p_hwfn, void *tlvs_list) 113437bff2b9SYuval Mintz { 113537bff2b9SYuval Mintz u16 i = 1, total_length = 0; 113637bff2b9SYuval Mintz struct channel_tlv *tlv; 113737bff2b9SYuval Mintz 113837bff2b9SYuval Mintz do { 113937bff2b9SYuval Mintz tlv = (struct channel_tlv *)((u8 *)tlvs_list + total_length); 114037bff2b9SYuval Mintz 114137bff2b9SYuval Mintz /* output tlv */ 114237bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 114337bff2b9SYuval Mintz "TLV number %d: type %d, length %d\n", 114437bff2b9SYuval Mintz i, tlv->type, tlv->length); 114537bff2b9SYuval Mintz 114637bff2b9SYuval Mintz if (tlv->type == CHANNEL_TLV_LIST_END) 114737bff2b9SYuval Mintz return; 114837bff2b9SYuval Mintz 114937bff2b9SYuval Mintz /* Validate entry - protect against malicious VFs */ 115037bff2b9SYuval Mintz if (!tlv->length) { 115137bff2b9SYuval Mintz DP_NOTICE(p_hwfn, "TLV of length 0 found\n"); 115237bff2b9SYuval Mintz return; 115337bff2b9SYuval Mintz } 115437bff2b9SYuval Mintz 115537bff2b9SYuval Mintz total_length += tlv->length; 115637bff2b9SYuval Mintz 115737bff2b9SYuval Mintz if (total_length >= sizeof(struct tlv_buffer_size)) { 115837bff2b9SYuval Mintz DP_NOTICE(p_hwfn, "TLV ==> Buffer overflow\n"); 115937bff2b9SYuval Mintz return; 116037bff2b9SYuval Mintz } 116137bff2b9SYuval Mintz 116237bff2b9SYuval Mintz i++; 116337bff2b9SYuval Mintz } while (1); 116437bff2b9SYuval Mintz } 116537bff2b9SYuval Mintz 116637bff2b9SYuval Mintz static void qed_iov_send_response(struct qed_hwfn *p_hwfn, 116737bff2b9SYuval Mintz struct qed_ptt *p_ptt, 116837bff2b9SYuval Mintz struct qed_vf_info *p_vf, 116937bff2b9SYuval Mintz u16 length, u8 status) 117037bff2b9SYuval Mintz { 117137bff2b9SYuval Mintz struct qed_iov_vf_mbx *mbx = &p_vf->vf_mbx; 117237bff2b9SYuval Mintz struct qed_dmae_params params; 117337bff2b9SYuval Mintz u8 eng_vf_id; 117437bff2b9SYuval Mintz 117537bff2b9SYuval Mintz mbx->reply_virt->default_resp.hdr.status = status; 117637bff2b9SYuval Mintz 117737bff2b9SYuval Mintz qed_dp_tlv_list(p_hwfn, mbx->reply_virt); 117837bff2b9SYuval Mintz 117937bff2b9SYuval Mintz eng_vf_id = p_vf->abs_vf_id; 118037bff2b9SYuval Mintz 118137bff2b9SYuval Mintz memset(¶ms, 0, sizeof(struct qed_dmae_params)); 118237bff2b9SYuval Mintz params.flags = QED_DMAE_FLAG_VF_DST; 118337bff2b9SYuval Mintz params.dst_vfid = eng_vf_id; 118437bff2b9SYuval Mintz 118537bff2b9SYuval Mintz qed_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys + sizeof(u64), 118637bff2b9SYuval Mintz mbx->req_virt->first_tlv.reply_address + 118737bff2b9SYuval Mintz sizeof(u64), 118837bff2b9SYuval Mintz (sizeof(union pfvf_tlvs) - sizeof(u64)) / 4, 118937bff2b9SYuval Mintz ¶ms); 119037bff2b9SYuval Mintz 1191d9194081SMintz, Yuval /* Once PF copies the rc to the VF, the latter can continue 1192d9194081SMintz, Yuval * and send an additional message. So we have to make sure the 1193d9194081SMintz, Yuval * channel would be re-set to ready prior to that. 1194d9194081SMintz, Yuval */ 119537bff2b9SYuval Mintz REG_WR(p_hwfn, 119637bff2b9SYuval Mintz GTT_BAR0_MAP_REG_USDM_RAM + 119737bff2b9SYuval Mintz USTORM_VF_PF_CHANNEL_READY_OFFSET(eng_vf_id), 1); 1198d9194081SMintz, Yuval 1199d9194081SMintz, Yuval qed_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys, 1200d9194081SMintz, Yuval mbx->req_virt->first_tlv.reply_address, 1201d9194081SMintz, Yuval sizeof(u64) / 4, ¶ms); 120237bff2b9SYuval Mintz } 120337bff2b9SYuval Mintz 1204dacd88d6SYuval Mintz static u16 qed_iov_vport_to_tlv(struct qed_hwfn *p_hwfn, 1205dacd88d6SYuval Mintz enum qed_iov_vport_update_flag flag) 1206dacd88d6SYuval Mintz { 1207dacd88d6SYuval Mintz switch (flag) { 1208dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_ACTIVATE: 1209dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_ACTIVATE; 121017b235c1SYuval Mintz case QED_IOV_VP_UPDATE_VLAN_STRIP: 121117b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP; 121217b235c1SYuval Mintz case QED_IOV_VP_UPDATE_TX_SWITCH: 121317b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; 1214dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_MCAST: 1215dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_MCAST; 1216dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_ACCEPT_PARAM: 1217dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; 1218dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_RSS: 1219dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_RSS; 122017b235c1SYuval Mintz case QED_IOV_VP_UPDATE_ACCEPT_ANY_VLAN: 122117b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; 122217b235c1SYuval Mintz case QED_IOV_VP_UPDATE_SGE_TPA: 122317b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_SGE_TPA; 1224dacd88d6SYuval Mintz default: 1225dacd88d6SYuval Mintz return 0; 1226dacd88d6SYuval Mintz } 1227dacd88d6SYuval Mintz } 1228dacd88d6SYuval Mintz 1229dacd88d6SYuval Mintz static u16 qed_iov_prep_vp_update_resp_tlvs(struct qed_hwfn *p_hwfn, 1230dacd88d6SYuval Mintz struct qed_vf_info *p_vf, 1231dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, 1232dacd88d6SYuval Mintz u8 status, 1233dacd88d6SYuval Mintz u16 tlvs_mask, u16 tlvs_accepted) 1234dacd88d6SYuval Mintz { 1235dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 1236dacd88d6SYuval Mintz u16 size, total_len, i; 1237dacd88d6SYuval Mintz 1238dacd88d6SYuval Mintz memset(p_mbx->reply_virt, 0, sizeof(union pfvf_tlvs)); 1239dacd88d6SYuval Mintz p_mbx->offset = (u8 *)p_mbx->reply_virt; 1240dacd88d6SYuval Mintz size = sizeof(struct pfvf_def_resp_tlv); 1241dacd88d6SYuval Mintz total_len = size; 1242dacd88d6SYuval Mintz 1243dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_mbx->offset, CHANNEL_TLV_VPORT_UPDATE, size); 1244dacd88d6SYuval Mintz 1245dacd88d6SYuval Mintz /* Prepare response for all extended tlvs if they are found by PF */ 1246dacd88d6SYuval Mintz for (i = 0; i < QED_IOV_VP_UPDATE_MAX; i++) { 12471a635e48SYuval Mintz if (!(tlvs_mask & BIT(i))) 1248dacd88d6SYuval Mintz continue; 1249dacd88d6SYuval Mintz 1250dacd88d6SYuval Mintz resp = qed_add_tlv(p_hwfn, &p_mbx->offset, 1251dacd88d6SYuval Mintz qed_iov_vport_to_tlv(p_hwfn, i), size); 1252dacd88d6SYuval Mintz 12531a635e48SYuval Mintz if (tlvs_accepted & BIT(i)) 1254dacd88d6SYuval Mintz resp->hdr.status = status; 1255dacd88d6SYuval Mintz else 1256dacd88d6SYuval Mintz resp->hdr.status = PFVF_STATUS_NOT_SUPPORTED; 1257dacd88d6SYuval Mintz 1258dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, 1259dacd88d6SYuval Mintz QED_MSG_IOV, 1260dacd88d6SYuval Mintz "VF[%d] - vport_update response: TLV %d, status %02x\n", 1261dacd88d6SYuval Mintz p_vf->relative_vf_id, 1262dacd88d6SYuval Mintz qed_iov_vport_to_tlv(p_hwfn, i), resp->hdr.status); 1263dacd88d6SYuval Mintz 1264dacd88d6SYuval Mintz total_len += size; 1265dacd88d6SYuval Mintz } 1266dacd88d6SYuval Mintz 1267dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_mbx->offset, CHANNEL_TLV_LIST_END, 1268dacd88d6SYuval Mintz sizeof(struct channel_list_end_tlv)); 1269dacd88d6SYuval Mintz 1270dacd88d6SYuval Mintz return total_len; 1271dacd88d6SYuval Mintz } 1272dacd88d6SYuval Mintz 127337bff2b9SYuval Mintz static void qed_iov_prepare_resp(struct qed_hwfn *p_hwfn, 127437bff2b9SYuval Mintz struct qed_ptt *p_ptt, 127537bff2b9SYuval Mintz struct qed_vf_info *vf_info, 127637bff2b9SYuval Mintz u16 type, u16 length, u8 status) 127737bff2b9SYuval Mintz { 127837bff2b9SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf_info->vf_mbx; 127937bff2b9SYuval Mintz 128037bff2b9SYuval Mintz mbx->offset = (u8 *)mbx->reply_virt; 128137bff2b9SYuval Mintz 128237bff2b9SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, type, length); 128337bff2b9SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 128437bff2b9SYuval Mintz sizeof(struct channel_list_end_tlv)); 128537bff2b9SYuval Mintz 128637bff2b9SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, vf_info, length, status); 128737bff2b9SYuval Mintz } 128837bff2b9SYuval Mintz 1289ba56947aSBaoyou Xie static struct 1290ba56947aSBaoyou Xie qed_public_vf_info *qed_iov_get_public_vf_info(struct qed_hwfn *p_hwfn, 12910b55e27dSYuval Mintz u16 relative_vf_id, 12920b55e27dSYuval Mintz bool b_enabled_only) 12930b55e27dSYuval Mintz { 12940b55e27dSYuval Mintz struct qed_vf_info *vf = NULL; 12950b55e27dSYuval Mintz 12960b55e27dSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, relative_vf_id, b_enabled_only); 12970b55e27dSYuval Mintz if (!vf) 12980b55e27dSYuval Mintz return NULL; 12990b55e27dSYuval Mintz 13000b55e27dSYuval Mintz return &vf->p_vf_info; 13010b55e27dSYuval Mintz } 13020b55e27dSYuval Mintz 1303ba56947aSBaoyou Xie static void qed_iov_clean_vf(struct qed_hwfn *p_hwfn, u8 vfid) 13040b55e27dSYuval Mintz { 13050b55e27dSYuval Mintz struct qed_public_vf_info *vf_info; 13060b55e27dSYuval Mintz 13070b55e27dSYuval Mintz vf_info = qed_iov_get_public_vf_info(p_hwfn, vfid, false); 13080b55e27dSYuval Mintz 13090b55e27dSYuval Mintz if (!vf_info) 13100b55e27dSYuval Mintz return; 13110b55e27dSYuval Mintz 13120b55e27dSYuval Mintz /* Clear the VF mac */ 13130ee28e31SShyam Saini eth_zero_addr(vf_info->mac); 1314f990c82cSMintz, Yuval 1315f990c82cSMintz, Yuval vf_info->rx_accept_mode = 0; 1316f990c82cSMintz, Yuval vf_info->tx_accept_mode = 0; 13170b55e27dSYuval Mintz } 13180b55e27dSYuval Mintz 13190b55e27dSYuval Mintz static void qed_iov_vf_cleanup(struct qed_hwfn *p_hwfn, 13200b55e27dSYuval Mintz struct qed_vf_info *p_vf) 13210b55e27dSYuval Mintz { 13220b55e27dSYuval Mintz u32 i; 13230b55e27dSYuval Mintz 13240b55e27dSYuval Mintz p_vf->vf_bulletin = 0; 1325dacd88d6SYuval Mintz p_vf->vport_instance = 0; 132608feecd7SYuval Mintz p_vf->configured_features = 0; 13270b55e27dSYuval Mintz 13280b55e27dSYuval Mintz /* If VF previously requested less resources, go back to default */ 13290b55e27dSYuval Mintz p_vf->num_rxqs = p_vf->num_sbs; 13300b55e27dSYuval Mintz p_vf->num_txqs = p_vf->num_sbs; 13310b55e27dSYuval Mintz 1332dacd88d6SYuval Mintz p_vf->num_active_rxqs = 0; 1333dacd88d6SYuval Mintz 13343da7a37aSMintz, Yuval for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++) { 13353da7a37aSMintz, Yuval struct qed_vf_q_info *p_queue = &p_vf->vf_queues[i]; 13363da7a37aSMintz, Yuval 13373da7a37aSMintz, Yuval if (p_queue->p_rx_cid) { 13383da7a37aSMintz, Yuval qed_eth_queue_cid_release(p_hwfn, p_queue->p_rx_cid); 13393da7a37aSMintz, Yuval p_queue->p_rx_cid = NULL; 13403da7a37aSMintz, Yuval } 13413da7a37aSMintz, Yuval 13423da7a37aSMintz, Yuval if (p_queue->p_tx_cid) { 13433da7a37aSMintz, Yuval qed_eth_queue_cid_release(p_hwfn, p_queue->p_tx_cid); 13443da7a37aSMintz, Yuval p_queue->p_tx_cid = NULL; 13453da7a37aSMintz, Yuval } 13463da7a37aSMintz, Yuval } 13470b55e27dSYuval Mintz 134808feecd7SYuval Mintz memset(&p_vf->shadow_config, 0, sizeof(p_vf->shadow_config)); 13491fe614d1SYuval Mintz memset(&p_vf->acquire, 0, sizeof(p_vf->acquire)); 13500b55e27dSYuval Mintz qed_iov_clean_vf(p_hwfn, p_vf->relative_vf_id); 13510b55e27dSYuval Mintz } 13520b55e27dSYuval Mintz 13531cf2b1a9SYuval Mintz static u8 qed_iov_vf_mbx_acquire_resc(struct qed_hwfn *p_hwfn, 13541cf2b1a9SYuval Mintz struct qed_ptt *p_ptt, 13551cf2b1a9SYuval Mintz struct qed_vf_info *p_vf, 13561cf2b1a9SYuval Mintz struct vf_pf_resc_request *p_req, 13571cf2b1a9SYuval Mintz struct pf_vf_resc *p_resp) 13581cf2b1a9SYuval Mintz { 13591cf2b1a9SYuval Mintz int i; 13601cf2b1a9SYuval Mintz 13611cf2b1a9SYuval Mintz /* Queue related information */ 13621cf2b1a9SYuval Mintz p_resp->num_rxqs = p_vf->num_rxqs; 13631cf2b1a9SYuval Mintz p_resp->num_txqs = p_vf->num_txqs; 13641cf2b1a9SYuval Mintz p_resp->num_sbs = p_vf->num_sbs; 13651cf2b1a9SYuval Mintz 13661cf2b1a9SYuval Mintz for (i = 0; i < p_resp->num_sbs; i++) { 13671cf2b1a9SYuval Mintz p_resp->hw_sbs[i].hw_sb_id = p_vf->igu_sbs[i]; 13681cf2b1a9SYuval Mintz p_resp->hw_sbs[i].sb_qid = 0; 13691cf2b1a9SYuval Mintz } 13701cf2b1a9SYuval Mintz 13711cf2b1a9SYuval Mintz /* These fields are filled for backward compatibility. 13721cf2b1a9SYuval Mintz * Unused by modern vfs. 13731cf2b1a9SYuval Mintz */ 13741cf2b1a9SYuval Mintz for (i = 0; i < p_resp->num_rxqs; i++) { 13751cf2b1a9SYuval Mintz qed_fw_l2_queue(p_hwfn, p_vf->vf_queues[i].fw_rx_qid, 13761cf2b1a9SYuval Mintz (u16 *)&p_resp->hw_qid[i]); 13771cf2b1a9SYuval Mintz p_resp->cid[i] = p_vf->vf_queues[i].fw_cid; 13781cf2b1a9SYuval Mintz } 13791cf2b1a9SYuval Mintz 13801cf2b1a9SYuval Mintz /* Filter related information */ 13811cf2b1a9SYuval Mintz p_resp->num_mac_filters = min_t(u8, p_vf->num_mac_filters, 13821cf2b1a9SYuval Mintz p_req->num_mac_filters); 13831cf2b1a9SYuval Mintz p_resp->num_vlan_filters = min_t(u8, p_vf->num_vlan_filters, 13841cf2b1a9SYuval Mintz p_req->num_vlan_filters); 13851cf2b1a9SYuval Mintz 13861cf2b1a9SYuval Mintz /* This isn't really needed/enforced, but some legacy VFs might depend 13871cf2b1a9SYuval Mintz * on the correct filling of this field. 13881cf2b1a9SYuval Mintz */ 13891cf2b1a9SYuval Mintz p_resp->num_mc_filters = QED_MAX_MC_ADDRS; 13901cf2b1a9SYuval Mintz 13911cf2b1a9SYuval Mintz /* Validate sufficient resources for VF */ 13921cf2b1a9SYuval Mintz if (p_resp->num_rxqs < p_req->num_rxqs || 13931cf2b1a9SYuval Mintz p_resp->num_txqs < p_req->num_txqs || 13941cf2b1a9SYuval Mintz p_resp->num_sbs < p_req->num_sbs || 13951cf2b1a9SYuval Mintz p_resp->num_mac_filters < p_req->num_mac_filters || 13961cf2b1a9SYuval Mintz p_resp->num_vlan_filters < p_req->num_vlan_filters || 13971cf2b1a9SYuval Mintz p_resp->num_mc_filters < p_req->num_mc_filters) { 13981cf2b1a9SYuval Mintz DP_VERBOSE(p_hwfn, 13991cf2b1a9SYuval Mintz QED_MSG_IOV, 14001cf2b1a9SYuval Mintz "VF[%d] - Insufficient resources: rxq [%02x/%02x] txq [%02x/%02x] sbs [%02x/%02x] mac [%02x/%02x] vlan [%02x/%02x] mc [%02x/%02x]\n", 14011cf2b1a9SYuval Mintz p_vf->abs_vf_id, 14021cf2b1a9SYuval Mintz p_req->num_rxqs, 14031cf2b1a9SYuval Mintz p_resp->num_rxqs, 14041cf2b1a9SYuval Mintz p_req->num_rxqs, 14051cf2b1a9SYuval Mintz p_resp->num_txqs, 14061cf2b1a9SYuval Mintz p_req->num_sbs, 14071cf2b1a9SYuval Mintz p_resp->num_sbs, 14081cf2b1a9SYuval Mintz p_req->num_mac_filters, 14091cf2b1a9SYuval Mintz p_resp->num_mac_filters, 14101cf2b1a9SYuval Mintz p_req->num_vlan_filters, 14111cf2b1a9SYuval Mintz p_resp->num_vlan_filters, 14121cf2b1a9SYuval Mintz p_req->num_mc_filters, p_resp->num_mc_filters); 1413a044df83SYuval Mintz 1414a044df83SYuval Mintz /* Some legacy OSes are incapable of correctly handling this 1415a044df83SYuval Mintz * failure. 1416a044df83SYuval Mintz */ 1417a044df83SYuval Mintz if ((p_vf->acquire.vfdev_info.eth_fp_hsi_minor == 1418a044df83SYuval Mintz ETH_HSI_VER_NO_PKT_LEN_TUNN) && 1419a044df83SYuval Mintz (p_vf->acquire.vfdev_info.os_type == 1420a044df83SYuval Mintz VFPF_ACQUIRE_OS_WINDOWS)) 1421a044df83SYuval Mintz return PFVF_STATUS_SUCCESS; 1422a044df83SYuval Mintz 14231cf2b1a9SYuval Mintz return PFVF_STATUS_NO_RESOURCE; 14241cf2b1a9SYuval Mintz } 14251cf2b1a9SYuval Mintz 14261cf2b1a9SYuval Mintz return PFVF_STATUS_SUCCESS; 14271cf2b1a9SYuval Mintz } 14281cf2b1a9SYuval Mintz 14291cf2b1a9SYuval Mintz static void qed_iov_vf_mbx_acquire_stats(struct qed_hwfn *p_hwfn, 14301cf2b1a9SYuval Mintz struct pfvf_stats_info *p_stats) 14311cf2b1a9SYuval Mintz { 14321cf2b1a9SYuval Mintz p_stats->mstats.address = PXP_VF_BAR0_START_MSDM_ZONE_B + 14331cf2b1a9SYuval Mintz offsetof(struct mstorm_vf_zone, 14341cf2b1a9SYuval Mintz non_trigger.eth_queue_stat); 14351cf2b1a9SYuval Mintz p_stats->mstats.len = sizeof(struct eth_mstorm_per_queue_stat); 14361cf2b1a9SYuval Mintz p_stats->ustats.address = PXP_VF_BAR0_START_USDM_ZONE_B + 14371cf2b1a9SYuval Mintz offsetof(struct ustorm_vf_zone, 14381cf2b1a9SYuval Mintz non_trigger.eth_queue_stat); 14391cf2b1a9SYuval Mintz p_stats->ustats.len = sizeof(struct eth_ustorm_per_queue_stat); 14401cf2b1a9SYuval Mintz p_stats->pstats.address = PXP_VF_BAR0_START_PSDM_ZONE_B + 14411cf2b1a9SYuval Mintz offsetof(struct pstorm_vf_zone, 14421cf2b1a9SYuval Mintz non_trigger.eth_queue_stat); 14431cf2b1a9SYuval Mintz p_stats->pstats.len = sizeof(struct eth_pstorm_per_queue_stat); 14441cf2b1a9SYuval Mintz p_stats->tstats.address = 0; 14451cf2b1a9SYuval Mintz p_stats->tstats.len = 0; 14461cf2b1a9SYuval Mintz } 14471cf2b1a9SYuval Mintz 14481408cc1fSYuval Mintz static void qed_iov_vf_mbx_acquire(struct qed_hwfn *p_hwfn, 144937bff2b9SYuval Mintz struct qed_ptt *p_ptt, 14501408cc1fSYuval Mintz struct qed_vf_info *vf) 145137bff2b9SYuval Mintz { 14521408cc1fSYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 14531408cc1fSYuval Mintz struct pfvf_acquire_resp_tlv *resp = &mbx->reply_virt->acquire_resp; 14541408cc1fSYuval Mintz struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info; 14551408cc1fSYuval Mintz struct vfpf_acquire_tlv *req = &mbx->req_virt->acquire; 14561cf2b1a9SYuval Mintz u8 vfpf_status = PFVF_STATUS_NOT_SUPPORTED; 14571408cc1fSYuval Mintz struct pf_vf_resc *resc = &resp->resc; 14581fe614d1SYuval Mintz int rc; 14591fe614d1SYuval Mintz 14601fe614d1SYuval Mintz memset(resp, 0, sizeof(*resp)); 14611408cc1fSYuval Mintz 146205fafbfbSYuval Mintz /* Write the PF version so that VF would know which version 146305fafbfbSYuval Mintz * is supported - might be later overriden. This guarantees that 146405fafbfbSYuval Mintz * VF could recognize legacy PF based on lack of versions in reply. 146505fafbfbSYuval Mintz */ 146605fafbfbSYuval Mintz pfdev_info->major_fp_hsi = ETH_HSI_VER_MAJOR; 146705fafbfbSYuval Mintz pfdev_info->minor_fp_hsi = ETH_HSI_VER_MINOR; 146805fafbfbSYuval Mintz 1469a044df83SYuval Mintz if (vf->state != VF_FREE && vf->state != VF_STOPPED) { 1470a044df83SYuval Mintz DP_VERBOSE(p_hwfn, 1471a044df83SYuval Mintz QED_MSG_IOV, 1472a044df83SYuval Mintz "VF[%d] sent ACQUIRE but is already in state %d - fail request\n", 1473a044df83SYuval Mintz vf->abs_vf_id, vf->state); 1474a044df83SYuval Mintz goto out; 1475a044df83SYuval Mintz } 1476a044df83SYuval Mintz 14771408cc1fSYuval Mintz /* Validate FW compatibility */ 14781fe614d1SYuval Mintz if (req->vfdev_info.eth_fp_hsi_major != ETH_HSI_VER_MAJOR) { 1479a044df83SYuval Mintz if (req->vfdev_info.capabilities & 1480a044df83SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI) { 1481a044df83SYuval Mintz struct vf_pf_vfdev_info *p_vfdev = &req->vfdev_info; 1482a044df83SYuval Mintz 1483a044df83SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1484a044df83SYuval Mintz "VF[%d] is pre-fastpath HSI\n", 1485a044df83SYuval Mintz vf->abs_vf_id); 1486a044df83SYuval Mintz p_vfdev->eth_fp_hsi_major = ETH_HSI_VER_MAJOR; 1487a044df83SYuval Mintz p_vfdev->eth_fp_hsi_minor = ETH_HSI_VER_NO_PKT_LEN_TUNN; 1488a044df83SYuval Mintz } else { 14891408cc1fSYuval Mintz DP_INFO(p_hwfn, 14901fe614d1SYuval Mintz "VF[%d] needs fastpath HSI %02x.%02x, which is incompatible with loaded FW's faspath HSI %02x.%02x\n", 14911408cc1fSYuval Mintz vf->abs_vf_id, 14921fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_major, 14931fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_minor, 14941fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR); 14951fe614d1SYuval Mintz 14961408cc1fSYuval Mintz goto out; 14971408cc1fSYuval Mintz } 1498a044df83SYuval Mintz } 14991408cc1fSYuval Mintz 15001408cc1fSYuval Mintz /* On 100g PFs, prevent old VFs from loading */ 15011408cc1fSYuval Mintz if ((p_hwfn->cdev->num_hwfns > 1) && 15021408cc1fSYuval Mintz !(req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_100G)) { 15031408cc1fSYuval Mintz DP_INFO(p_hwfn, 15041408cc1fSYuval Mintz "VF[%d] is running an old driver that doesn't support 100g\n", 15051408cc1fSYuval Mintz vf->abs_vf_id); 15061408cc1fSYuval Mintz goto out; 15071408cc1fSYuval Mintz } 15081408cc1fSYuval Mintz 15091fe614d1SYuval Mintz /* Store the acquire message */ 15101fe614d1SYuval Mintz memcpy(&vf->acquire, req, sizeof(vf->acquire)); 15111408cc1fSYuval Mintz 15121408cc1fSYuval Mintz vf->opaque_fid = req->vfdev_info.opaque_fid; 15131408cc1fSYuval Mintz 15141408cc1fSYuval Mintz vf->vf_bulletin = req->bulletin_addr; 15151408cc1fSYuval Mintz vf->bulletin.size = (vf->bulletin.size < req->bulletin_size) ? 15161408cc1fSYuval Mintz vf->bulletin.size : req->bulletin_size; 15171408cc1fSYuval Mintz 15181408cc1fSYuval Mintz /* fill in pfdev info */ 15191408cc1fSYuval Mintz pfdev_info->chip_num = p_hwfn->cdev->chip_num; 15201408cc1fSYuval Mintz pfdev_info->db_size = 0; 15211408cc1fSYuval Mintz pfdev_info->indices_per_sb = PIS_PER_SB; 15221408cc1fSYuval Mintz 15231408cc1fSYuval Mintz pfdev_info->capabilities = PFVF_ACQUIRE_CAP_DEFAULT_UNTAGGED | 15241408cc1fSYuval Mintz PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE; 15251408cc1fSYuval Mintz if (p_hwfn->cdev->num_hwfns > 1) 15261408cc1fSYuval Mintz pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_100G; 15271408cc1fSYuval Mintz 15281cf2b1a9SYuval Mintz qed_iov_vf_mbx_acquire_stats(p_hwfn, &pfdev_info->stats_info); 15291408cc1fSYuval Mintz 15301408cc1fSYuval Mintz memcpy(pfdev_info->port_mac, p_hwfn->hw_info.hw_mac_addr, ETH_ALEN); 15311408cc1fSYuval Mintz 15321408cc1fSYuval Mintz pfdev_info->fw_major = FW_MAJOR_VERSION; 15331408cc1fSYuval Mintz pfdev_info->fw_minor = FW_MINOR_VERSION; 15341408cc1fSYuval Mintz pfdev_info->fw_rev = FW_REVISION_VERSION; 15351408cc1fSYuval Mintz pfdev_info->fw_eng = FW_ENGINEERING_VERSION; 1536a044df83SYuval Mintz 1537a044df83SYuval Mintz /* Incorrect when legacy, but doesn't matter as legacy isn't reading 1538a044df83SYuval Mintz * this field. 1539a044df83SYuval Mintz */ 15401a635e48SYuval Mintz pfdev_info->minor_fp_hsi = min_t(u8, ETH_HSI_VER_MINOR, 15411fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_minor); 15421408cc1fSYuval Mintz pfdev_info->os_type = VFPF_ACQUIRE_OS_LINUX; 15431408cc1fSYuval Mintz qed_mcp_get_mfw_ver(p_hwfn, p_ptt, &pfdev_info->mfw_ver, NULL); 15441408cc1fSYuval Mintz 15451408cc1fSYuval Mintz pfdev_info->dev_type = p_hwfn->cdev->type; 15461408cc1fSYuval Mintz pfdev_info->chip_rev = p_hwfn->cdev->chip_rev; 15471408cc1fSYuval Mintz 15481cf2b1a9SYuval Mintz /* Fill resources available to VF; Make sure there are enough to 15491cf2b1a9SYuval Mintz * satisfy the VF's request. 15501408cc1fSYuval Mintz */ 15511cf2b1a9SYuval Mintz vfpf_status = qed_iov_vf_mbx_acquire_resc(p_hwfn, p_ptt, vf, 15521cf2b1a9SYuval Mintz &req->resc_request, resc); 15531cf2b1a9SYuval Mintz if (vfpf_status != PFVF_STATUS_SUCCESS) 15541cf2b1a9SYuval Mintz goto out; 15551408cc1fSYuval Mintz 15561fe614d1SYuval Mintz /* Start the VF in FW */ 15571fe614d1SYuval Mintz rc = qed_sp_vf_start(p_hwfn, vf); 15581fe614d1SYuval Mintz if (rc) { 15591fe614d1SYuval Mintz DP_NOTICE(p_hwfn, "Failed to start VF[%02x]\n", vf->abs_vf_id); 15601fe614d1SYuval Mintz vfpf_status = PFVF_STATUS_FAILURE; 15611fe614d1SYuval Mintz goto out; 15621fe614d1SYuval Mintz } 15631fe614d1SYuval Mintz 15641408cc1fSYuval Mintz /* Fill agreed size of bulletin board in response */ 15651408cc1fSYuval Mintz resp->bulletin_size = vf->bulletin.size; 156636558c3dSYuval Mintz qed_iov_post_vf_bulletin(p_hwfn, vf->relative_vf_id, p_ptt); 15671408cc1fSYuval Mintz 15681408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 15691408cc1fSYuval Mintz QED_MSG_IOV, 15701408cc1fSYuval Mintz "VF[%d] ACQUIRE_RESPONSE: pfdev_info- chip_num=0x%x, db_size=%d, idx_per_sb=%d, pf_cap=0x%llx\n" 15711408cc1fSYuval Mintz "resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d\n", 15721408cc1fSYuval Mintz vf->abs_vf_id, 15731408cc1fSYuval Mintz resp->pfdev_info.chip_num, 15741408cc1fSYuval Mintz resp->pfdev_info.db_size, 15751408cc1fSYuval Mintz resp->pfdev_info.indices_per_sb, 15761408cc1fSYuval Mintz resp->pfdev_info.capabilities, 15771408cc1fSYuval Mintz resc->num_rxqs, 15781408cc1fSYuval Mintz resc->num_txqs, 15791408cc1fSYuval Mintz resc->num_sbs, 15801408cc1fSYuval Mintz resc->num_mac_filters, 15811408cc1fSYuval Mintz resc->num_vlan_filters); 15821408cc1fSYuval Mintz vf->state = VF_ACQUIRED; 15831408cc1fSYuval Mintz 15841408cc1fSYuval Mintz /* Prepare Response */ 15851408cc1fSYuval Mintz out: 15861408cc1fSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_ACQUIRE, 15871408cc1fSYuval Mintz sizeof(struct pfvf_acquire_resp_tlv), vfpf_status); 158837bff2b9SYuval Mintz } 158937bff2b9SYuval Mintz 15906ddc7608SYuval Mintz static int __qed_iov_spoofchk_set(struct qed_hwfn *p_hwfn, 15916ddc7608SYuval Mintz struct qed_vf_info *p_vf, bool val) 15926ddc7608SYuval Mintz { 15936ddc7608SYuval Mintz struct qed_sp_vport_update_params params; 15946ddc7608SYuval Mintz int rc; 15956ddc7608SYuval Mintz 15966ddc7608SYuval Mintz if (val == p_vf->spoof_chk) { 15976ddc7608SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 15986ddc7608SYuval Mintz "Spoofchk value[%d] is already configured\n", val); 15996ddc7608SYuval Mintz return 0; 16006ddc7608SYuval Mintz } 16016ddc7608SYuval Mintz 16026ddc7608SYuval Mintz memset(¶ms, 0, sizeof(struct qed_sp_vport_update_params)); 16036ddc7608SYuval Mintz params.opaque_fid = p_vf->opaque_fid; 16046ddc7608SYuval Mintz params.vport_id = p_vf->vport_id; 16056ddc7608SYuval Mintz params.update_anti_spoofing_en_flg = 1; 16066ddc7608SYuval Mintz params.anti_spoofing_en = val; 16076ddc7608SYuval Mintz 16086ddc7608SYuval Mintz rc = qed_sp_vport_update(p_hwfn, ¶ms, QED_SPQ_MODE_EBLOCK, NULL); 1609cb1fa088SYuval Mintz if (!rc) { 16106ddc7608SYuval Mintz p_vf->spoof_chk = val; 16116ddc7608SYuval Mintz p_vf->req_spoofchk_val = p_vf->spoof_chk; 16126ddc7608SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 16136ddc7608SYuval Mintz "Spoofchk val[%d] configured\n", val); 16146ddc7608SYuval Mintz } else { 16156ddc7608SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 16166ddc7608SYuval Mintz "Spoofchk configuration[val:%d] failed for VF[%d]\n", 16176ddc7608SYuval Mintz val, p_vf->relative_vf_id); 16186ddc7608SYuval Mintz } 16196ddc7608SYuval Mintz 16206ddc7608SYuval Mintz return rc; 16216ddc7608SYuval Mintz } 16226ddc7608SYuval Mintz 162308feecd7SYuval Mintz static int qed_iov_reconfigure_unicast_vlan(struct qed_hwfn *p_hwfn, 162408feecd7SYuval Mintz struct qed_vf_info *p_vf) 162508feecd7SYuval Mintz { 162608feecd7SYuval Mintz struct qed_filter_ucast filter; 162708feecd7SYuval Mintz int rc = 0; 162808feecd7SYuval Mintz int i; 162908feecd7SYuval Mintz 163008feecd7SYuval Mintz memset(&filter, 0, sizeof(filter)); 163108feecd7SYuval Mintz filter.is_rx_filter = 1; 163208feecd7SYuval Mintz filter.is_tx_filter = 1; 163308feecd7SYuval Mintz filter.vport_to_add_to = p_vf->vport_id; 163408feecd7SYuval Mintz filter.opcode = QED_FILTER_ADD; 163508feecd7SYuval Mintz 163608feecd7SYuval Mintz /* Reconfigure vlans */ 163708feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) { 163808feecd7SYuval Mintz if (!p_vf->shadow_config.vlans[i].used) 163908feecd7SYuval Mintz continue; 164008feecd7SYuval Mintz 164108feecd7SYuval Mintz filter.type = QED_FILTER_VLAN; 164208feecd7SYuval Mintz filter.vlan = p_vf->shadow_config.vlans[i].vid; 16431a635e48SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 164408feecd7SYuval Mintz "Reconfiguring VLAN [0x%04x] for VF [%04x]\n", 164508feecd7SYuval Mintz filter.vlan, p_vf->relative_vf_id); 16461a635e48SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid, 16471a635e48SYuval Mintz &filter, QED_SPQ_MODE_CB, NULL); 164808feecd7SYuval Mintz if (rc) { 164908feecd7SYuval Mintz DP_NOTICE(p_hwfn, 165008feecd7SYuval Mintz "Failed to configure VLAN [%04x] to VF [%04x]\n", 165108feecd7SYuval Mintz filter.vlan, p_vf->relative_vf_id); 165208feecd7SYuval Mintz break; 165308feecd7SYuval Mintz } 165408feecd7SYuval Mintz } 165508feecd7SYuval Mintz 165608feecd7SYuval Mintz return rc; 165708feecd7SYuval Mintz } 165808feecd7SYuval Mintz 165908feecd7SYuval Mintz static int 166008feecd7SYuval Mintz qed_iov_reconfigure_unicast_shadow(struct qed_hwfn *p_hwfn, 166108feecd7SYuval Mintz struct qed_vf_info *p_vf, u64 events) 166208feecd7SYuval Mintz { 166308feecd7SYuval Mintz int rc = 0; 166408feecd7SYuval Mintz 16651a635e48SYuval Mintz if ((events & BIT(VLAN_ADDR_FORCED)) && 166608feecd7SYuval Mintz !(p_vf->configured_features & (1 << VLAN_ADDR_FORCED))) 166708feecd7SYuval Mintz rc = qed_iov_reconfigure_unicast_vlan(p_hwfn, p_vf); 166808feecd7SYuval Mintz 166908feecd7SYuval Mintz return rc; 167008feecd7SYuval Mintz } 167108feecd7SYuval Mintz 167208feecd7SYuval Mintz static int qed_iov_configure_vport_forced(struct qed_hwfn *p_hwfn, 167308feecd7SYuval Mintz struct qed_vf_info *p_vf, u64 events) 167408feecd7SYuval Mintz { 167508feecd7SYuval Mintz int rc = 0; 167608feecd7SYuval Mintz struct qed_filter_ucast filter; 167708feecd7SYuval Mintz 167808feecd7SYuval Mintz if (!p_vf->vport_instance) 167908feecd7SYuval Mintz return -EINVAL; 168008feecd7SYuval Mintz 16811a635e48SYuval Mintz if (events & BIT(MAC_ADDR_FORCED)) { 1682eff16960SYuval Mintz /* Since there's no way [currently] of removing the MAC, 1683eff16960SYuval Mintz * we can always assume this means we need to force it. 1684eff16960SYuval Mintz */ 1685eff16960SYuval Mintz memset(&filter, 0, sizeof(filter)); 1686eff16960SYuval Mintz filter.type = QED_FILTER_MAC; 1687eff16960SYuval Mintz filter.opcode = QED_FILTER_REPLACE; 1688eff16960SYuval Mintz filter.is_rx_filter = 1; 1689eff16960SYuval Mintz filter.is_tx_filter = 1; 1690eff16960SYuval Mintz filter.vport_to_add_to = p_vf->vport_id; 1691eff16960SYuval Mintz ether_addr_copy(filter.mac, p_vf->bulletin.p_virt->mac); 1692eff16960SYuval Mintz 1693eff16960SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid, 1694eff16960SYuval Mintz &filter, QED_SPQ_MODE_CB, NULL); 1695eff16960SYuval Mintz if (rc) { 1696eff16960SYuval Mintz DP_NOTICE(p_hwfn, 1697eff16960SYuval Mintz "PF failed to configure MAC for VF\n"); 1698eff16960SYuval Mintz return rc; 1699eff16960SYuval Mintz } 1700eff16960SYuval Mintz 1701eff16960SYuval Mintz p_vf->configured_features |= 1 << MAC_ADDR_FORCED; 1702eff16960SYuval Mintz } 1703eff16960SYuval Mintz 17041a635e48SYuval Mintz if (events & BIT(VLAN_ADDR_FORCED)) { 170508feecd7SYuval Mintz struct qed_sp_vport_update_params vport_update; 170608feecd7SYuval Mintz u8 removal; 170708feecd7SYuval Mintz int i; 170808feecd7SYuval Mintz 170908feecd7SYuval Mintz memset(&filter, 0, sizeof(filter)); 171008feecd7SYuval Mintz filter.type = QED_FILTER_VLAN; 171108feecd7SYuval Mintz filter.is_rx_filter = 1; 171208feecd7SYuval Mintz filter.is_tx_filter = 1; 171308feecd7SYuval Mintz filter.vport_to_add_to = p_vf->vport_id; 171408feecd7SYuval Mintz filter.vlan = p_vf->bulletin.p_virt->pvid; 171508feecd7SYuval Mintz filter.opcode = filter.vlan ? QED_FILTER_REPLACE : 171608feecd7SYuval Mintz QED_FILTER_FLUSH; 171708feecd7SYuval Mintz 171808feecd7SYuval Mintz /* Send the ramrod */ 171908feecd7SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid, 172008feecd7SYuval Mintz &filter, QED_SPQ_MODE_CB, NULL); 172108feecd7SYuval Mintz if (rc) { 172208feecd7SYuval Mintz DP_NOTICE(p_hwfn, 172308feecd7SYuval Mintz "PF failed to configure VLAN for VF\n"); 172408feecd7SYuval Mintz return rc; 172508feecd7SYuval Mintz } 172608feecd7SYuval Mintz 172708feecd7SYuval Mintz /* Update the default-vlan & silent vlan stripping */ 172808feecd7SYuval Mintz memset(&vport_update, 0, sizeof(vport_update)); 172908feecd7SYuval Mintz vport_update.opaque_fid = p_vf->opaque_fid; 173008feecd7SYuval Mintz vport_update.vport_id = p_vf->vport_id; 173108feecd7SYuval Mintz vport_update.update_default_vlan_enable_flg = 1; 173208feecd7SYuval Mintz vport_update.default_vlan_enable_flg = filter.vlan ? 1 : 0; 173308feecd7SYuval Mintz vport_update.update_default_vlan_flg = 1; 173408feecd7SYuval Mintz vport_update.default_vlan = filter.vlan; 173508feecd7SYuval Mintz 173608feecd7SYuval Mintz vport_update.update_inner_vlan_removal_flg = 1; 173708feecd7SYuval Mintz removal = filter.vlan ? 1 173808feecd7SYuval Mintz : p_vf->shadow_config.inner_vlan_removal; 173908feecd7SYuval Mintz vport_update.inner_vlan_removal_flg = removal; 174008feecd7SYuval Mintz vport_update.silent_vlan_removal_flg = filter.vlan ? 1 : 0; 174108feecd7SYuval Mintz rc = qed_sp_vport_update(p_hwfn, 174208feecd7SYuval Mintz &vport_update, 174308feecd7SYuval Mintz QED_SPQ_MODE_EBLOCK, NULL); 174408feecd7SYuval Mintz if (rc) { 174508feecd7SYuval Mintz DP_NOTICE(p_hwfn, 174608feecd7SYuval Mintz "PF failed to configure VF vport for vlan\n"); 174708feecd7SYuval Mintz return rc; 174808feecd7SYuval Mintz } 174908feecd7SYuval Mintz 175008feecd7SYuval Mintz /* Update all the Rx queues */ 175108feecd7SYuval Mintz for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++) { 17523da7a37aSMintz, Yuval struct qed_queue_cid *p_cid; 175308feecd7SYuval Mintz 17543da7a37aSMintz, Yuval p_cid = p_vf->vf_queues[i].p_rx_cid; 17553da7a37aSMintz, Yuval if (!p_cid) 175608feecd7SYuval Mintz continue; 175708feecd7SYuval Mintz 17583da7a37aSMintz, Yuval rc = qed_sp_eth_rx_queues_update(p_hwfn, 17593da7a37aSMintz, Yuval (void **)&p_cid, 176008feecd7SYuval Mintz 1, 0, 1, 176108feecd7SYuval Mintz QED_SPQ_MODE_EBLOCK, 176208feecd7SYuval Mintz NULL); 176308feecd7SYuval Mintz if (rc) { 176408feecd7SYuval Mintz DP_NOTICE(p_hwfn, 176508feecd7SYuval Mintz "Failed to send Rx update fo queue[0x%04x]\n", 17663da7a37aSMintz, Yuval p_cid->rel.queue_id); 176708feecd7SYuval Mintz return rc; 176808feecd7SYuval Mintz } 176908feecd7SYuval Mintz } 177008feecd7SYuval Mintz 177108feecd7SYuval Mintz if (filter.vlan) 177208feecd7SYuval Mintz p_vf->configured_features |= 1 << VLAN_ADDR_FORCED; 177308feecd7SYuval Mintz else 17741a635e48SYuval Mintz p_vf->configured_features &= ~BIT(VLAN_ADDR_FORCED); 177508feecd7SYuval Mintz } 177608feecd7SYuval Mintz 177708feecd7SYuval Mintz /* If forced features are terminated, we need to configure the shadow 177808feecd7SYuval Mintz * configuration back again. 177908feecd7SYuval Mintz */ 178008feecd7SYuval Mintz if (events) 178108feecd7SYuval Mintz qed_iov_reconfigure_unicast_shadow(p_hwfn, p_vf, events); 178208feecd7SYuval Mintz 178308feecd7SYuval Mintz return rc; 178408feecd7SYuval Mintz } 178508feecd7SYuval Mintz 1786dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn, 1787dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1788dacd88d6SYuval Mintz struct qed_vf_info *vf) 1789dacd88d6SYuval Mintz { 1790dacd88d6SYuval Mintz struct qed_sp_vport_start_params params = { 0 }; 1791dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 1792dacd88d6SYuval Mintz struct vfpf_vport_start_tlv *start; 1793dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 1794dacd88d6SYuval Mintz struct qed_vf_info *vf_info; 179508feecd7SYuval Mintz u64 *p_bitmap; 1796dacd88d6SYuval Mintz int sb_id; 1797dacd88d6SYuval Mintz int rc; 1798dacd88d6SYuval Mintz 1799dacd88d6SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vf->relative_vf_id, true); 1800dacd88d6SYuval Mintz if (!vf_info) { 1801dacd88d6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 1802dacd88d6SYuval Mintz "Failed to get VF info, invalid vfid [%d]\n", 1803dacd88d6SYuval Mintz vf->relative_vf_id); 1804dacd88d6SYuval Mintz return; 1805dacd88d6SYuval Mintz } 1806dacd88d6SYuval Mintz 1807dacd88d6SYuval Mintz vf->state = VF_ENABLED; 1808dacd88d6SYuval Mintz start = &mbx->req_virt->start_vport; 1809dacd88d6SYuval Mintz 1810b801b159SMintz, Yuval qed_iov_enable_vf_traffic(p_hwfn, p_ptt, vf); 1811b801b159SMintz, Yuval 1812dacd88d6SYuval Mintz /* Initialize Status block in CAU */ 1813dacd88d6SYuval Mintz for (sb_id = 0; sb_id < vf->num_sbs; sb_id++) { 1814dacd88d6SYuval Mintz if (!start->sb_addr[sb_id]) { 1815dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1816dacd88d6SYuval Mintz "VF[%d] did not fill the address of SB %d\n", 1817dacd88d6SYuval Mintz vf->relative_vf_id, sb_id); 1818dacd88d6SYuval Mintz break; 1819dacd88d6SYuval Mintz } 1820dacd88d6SYuval Mintz 1821dacd88d6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, 1822dacd88d6SYuval Mintz start->sb_addr[sb_id], 18231a635e48SYuval Mintz vf->igu_sbs[sb_id], vf->abs_vf_id, 1); 1824dacd88d6SYuval Mintz } 1825dacd88d6SYuval Mintz 1826dacd88d6SYuval Mintz vf->mtu = start->mtu; 182708feecd7SYuval Mintz vf->shadow_config.inner_vlan_removal = start->inner_vlan_removal; 182808feecd7SYuval Mintz 182908feecd7SYuval Mintz /* Take into consideration configuration forced by hypervisor; 183008feecd7SYuval Mintz * If none is configured, use the supplied VF values [for old 183108feecd7SYuval Mintz * vfs that would still be fine, since they passed '0' as padding]. 183208feecd7SYuval Mintz */ 183308feecd7SYuval Mintz p_bitmap = &vf_info->bulletin.p_virt->valid_bitmap; 18341a635e48SYuval Mintz if (!(*p_bitmap & BIT(VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED))) { 183508feecd7SYuval Mintz u8 vf_req = start->only_untagged; 183608feecd7SYuval Mintz 183708feecd7SYuval Mintz vf_info->bulletin.p_virt->default_only_untagged = vf_req; 183808feecd7SYuval Mintz *p_bitmap |= 1 << VFPF_BULLETIN_UNTAGGED_DEFAULT; 183908feecd7SYuval Mintz } 1840dacd88d6SYuval Mintz 1841dacd88d6SYuval Mintz params.tpa_mode = start->tpa_mode; 1842dacd88d6SYuval Mintz params.remove_inner_vlan = start->inner_vlan_removal; 1843831bfb0eSYuval Mintz params.tx_switching = true; 1844dacd88d6SYuval Mintz 184508feecd7SYuval Mintz params.only_untagged = vf_info->bulletin.p_virt->default_only_untagged; 1846dacd88d6SYuval Mintz params.drop_ttl0 = false; 1847dacd88d6SYuval Mintz params.concrete_fid = vf->concrete_fid; 1848dacd88d6SYuval Mintz params.opaque_fid = vf->opaque_fid; 1849dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 1850dacd88d6SYuval Mintz params.max_buffers_per_cqe = start->max_buffers_per_cqe; 1851dacd88d6SYuval Mintz params.mtu = vf->mtu; 185211a85d75SYuval Mintz params.check_mac = true; 1853dacd88d6SYuval Mintz 1854dacd88d6SYuval Mintz rc = qed_sp_eth_vport_start(p_hwfn, ¶ms); 18551a635e48SYuval Mintz if (rc) { 1856dacd88d6SYuval Mintz DP_ERR(p_hwfn, 1857dacd88d6SYuval Mintz "qed_iov_vf_mbx_start_vport returned error %d\n", rc); 1858dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1859dacd88d6SYuval Mintz } else { 1860dacd88d6SYuval Mintz vf->vport_instance++; 186108feecd7SYuval Mintz 186208feecd7SYuval Mintz /* Force configuration if needed on the newly opened vport */ 186308feecd7SYuval Mintz qed_iov_configure_vport_forced(p_hwfn, vf, *p_bitmap); 18646ddc7608SYuval Mintz 18656ddc7608SYuval Mintz __qed_iov_spoofchk_set(p_hwfn, vf, vf->req_spoofchk_val); 1866dacd88d6SYuval Mintz } 1867dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_START, 1868dacd88d6SYuval Mintz sizeof(struct pfvf_def_resp_tlv), status); 1869dacd88d6SYuval Mintz } 1870dacd88d6SYuval Mintz 1871dacd88d6SYuval Mintz static void qed_iov_vf_mbx_stop_vport(struct qed_hwfn *p_hwfn, 1872dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1873dacd88d6SYuval Mintz struct qed_vf_info *vf) 1874dacd88d6SYuval Mintz { 1875dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 1876dacd88d6SYuval Mintz int rc; 1877dacd88d6SYuval Mintz 1878dacd88d6SYuval Mintz vf->vport_instance--; 18796ddc7608SYuval Mintz vf->spoof_chk = false; 1880dacd88d6SYuval Mintz 1881f109c240SMintz, Yuval if ((qed_iov_validate_active_rxq(p_hwfn, vf)) || 1882f109c240SMintz, Yuval (qed_iov_validate_active_txq(p_hwfn, vf))) { 1883f109c240SMintz, Yuval vf->b_malicious = true; 1884f109c240SMintz, Yuval DP_NOTICE(p_hwfn, 1885f109c240SMintz, Yuval "VF [%02x] - considered malicious; Unable to stop RX/TX queuess\n", 1886f109c240SMintz, Yuval vf->abs_vf_id); 1887f109c240SMintz, Yuval status = PFVF_STATUS_MALICIOUS; 1888f109c240SMintz, Yuval goto out; 1889f109c240SMintz, Yuval } 1890f109c240SMintz, Yuval 1891dacd88d6SYuval Mintz rc = qed_sp_vport_stop(p_hwfn, vf->opaque_fid, vf->vport_id); 18921a635e48SYuval Mintz if (rc) { 1893dacd88d6SYuval Mintz DP_ERR(p_hwfn, "qed_iov_vf_mbx_stop_vport returned error %d\n", 1894dacd88d6SYuval Mintz rc); 1895dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1896dacd88d6SYuval Mintz } 1897dacd88d6SYuval Mintz 189808feecd7SYuval Mintz /* Forget the configuration on the vport */ 189908feecd7SYuval Mintz vf->configured_features = 0; 190008feecd7SYuval Mintz memset(&vf->shadow_config, 0, sizeof(vf->shadow_config)); 190108feecd7SYuval Mintz 1902f109c240SMintz, Yuval out: 1903dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_TEARDOWN, 1904dacd88d6SYuval Mintz sizeof(struct pfvf_def_resp_tlv), status); 1905dacd88d6SYuval Mintz } 1906dacd88d6SYuval Mintz 1907dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_rxq_resp(struct qed_hwfn *p_hwfn, 1908dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1909a044df83SYuval Mintz struct qed_vf_info *vf, 1910a044df83SYuval Mintz u8 status, bool b_legacy) 1911dacd88d6SYuval Mintz { 1912dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 1913dacd88d6SYuval Mintz struct pfvf_start_queue_resp_tlv *p_tlv; 1914dacd88d6SYuval Mintz struct vfpf_start_rxq_tlv *req; 1915a044df83SYuval Mintz u16 length; 1916dacd88d6SYuval Mintz 1917dacd88d6SYuval Mintz mbx->offset = (u8 *)mbx->reply_virt; 1918dacd88d6SYuval Mintz 1919a044df83SYuval Mintz /* Taking a bigger struct instead of adding a TLV to list was a 1920a044df83SYuval Mintz * mistake, but one which we're now stuck with, as some older 1921a044df83SYuval Mintz * clients assume the size of the previous response. 1922a044df83SYuval Mintz */ 1923a044df83SYuval Mintz if (!b_legacy) 1924a044df83SYuval Mintz length = sizeof(*p_tlv); 1925a044df83SYuval Mintz else 1926a044df83SYuval Mintz length = sizeof(struct pfvf_def_resp_tlv); 1927a044df83SYuval Mintz 1928dacd88d6SYuval Mintz p_tlv = qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_START_RXQ, 1929a044df83SYuval Mintz length); 1930dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 1931dacd88d6SYuval Mintz sizeof(struct channel_list_end_tlv)); 1932dacd88d6SYuval Mintz 1933dacd88d6SYuval Mintz /* Update the TLV with the response */ 1934a044df83SYuval Mintz if ((status == PFVF_STATUS_SUCCESS) && !b_legacy) { 1935dacd88d6SYuval Mintz req = &mbx->req_virt->start_rxq; 1936351a4dedSYuval Mintz p_tlv->offset = PXP_VF_BAR0_START_MSDM_ZONE_B + 1937351a4dedSYuval Mintz offsetof(struct mstorm_vf_zone, 1938351a4dedSYuval Mintz non_trigger.eth_rx_queue_producers) + 1939351a4dedSYuval Mintz sizeof(struct eth_rx_prod_data) * req->rx_qid; 1940dacd88d6SYuval Mintz } 1941dacd88d6SYuval Mintz 1942a044df83SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, vf, length, status); 1943dacd88d6SYuval Mintz } 1944dacd88d6SYuval Mintz 1945dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn, 1946dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1947dacd88d6SYuval Mintz struct qed_vf_info *vf) 1948dacd88d6SYuval Mintz { 1949dacd88d6SYuval Mintz struct qed_queue_start_common_params params; 1950dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 195141086467SYuval Mintz u8 status = PFVF_STATUS_NO_RESOURCE; 19523da7a37aSMintz, Yuval struct qed_vf_q_info *p_queue; 1953dacd88d6SYuval Mintz struct vfpf_start_rxq_tlv *req; 1954a044df83SYuval Mintz bool b_legacy_vf = false; 1955dacd88d6SYuval Mintz int rc; 1956dacd88d6SYuval Mintz 1957dacd88d6SYuval Mintz req = &mbx->req_virt->start_rxq; 195841086467SYuval Mintz 1959f109c240SMintz, Yuval if (!qed_iov_validate_rxq(p_hwfn, vf, req->rx_qid, 1960f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_DISABLE) || 196141086467SYuval Mintz !qed_iov_validate_sb(p_hwfn, vf, req->hw_sb)) 196241086467SYuval Mintz goto out; 196341086467SYuval Mintz 19643da7a37aSMintz, Yuval /* Acquire a new queue-cid */ 19653da7a37aSMintz, Yuval p_queue = &vf->vf_queues[req->rx_qid]; 19663da7a37aSMintz, Yuval 19673da7a37aSMintz, Yuval memset(¶ms, 0, sizeof(params)); 19683da7a37aSMintz, Yuval params.queue_id = p_queue->fw_rx_qid; 1969dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 19703da7a37aSMintz, Yuval params.stats_id = vf->abs_vf_id + 0x10; 1971dacd88d6SYuval Mintz params.sb = req->hw_sb; 1972dacd88d6SYuval Mintz params.sb_idx = req->sb_index; 1973dacd88d6SYuval Mintz 19743da7a37aSMintz, Yuval p_queue->p_rx_cid = _qed_eth_queue_to_cid(p_hwfn, 19753da7a37aSMintz, Yuval vf->opaque_fid, 19763da7a37aSMintz, Yuval p_queue->fw_cid, 19773da7a37aSMintz, Yuval req->rx_qid, ¶ms); 19783da7a37aSMintz, Yuval if (!p_queue->p_rx_cid) 19793da7a37aSMintz, Yuval goto out; 19803da7a37aSMintz, Yuval 1981a044df83SYuval Mintz /* Legacy VFs have their Producers in a different location, which they 1982a044df83SYuval Mintz * calculate on their own and clean the producer prior to this. 1983a044df83SYuval Mintz */ 1984a044df83SYuval Mintz if (vf->acquire.vfdev_info.eth_fp_hsi_minor == 1985a044df83SYuval Mintz ETH_HSI_VER_NO_PKT_LEN_TUNN) { 1986a044df83SYuval Mintz b_legacy_vf = true; 1987a044df83SYuval Mintz } else { 1988a044df83SYuval Mintz REG_WR(p_hwfn, 1989a044df83SYuval Mintz GTT_BAR0_MAP_REG_MSDM_RAM + 1990a044df83SYuval Mintz MSTORM_ETH_VF_PRODS_OFFSET(vf->abs_vf_id, req->rx_qid), 1991a044df83SYuval Mintz 0); 1992a044df83SYuval Mintz } 19933da7a37aSMintz, Yuval p_queue->p_rx_cid->b_legacy_vf = b_legacy_vf; 1994a044df83SYuval Mintz 19953da7a37aSMintz, Yuval rc = qed_eth_rxq_start_ramrod(p_hwfn, 19963da7a37aSMintz, Yuval p_queue->p_rx_cid, 1997dacd88d6SYuval Mintz req->bd_max_bytes, 1998dacd88d6SYuval Mintz req->rxq_addr, 19993da7a37aSMintz, Yuval req->cqe_pbl_addr, req->cqe_pbl_size); 2000dacd88d6SYuval Mintz if (rc) { 2001dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 20023da7a37aSMintz, Yuval qed_eth_queue_cid_release(p_hwfn, p_queue->p_rx_cid); 20033da7a37aSMintz, Yuval p_queue->p_rx_cid = NULL; 2004dacd88d6SYuval Mintz } else { 200541086467SYuval Mintz status = PFVF_STATUS_SUCCESS; 2006dacd88d6SYuval Mintz vf->num_active_rxqs++; 2007dacd88d6SYuval Mintz } 2008dacd88d6SYuval Mintz 200941086467SYuval Mintz out: 2010a044df83SYuval Mintz qed_iov_vf_mbx_start_rxq_resp(p_hwfn, p_ptt, vf, status, b_legacy_vf); 2011dacd88d6SYuval Mintz } 2012dacd88d6SYuval Mintz 2013eaf3c0c6SChopra, Manish static void 2014eaf3c0c6SChopra, Manish qed_iov_pf_update_tun_response(struct pfvf_update_tunn_param_tlv *p_resp, 2015eaf3c0c6SChopra, Manish struct qed_tunnel_info *p_tun, 2016eaf3c0c6SChopra, Manish u16 tunn_feature_mask) 2017eaf3c0c6SChopra, Manish { 2018eaf3c0c6SChopra, Manish p_resp->tunn_feature_mask = tunn_feature_mask; 2019eaf3c0c6SChopra, Manish p_resp->vxlan_mode = p_tun->vxlan.b_mode_enabled; 2020eaf3c0c6SChopra, Manish p_resp->l2geneve_mode = p_tun->l2_geneve.b_mode_enabled; 2021eaf3c0c6SChopra, Manish p_resp->ipgeneve_mode = p_tun->ip_geneve.b_mode_enabled; 2022eaf3c0c6SChopra, Manish p_resp->l2gre_mode = p_tun->l2_gre.b_mode_enabled; 2023eaf3c0c6SChopra, Manish p_resp->ipgre_mode = p_tun->l2_gre.b_mode_enabled; 2024eaf3c0c6SChopra, Manish p_resp->vxlan_clss = p_tun->vxlan.tun_cls; 2025eaf3c0c6SChopra, Manish p_resp->l2gre_clss = p_tun->l2_gre.tun_cls; 2026eaf3c0c6SChopra, Manish p_resp->ipgre_clss = p_tun->ip_gre.tun_cls; 2027eaf3c0c6SChopra, Manish p_resp->l2geneve_clss = p_tun->l2_geneve.tun_cls; 2028eaf3c0c6SChopra, Manish p_resp->ipgeneve_clss = p_tun->ip_geneve.tun_cls; 2029eaf3c0c6SChopra, Manish p_resp->geneve_udp_port = p_tun->geneve_port.port; 2030eaf3c0c6SChopra, Manish p_resp->vxlan_udp_port = p_tun->vxlan_port.port; 2031eaf3c0c6SChopra, Manish } 2032eaf3c0c6SChopra, Manish 2033eaf3c0c6SChopra, Manish static void 2034eaf3c0c6SChopra, Manish __qed_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv *p_req, 2035eaf3c0c6SChopra, Manish struct qed_tunn_update_type *p_tun, 2036eaf3c0c6SChopra, Manish enum qed_tunn_mode mask, u8 tun_cls) 2037eaf3c0c6SChopra, Manish { 2038eaf3c0c6SChopra, Manish if (p_req->tun_mode_update_mask & BIT(mask)) { 2039eaf3c0c6SChopra, Manish p_tun->b_update_mode = true; 2040eaf3c0c6SChopra, Manish 2041eaf3c0c6SChopra, Manish if (p_req->tunn_mode & BIT(mask)) 2042eaf3c0c6SChopra, Manish p_tun->b_mode_enabled = true; 2043eaf3c0c6SChopra, Manish } 2044eaf3c0c6SChopra, Manish 2045eaf3c0c6SChopra, Manish p_tun->tun_cls = tun_cls; 2046eaf3c0c6SChopra, Manish } 2047eaf3c0c6SChopra, Manish 2048eaf3c0c6SChopra, Manish static void 2049eaf3c0c6SChopra, Manish qed_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv *p_req, 2050eaf3c0c6SChopra, Manish struct qed_tunn_update_type *p_tun, 2051eaf3c0c6SChopra, Manish struct qed_tunn_update_udp_port *p_port, 2052eaf3c0c6SChopra, Manish enum qed_tunn_mode mask, 2053eaf3c0c6SChopra, Manish u8 tun_cls, u8 update_port, u16 port) 2054eaf3c0c6SChopra, Manish { 2055eaf3c0c6SChopra, Manish if (update_port) { 2056eaf3c0c6SChopra, Manish p_port->b_update_port = true; 2057eaf3c0c6SChopra, Manish p_port->port = port; 2058eaf3c0c6SChopra, Manish } 2059eaf3c0c6SChopra, Manish 2060eaf3c0c6SChopra, Manish __qed_iov_pf_update_tun_param(p_req, p_tun, mask, tun_cls); 2061eaf3c0c6SChopra, Manish } 2062eaf3c0c6SChopra, Manish 2063eaf3c0c6SChopra, Manish static bool 2064eaf3c0c6SChopra, Manish qed_iov_pf_validate_tunn_param(struct vfpf_update_tunn_param_tlv *p_req) 2065eaf3c0c6SChopra, Manish { 2066eaf3c0c6SChopra, Manish bool b_update_requested = false; 2067eaf3c0c6SChopra, Manish 2068eaf3c0c6SChopra, Manish if (p_req->tun_mode_update_mask || p_req->update_tun_cls || 2069eaf3c0c6SChopra, Manish p_req->update_geneve_port || p_req->update_vxlan_port) 2070eaf3c0c6SChopra, Manish b_update_requested = true; 2071eaf3c0c6SChopra, Manish 2072eaf3c0c6SChopra, Manish return b_update_requested; 2073eaf3c0c6SChopra, Manish } 2074eaf3c0c6SChopra, Manish 2075eaf3c0c6SChopra, Manish static void qed_pf_validate_tunn_mode(struct qed_tunn_update_type *tun, int *rc) 2076eaf3c0c6SChopra, Manish { 2077eaf3c0c6SChopra, Manish if (tun->b_update_mode && !tun->b_mode_enabled) { 2078eaf3c0c6SChopra, Manish tun->b_update_mode = false; 2079eaf3c0c6SChopra, Manish *rc = -EINVAL; 2080eaf3c0c6SChopra, Manish } 2081eaf3c0c6SChopra, Manish } 2082eaf3c0c6SChopra, Manish 2083eaf3c0c6SChopra, Manish static int 2084eaf3c0c6SChopra, Manish qed_pf_validate_modify_tunn_config(struct qed_hwfn *p_hwfn, 2085eaf3c0c6SChopra, Manish u16 *tun_features, bool *update, 2086eaf3c0c6SChopra, Manish struct qed_tunnel_info *tun_src) 2087eaf3c0c6SChopra, Manish { 2088eaf3c0c6SChopra, Manish struct qed_eth_cb_ops *ops = p_hwfn->cdev->protocol_ops.eth; 2089eaf3c0c6SChopra, Manish struct qed_tunnel_info *tun = &p_hwfn->cdev->tunnel; 2090eaf3c0c6SChopra, Manish u16 bultn_vxlan_port, bultn_geneve_port; 2091eaf3c0c6SChopra, Manish void *cookie = p_hwfn->cdev->ops_cookie; 2092eaf3c0c6SChopra, Manish int i, rc = 0; 2093eaf3c0c6SChopra, Manish 2094eaf3c0c6SChopra, Manish *tun_features = p_hwfn->cdev->tunn_feature_mask; 2095eaf3c0c6SChopra, Manish bultn_vxlan_port = tun->vxlan_port.port; 2096eaf3c0c6SChopra, Manish bultn_geneve_port = tun->geneve_port.port; 2097eaf3c0c6SChopra, Manish qed_pf_validate_tunn_mode(&tun_src->vxlan, &rc); 2098eaf3c0c6SChopra, Manish qed_pf_validate_tunn_mode(&tun_src->l2_geneve, &rc); 2099eaf3c0c6SChopra, Manish qed_pf_validate_tunn_mode(&tun_src->ip_geneve, &rc); 2100eaf3c0c6SChopra, Manish qed_pf_validate_tunn_mode(&tun_src->l2_gre, &rc); 2101eaf3c0c6SChopra, Manish qed_pf_validate_tunn_mode(&tun_src->ip_gre, &rc); 2102eaf3c0c6SChopra, Manish 2103eaf3c0c6SChopra, Manish if ((tun_src->b_update_rx_cls || tun_src->b_update_tx_cls) && 2104eaf3c0c6SChopra, Manish (tun_src->vxlan.tun_cls != QED_TUNN_CLSS_MAC_VLAN || 2105eaf3c0c6SChopra, Manish tun_src->l2_geneve.tun_cls != QED_TUNN_CLSS_MAC_VLAN || 2106eaf3c0c6SChopra, Manish tun_src->ip_geneve.tun_cls != QED_TUNN_CLSS_MAC_VLAN || 2107eaf3c0c6SChopra, Manish tun_src->l2_gre.tun_cls != QED_TUNN_CLSS_MAC_VLAN || 2108eaf3c0c6SChopra, Manish tun_src->ip_gre.tun_cls != QED_TUNN_CLSS_MAC_VLAN)) { 2109eaf3c0c6SChopra, Manish tun_src->b_update_rx_cls = false; 2110eaf3c0c6SChopra, Manish tun_src->b_update_tx_cls = false; 2111eaf3c0c6SChopra, Manish rc = -EINVAL; 2112eaf3c0c6SChopra, Manish } 2113eaf3c0c6SChopra, Manish 2114eaf3c0c6SChopra, Manish if (tun_src->vxlan_port.b_update_port) { 2115eaf3c0c6SChopra, Manish if (tun_src->vxlan_port.port == tun->vxlan_port.port) { 2116eaf3c0c6SChopra, Manish tun_src->vxlan_port.b_update_port = false; 2117eaf3c0c6SChopra, Manish } else { 2118eaf3c0c6SChopra, Manish *update = true; 2119eaf3c0c6SChopra, Manish bultn_vxlan_port = tun_src->vxlan_port.port; 2120eaf3c0c6SChopra, Manish } 2121eaf3c0c6SChopra, Manish } 2122eaf3c0c6SChopra, Manish 2123eaf3c0c6SChopra, Manish if (tun_src->geneve_port.b_update_port) { 2124eaf3c0c6SChopra, Manish if (tun_src->geneve_port.port == tun->geneve_port.port) { 2125eaf3c0c6SChopra, Manish tun_src->geneve_port.b_update_port = false; 2126eaf3c0c6SChopra, Manish } else { 2127eaf3c0c6SChopra, Manish *update = true; 2128eaf3c0c6SChopra, Manish bultn_geneve_port = tun_src->geneve_port.port; 2129eaf3c0c6SChopra, Manish } 2130eaf3c0c6SChopra, Manish } 2131eaf3c0c6SChopra, Manish 2132eaf3c0c6SChopra, Manish qed_for_each_vf(p_hwfn, i) { 2133eaf3c0c6SChopra, Manish qed_iov_bulletin_set_udp_ports(p_hwfn, i, bultn_vxlan_port, 2134eaf3c0c6SChopra, Manish bultn_geneve_port); 2135eaf3c0c6SChopra, Manish } 2136eaf3c0c6SChopra, Manish 2137eaf3c0c6SChopra, Manish qed_schedule_iov(p_hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 2138eaf3c0c6SChopra, Manish ops->ports_update(cookie, bultn_vxlan_port, bultn_geneve_port); 2139eaf3c0c6SChopra, Manish 2140eaf3c0c6SChopra, Manish return rc; 2141eaf3c0c6SChopra, Manish } 2142eaf3c0c6SChopra, Manish 2143eaf3c0c6SChopra, Manish static void qed_iov_vf_mbx_update_tunn_param(struct qed_hwfn *p_hwfn, 2144eaf3c0c6SChopra, Manish struct qed_ptt *p_ptt, 2145eaf3c0c6SChopra, Manish struct qed_vf_info *p_vf) 2146eaf3c0c6SChopra, Manish { 2147eaf3c0c6SChopra, Manish struct qed_tunnel_info *p_tun = &p_hwfn->cdev->tunnel; 2148eaf3c0c6SChopra, Manish struct qed_iov_vf_mbx *mbx = &p_vf->vf_mbx; 2149eaf3c0c6SChopra, Manish struct pfvf_update_tunn_param_tlv *p_resp; 2150eaf3c0c6SChopra, Manish struct vfpf_update_tunn_param_tlv *p_req; 2151eaf3c0c6SChopra, Manish u8 status = PFVF_STATUS_SUCCESS; 2152eaf3c0c6SChopra, Manish bool b_update_required = false; 2153eaf3c0c6SChopra, Manish struct qed_tunnel_info tunn; 2154eaf3c0c6SChopra, Manish u16 tunn_feature_mask = 0; 2155eaf3c0c6SChopra, Manish int i, rc = 0; 2156eaf3c0c6SChopra, Manish 2157eaf3c0c6SChopra, Manish mbx->offset = (u8 *)mbx->reply_virt; 2158eaf3c0c6SChopra, Manish 2159eaf3c0c6SChopra, Manish memset(&tunn, 0, sizeof(tunn)); 2160eaf3c0c6SChopra, Manish p_req = &mbx->req_virt->tunn_param_update; 2161eaf3c0c6SChopra, Manish 2162eaf3c0c6SChopra, Manish if (!qed_iov_pf_validate_tunn_param(p_req)) { 2163eaf3c0c6SChopra, Manish DP_VERBOSE(p_hwfn, QED_MSG_IOV, 2164eaf3c0c6SChopra, Manish "No tunnel update requested by VF\n"); 2165eaf3c0c6SChopra, Manish status = PFVF_STATUS_FAILURE; 2166eaf3c0c6SChopra, Manish goto send_resp; 2167eaf3c0c6SChopra, Manish } 2168eaf3c0c6SChopra, Manish 2169eaf3c0c6SChopra, Manish tunn.b_update_rx_cls = p_req->update_tun_cls; 2170eaf3c0c6SChopra, Manish tunn.b_update_tx_cls = p_req->update_tun_cls; 2171eaf3c0c6SChopra, Manish 2172eaf3c0c6SChopra, Manish qed_iov_pf_update_tun_param(p_req, &tunn.vxlan, &tunn.vxlan_port, 2173eaf3c0c6SChopra, Manish QED_MODE_VXLAN_TUNN, p_req->vxlan_clss, 2174eaf3c0c6SChopra, Manish p_req->update_vxlan_port, 2175eaf3c0c6SChopra, Manish p_req->vxlan_port); 2176eaf3c0c6SChopra, Manish qed_iov_pf_update_tun_param(p_req, &tunn.l2_geneve, &tunn.geneve_port, 2177eaf3c0c6SChopra, Manish QED_MODE_L2GENEVE_TUNN, 2178eaf3c0c6SChopra, Manish p_req->l2geneve_clss, 2179eaf3c0c6SChopra, Manish p_req->update_geneve_port, 2180eaf3c0c6SChopra, Manish p_req->geneve_port); 2181eaf3c0c6SChopra, Manish __qed_iov_pf_update_tun_param(p_req, &tunn.ip_geneve, 2182eaf3c0c6SChopra, Manish QED_MODE_IPGENEVE_TUNN, 2183eaf3c0c6SChopra, Manish p_req->ipgeneve_clss); 2184eaf3c0c6SChopra, Manish __qed_iov_pf_update_tun_param(p_req, &tunn.l2_gre, 2185eaf3c0c6SChopra, Manish QED_MODE_L2GRE_TUNN, p_req->l2gre_clss); 2186eaf3c0c6SChopra, Manish __qed_iov_pf_update_tun_param(p_req, &tunn.ip_gre, 2187eaf3c0c6SChopra, Manish QED_MODE_IPGRE_TUNN, p_req->ipgre_clss); 2188eaf3c0c6SChopra, Manish 2189eaf3c0c6SChopra, Manish /* If PF modifies VF's req then it should 2190eaf3c0c6SChopra, Manish * still return an error in case of partial configuration 2191eaf3c0c6SChopra, Manish * or modified configuration as opposed to requested one. 2192eaf3c0c6SChopra, Manish */ 2193eaf3c0c6SChopra, Manish rc = qed_pf_validate_modify_tunn_config(p_hwfn, &tunn_feature_mask, 2194eaf3c0c6SChopra, Manish &b_update_required, &tunn); 2195eaf3c0c6SChopra, Manish 2196eaf3c0c6SChopra, Manish if (rc) 2197eaf3c0c6SChopra, Manish status = PFVF_STATUS_FAILURE; 2198eaf3c0c6SChopra, Manish 2199eaf3c0c6SChopra, Manish /* If QED client is willing to update anything ? */ 2200eaf3c0c6SChopra, Manish if (b_update_required) { 2201eaf3c0c6SChopra, Manish u16 geneve_port; 2202eaf3c0c6SChopra, Manish 22034f64675fSManish Chopra rc = qed_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, &tunn, 2204eaf3c0c6SChopra, Manish QED_SPQ_MODE_EBLOCK, NULL); 2205eaf3c0c6SChopra, Manish if (rc) 2206eaf3c0c6SChopra, Manish status = PFVF_STATUS_FAILURE; 2207eaf3c0c6SChopra, Manish 2208eaf3c0c6SChopra, Manish geneve_port = p_tun->geneve_port.port; 2209eaf3c0c6SChopra, Manish qed_for_each_vf(p_hwfn, i) { 2210eaf3c0c6SChopra, Manish qed_iov_bulletin_set_udp_ports(p_hwfn, i, 2211eaf3c0c6SChopra, Manish p_tun->vxlan_port.port, 2212eaf3c0c6SChopra, Manish geneve_port); 2213eaf3c0c6SChopra, Manish } 2214eaf3c0c6SChopra, Manish } 2215eaf3c0c6SChopra, Manish 2216eaf3c0c6SChopra, Manish send_resp: 2217eaf3c0c6SChopra, Manish p_resp = qed_add_tlv(p_hwfn, &mbx->offset, 2218eaf3c0c6SChopra, Manish CHANNEL_TLV_UPDATE_TUNN_PARAM, sizeof(*p_resp)); 2219eaf3c0c6SChopra, Manish 2220eaf3c0c6SChopra, Manish qed_iov_pf_update_tun_response(p_resp, p_tun, tunn_feature_mask); 2221eaf3c0c6SChopra, Manish qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 2222eaf3c0c6SChopra, Manish sizeof(struct channel_list_end_tlv)); 2223eaf3c0c6SChopra, Manish 2224eaf3c0c6SChopra, Manish qed_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status); 2225eaf3c0c6SChopra, Manish } 2226eaf3c0c6SChopra, Manish 22275040acf5SYuval Mintz static void qed_iov_vf_mbx_start_txq_resp(struct qed_hwfn *p_hwfn, 22285040acf5SYuval Mintz struct qed_ptt *p_ptt, 22295040acf5SYuval Mintz struct qed_vf_info *p_vf, u8 status) 22305040acf5SYuval Mintz { 22315040acf5SYuval Mintz struct qed_iov_vf_mbx *mbx = &p_vf->vf_mbx; 22325040acf5SYuval Mintz struct pfvf_start_queue_resp_tlv *p_tlv; 2233a044df83SYuval Mintz bool b_legacy = false; 2234a044df83SYuval Mintz u16 length; 22355040acf5SYuval Mintz 22365040acf5SYuval Mintz mbx->offset = (u8 *)mbx->reply_virt; 22375040acf5SYuval Mintz 2238a044df83SYuval Mintz /* Taking a bigger struct instead of adding a TLV to list was a 2239a044df83SYuval Mintz * mistake, but one which we're now stuck with, as some older 2240a044df83SYuval Mintz * clients assume the size of the previous response. 2241a044df83SYuval Mintz */ 2242a044df83SYuval Mintz if (p_vf->acquire.vfdev_info.eth_fp_hsi_minor == 2243a044df83SYuval Mintz ETH_HSI_VER_NO_PKT_LEN_TUNN) 2244a044df83SYuval Mintz b_legacy = true; 2245a044df83SYuval Mintz 2246a044df83SYuval Mintz if (!b_legacy) 2247a044df83SYuval Mintz length = sizeof(*p_tlv); 2248a044df83SYuval Mintz else 2249a044df83SYuval Mintz length = sizeof(struct pfvf_def_resp_tlv); 2250a044df83SYuval Mintz 22515040acf5SYuval Mintz p_tlv = qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_START_TXQ, 2252a044df83SYuval Mintz length); 22535040acf5SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 22545040acf5SYuval Mintz sizeof(struct channel_list_end_tlv)); 22555040acf5SYuval Mintz 22565040acf5SYuval Mintz /* Update the TLV with the response */ 2257a044df83SYuval Mintz if ((status == PFVF_STATUS_SUCCESS) && !b_legacy) { 22585040acf5SYuval Mintz u16 qid = mbx->req_virt->start_txq.tx_qid; 22595040acf5SYuval Mintz 226051ff1725SRam Amrani p_tlv->offset = qed_db_addr_vf(p_vf->vf_queues[qid].fw_cid, 22615040acf5SYuval Mintz DQ_DEMS_LEGACY); 22625040acf5SYuval Mintz } 22635040acf5SYuval Mintz 2264a044df83SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, p_vf, length, status); 22655040acf5SYuval Mintz } 22665040acf5SYuval Mintz 2267dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn, 2268dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 2269dacd88d6SYuval Mintz struct qed_vf_info *vf) 2270dacd88d6SYuval Mintz { 2271dacd88d6SYuval Mintz struct qed_queue_start_common_params params; 2272dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 227341086467SYuval Mintz u8 status = PFVF_STATUS_NO_RESOURCE; 2274dacd88d6SYuval Mintz struct vfpf_start_txq_tlv *req; 22753da7a37aSMintz, Yuval struct qed_vf_q_info *p_queue; 2276dacd88d6SYuval Mintz int rc; 22773da7a37aSMintz, Yuval u16 pq; 2278dacd88d6SYuval Mintz 2279dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(params)); 2280dacd88d6SYuval Mintz req = &mbx->req_virt->start_txq; 228141086467SYuval Mintz 2282f109c240SMintz, Yuval if (!qed_iov_validate_txq(p_hwfn, vf, req->tx_qid, 2283f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_DISABLE) || 228441086467SYuval Mintz !qed_iov_validate_sb(p_hwfn, vf, req->hw_sb)) 228541086467SYuval Mintz goto out; 228641086467SYuval Mintz 22873da7a37aSMintz, Yuval /* Acquire a new queue-cid */ 22883da7a37aSMintz, Yuval p_queue = &vf->vf_queues[req->tx_qid]; 22893da7a37aSMintz, Yuval 22903da7a37aSMintz, Yuval params.queue_id = p_queue->fw_tx_qid; 2291dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 22923da7a37aSMintz, Yuval params.stats_id = vf->abs_vf_id + 0x10; 2293dacd88d6SYuval Mintz params.sb = req->hw_sb; 2294dacd88d6SYuval Mintz params.sb_idx = req->sb_index; 2295dacd88d6SYuval Mintz 22963da7a37aSMintz, Yuval p_queue->p_tx_cid = _qed_eth_queue_to_cid(p_hwfn, 2297dacd88d6SYuval Mintz vf->opaque_fid, 22983da7a37aSMintz, Yuval p_queue->fw_cid, 22993da7a37aSMintz, Yuval req->tx_qid, ¶ms); 23003da7a37aSMintz, Yuval if (!p_queue->p_tx_cid) 23013da7a37aSMintz, Yuval goto out; 2302dacd88d6SYuval Mintz 2303b5a9ee7cSAriel Elior pq = qed_get_cm_pq_idx_vf(p_hwfn, vf->relative_vf_id); 23043da7a37aSMintz, Yuval rc = qed_eth_txq_start_ramrod(p_hwfn, p_queue->p_tx_cid, 23053da7a37aSMintz, Yuval req->pbl_addr, req->pbl_size, pq); 230641086467SYuval Mintz if (rc) { 2307dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 23083da7a37aSMintz, Yuval qed_eth_queue_cid_release(p_hwfn, p_queue->p_tx_cid); 23093da7a37aSMintz, Yuval p_queue->p_tx_cid = NULL; 231041086467SYuval Mintz } else { 231141086467SYuval Mintz status = PFVF_STATUS_SUCCESS; 231241086467SYuval Mintz } 2313dacd88d6SYuval Mintz 231441086467SYuval Mintz out: 23155040acf5SYuval Mintz qed_iov_vf_mbx_start_txq_resp(p_hwfn, p_ptt, vf, status); 2316dacd88d6SYuval Mintz } 2317dacd88d6SYuval Mintz 2318dacd88d6SYuval Mintz static int qed_iov_vf_stop_rxqs(struct qed_hwfn *p_hwfn, 2319dacd88d6SYuval Mintz struct qed_vf_info *vf, 23204c4fa793SMintz, Yuval u16 rxq_id, bool cqe_completion) 2321dacd88d6SYuval Mintz { 23223da7a37aSMintz, Yuval struct qed_vf_q_info *p_queue; 2323dacd88d6SYuval Mintz int rc = 0; 2324dacd88d6SYuval Mintz 23254c4fa793SMintz, Yuval if (!qed_iov_validate_rxq(p_hwfn, vf, rxq_id, 23264c4fa793SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE)) { 23274c4fa793SMintz, Yuval DP_VERBOSE(p_hwfn, 23284c4fa793SMintz, Yuval QED_MSG_IOV, 23294c4fa793SMintz, Yuval "VF[%d] Tried Closing Rx 0x%04x which is inactive\n", 23304c4fa793SMintz, Yuval vf->relative_vf_id, rxq_id); 2331dacd88d6SYuval Mintz return -EINVAL; 23324c4fa793SMintz, Yuval } 2333dacd88d6SYuval Mintz 23344c4fa793SMintz, Yuval p_queue = &vf->vf_queues[rxq_id]; 23353da7a37aSMintz, Yuval 23363da7a37aSMintz, Yuval rc = qed_eth_rx_queue_stop(p_hwfn, 23373da7a37aSMintz, Yuval p_queue->p_rx_cid, 23383da7a37aSMintz, Yuval false, cqe_completion); 2339dacd88d6SYuval Mintz if (rc) 2340dacd88d6SYuval Mintz return rc; 23413da7a37aSMintz, Yuval 23424c4fa793SMintz, Yuval p_queue->p_rx_cid = NULL; 2343dacd88d6SYuval Mintz vf->num_active_rxqs--; 2344dacd88d6SYuval Mintz 23454c4fa793SMintz, Yuval return 0; 2346dacd88d6SYuval Mintz } 2347dacd88d6SYuval Mintz 2348dacd88d6SYuval Mintz static int qed_iov_vf_stop_txqs(struct qed_hwfn *p_hwfn, 23494c4fa793SMintz, Yuval struct qed_vf_info *vf, u16 txq_id) 2350dacd88d6SYuval Mintz { 23513da7a37aSMintz, Yuval struct qed_vf_q_info *p_queue; 23524c4fa793SMintz, Yuval int rc = 0; 2353dacd88d6SYuval Mintz 23544c4fa793SMintz, Yuval if (!qed_iov_validate_txq(p_hwfn, vf, txq_id, 23554c4fa793SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE)) 2356dacd88d6SYuval Mintz return -EINVAL; 2357dacd88d6SYuval Mintz 23584c4fa793SMintz, Yuval p_queue = &vf->vf_queues[txq_id]; 2359dacd88d6SYuval Mintz 23603da7a37aSMintz, Yuval rc = qed_eth_tx_queue_stop(p_hwfn, p_queue->p_tx_cid); 2361dacd88d6SYuval Mintz if (rc) 2362dacd88d6SYuval Mintz return rc; 23633da7a37aSMintz, Yuval 23643da7a37aSMintz, Yuval p_queue->p_tx_cid = NULL; 23653da7a37aSMintz, Yuval 23664c4fa793SMintz, Yuval return 0; 2367dacd88d6SYuval Mintz } 2368dacd88d6SYuval Mintz 2369dacd88d6SYuval Mintz static void qed_iov_vf_mbx_stop_rxqs(struct qed_hwfn *p_hwfn, 2370dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 2371dacd88d6SYuval Mintz struct qed_vf_info *vf) 2372dacd88d6SYuval Mintz { 2373dacd88d6SYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 2374dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 23754c4fa793SMintz, Yuval u8 status = PFVF_STATUS_FAILURE; 2376dacd88d6SYuval Mintz struct vfpf_stop_rxqs_tlv *req; 2377dacd88d6SYuval Mintz int rc; 2378dacd88d6SYuval Mintz 23794c4fa793SMintz, Yuval /* There has never been an official driver that used this interface 23804c4fa793SMintz, Yuval * for stopping multiple queues, and it is now considered deprecated. 23814c4fa793SMintz, Yuval * Validate this isn't used here. 2382dacd88d6SYuval Mintz */ 2383dacd88d6SYuval Mintz req = &mbx->req_virt->stop_rxqs; 23844c4fa793SMintz, Yuval if (req->num_rxqs != 1) { 23854c4fa793SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_IOV, 23864c4fa793SMintz, Yuval "Odd; VF[%d] tried stopping multiple Rx queues\n", 23874c4fa793SMintz, Yuval vf->relative_vf_id); 23884c4fa793SMintz, Yuval status = PFVF_STATUS_NOT_SUPPORTED; 23894c4fa793SMintz, Yuval goto out; 23904c4fa793SMintz, Yuval } 2391dacd88d6SYuval Mintz 23924c4fa793SMintz, Yuval rc = qed_iov_vf_stop_rxqs(p_hwfn, vf, req->rx_qid, 23934c4fa793SMintz, Yuval req->cqe_completion); 23944c4fa793SMintz, Yuval if (!rc) 23954c4fa793SMintz, Yuval status = PFVF_STATUS_SUCCESS; 23964c4fa793SMintz, Yuval out: 2397dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_RXQS, 2398dacd88d6SYuval Mintz length, status); 2399dacd88d6SYuval Mintz } 2400dacd88d6SYuval Mintz 2401dacd88d6SYuval Mintz static void qed_iov_vf_mbx_stop_txqs(struct qed_hwfn *p_hwfn, 2402dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 2403dacd88d6SYuval Mintz struct qed_vf_info *vf) 2404dacd88d6SYuval Mintz { 2405dacd88d6SYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 2406dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 24074c4fa793SMintz, Yuval u8 status = PFVF_STATUS_FAILURE; 2408dacd88d6SYuval Mintz struct vfpf_stop_txqs_tlv *req; 2409dacd88d6SYuval Mintz int rc; 2410dacd88d6SYuval Mintz 24114c4fa793SMintz, Yuval /* There has never been an official driver that used this interface 24124c4fa793SMintz, Yuval * for stopping multiple queues, and it is now considered deprecated. 24134c4fa793SMintz, Yuval * Validate this isn't used here. 2414dacd88d6SYuval Mintz */ 2415dacd88d6SYuval Mintz req = &mbx->req_virt->stop_txqs; 24164c4fa793SMintz, Yuval if (req->num_txqs != 1) { 24174c4fa793SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_IOV, 24184c4fa793SMintz, Yuval "Odd; VF[%d] tried stopping multiple Tx queues\n", 24194c4fa793SMintz, Yuval vf->relative_vf_id); 24204c4fa793SMintz, Yuval status = PFVF_STATUS_NOT_SUPPORTED; 24214c4fa793SMintz, Yuval goto out; 24224c4fa793SMintz, Yuval } 24234c4fa793SMintz, Yuval rc = qed_iov_vf_stop_txqs(p_hwfn, vf, req->tx_qid); 24244c4fa793SMintz, Yuval if (!rc) 24254c4fa793SMintz, Yuval status = PFVF_STATUS_SUCCESS; 2426dacd88d6SYuval Mintz 24274c4fa793SMintz, Yuval out: 2428dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_TXQS, 2429dacd88d6SYuval Mintz length, status); 2430dacd88d6SYuval Mintz } 2431dacd88d6SYuval Mintz 243217b235c1SYuval Mintz static void qed_iov_vf_mbx_update_rxqs(struct qed_hwfn *p_hwfn, 243317b235c1SYuval Mintz struct qed_ptt *p_ptt, 243417b235c1SYuval Mintz struct qed_vf_info *vf) 243517b235c1SYuval Mintz { 24363da7a37aSMintz, Yuval struct qed_queue_cid *handlers[QED_MAX_VF_CHAINS_PER_PF]; 243717b235c1SYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 243817b235c1SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 243917b235c1SYuval Mintz struct vfpf_update_rxq_tlv *req; 24403da7a37aSMintz, Yuval u8 status = PFVF_STATUS_FAILURE; 244117b235c1SYuval Mintz u8 complete_event_flg; 244217b235c1SYuval Mintz u8 complete_cqe_flg; 244317b235c1SYuval Mintz u16 qid; 244417b235c1SYuval Mintz int rc; 244517b235c1SYuval Mintz u8 i; 244617b235c1SYuval Mintz 244717b235c1SYuval Mintz req = &mbx->req_virt->update_rxq; 244817b235c1SYuval Mintz complete_cqe_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_CQE_FLAG); 244917b235c1SYuval Mintz complete_event_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_EVENT_FLAG); 245017b235c1SYuval Mintz 24513da7a37aSMintz, Yuval /* Validate inputs */ 2452f109c240SMintz, Yuval for (i = req->rx_qid; i < req->rx_qid + req->num_rxqs; i++) 2453f109c240SMintz, Yuval if (!qed_iov_validate_rxq(p_hwfn, vf, i, 2454f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE)) { 24553da7a37aSMintz, Yuval DP_INFO(p_hwfn, "VF[%d]: Incorrect Rxqs [%04x, %02x]\n", 24563da7a37aSMintz, Yuval vf->relative_vf_id, req->rx_qid, req->num_rxqs); 24573da7a37aSMintz, Yuval goto out; 245817b235c1SYuval Mintz } 245917b235c1SYuval Mintz 2460f109c240SMintz, Yuval /* Prepare the handlers */ 24613da7a37aSMintz, Yuval for (i = 0; i < req->num_rxqs; i++) { 24623da7a37aSMintz, Yuval qid = req->rx_qid + i; 24633da7a37aSMintz, Yuval handlers[i] = vf->vf_queues[qid].p_rx_cid; 24643da7a37aSMintz, Yuval } 24653da7a37aSMintz, Yuval 24663da7a37aSMintz, Yuval rc = qed_sp_eth_rx_queues_update(p_hwfn, (void **)&handlers, 24673da7a37aSMintz, Yuval req->num_rxqs, 246817b235c1SYuval Mintz complete_cqe_flg, 246917b235c1SYuval Mintz complete_event_flg, 247017b235c1SYuval Mintz QED_SPQ_MODE_EBLOCK, NULL); 24713da7a37aSMintz, Yuval if (rc) 24723da7a37aSMintz, Yuval goto out; 247317b235c1SYuval Mintz 24743da7a37aSMintz, Yuval status = PFVF_STATUS_SUCCESS; 24753da7a37aSMintz, Yuval out: 247617b235c1SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UPDATE_RXQ, 247717b235c1SYuval Mintz length, status); 247817b235c1SYuval Mintz } 247917b235c1SYuval Mintz 2480dacd88d6SYuval Mintz void *qed_iov_search_list_tlvs(struct qed_hwfn *p_hwfn, 2481dacd88d6SYuval Mintz void *p_tlvs_list, u16 req_type) 2482dacd88d6SYuval Mintz { 2483dacd88d6SYuval Mintz struct channel_tlv *p_tlv = (struct channel_tlv *)p_tlvs_list; 2484dacd88d6SYuval Mintz int len = 0; 2485dacd88d6SYuval Mintz 2486dacd88d6SYuval Mintz do { 2487dacd88d6SYuval Mintz if (!p_tlv->length) { 2488dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, "Zero length TLV found\n"); 2489dacd88d6SYuval Mintz return NULL; 2490dacd88d6SYuval Mintz } 2491dacd88d6SYuval Mintz 2492dacd88d6SYuval Mintz if (p_tlv->type == req_type) { 2493dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 2494dacd88d6SYuval Mintz "Extended tlv type %d, length %d found\n", 2495dacd88d6SYuval Mintz p_tlv->type, p_tlv->length); 2496dacd88d6SYuval Mintz return p_tlv; 2497dacd88d6SYuval Mintz } 2498dacd88d6SYuval Mintz 2499dacd88d6SYuval Mintz len += p_tlv->length; 2500dacd88d6SYuval Mintz p_tlv = (struct channel_tlv *)((u8 *)p_tlv + p_tlv->length); 2501dacd88d6SYuval Mintz 2502dacd88d6SYuval Mintz if ((len + p_tlv->length) > TLV_BUFFER_SIZE) { 2503dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, "TLVs has overrun the buffer size\n"); 2504dacd88d6SYuval Mintz return NULL; 2505dacd88d6SYuval Mintz } 2506dacd88d6SYuval Mintz } while (p_tlv->type != CHANNEL_TLV_LIST_END); 2507dacd88d6SYuval Mintz 2508dacd88d6SYuval Mintz return NULL; 2509dacd88d6SYuval Mintz } 2510dacd88d6SYuval Mintz 2511dacd88d6SYuval Mintz static void 2512dacd88d6SYuval Mintz qed_iov_vp_update_act_param(struct qed_hwfn *p_hwfn, 2513dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2514dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2515dacd88d6SYuval Mintz { 2516dacd88d6SYuval Mintz struct vfpf_vport_update_activate_tlv *p_act_tlv; 2517dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE; 2518dacd88d6SYuval Mintz 2519dacd88d6SYuval Mintz p_act_tlv = (struct vfpf_vport_update_activate_tlv *) 2520dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2521dacd88d6SYuval Mintz if (!p_act_tlv) 2522dacd88d6SYuval Mintz return; 2523dacd88d6SYuval Mintz 2524dacd88d6SYuval Mintz p_data->update_vport_active_rx_flg = p_act_tlv->update_rx; 2525dacd88d6SYuval Mintz p_data->vport_active_rx_flg = p_act_tlv->active_rx; 2526dacd88d6SYuval Mintz p_data->update_vport_active_tx_flg = p_act_tlv->update_tx; 2527dacd88d6SYuval Mintz p_data->vport_active_tx_flg = p_act_tlv->active_tx; 2528dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_ACTIVATE; 2529dacd88d6SYuval Mintz } 2530dacd88d6SYuval Mintz 2531dacd88d6SYuval Mintz static void 253217b235c1SYuval Mintz qed_iov_vp_update_vlan_param(struct qed_hwfn *p_hwfn, 253317b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 253417b235c1SYuval Mintz struct qed_vf_info *p_vf, 253517b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 253617b235c1SYuval Mintz { 253717b235c1SYuval Mintz struct vfpf_vport_update_vlan_strip_tlv *p_vlan_tlv; 253817b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP; 253917b235c1SYuval Mintz 254017b235c1SYuval Mintz p_vlan_tlv = (struct vfpf_vport_update_vlan_strip_tlv *) 254117b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 254217b235c1SYuval Mintz if (!p_vlan_tlv) 254317b235c1SYuval Mintz return; 254417b235c1SYuval Mintz 254508feecd7SYuval Mintz p_vf->shadow_config.inner_vlan_removal = p_vlan_tlv->remove_vlan; 254608feecd7SYuval Mintz 254708feecd7SYuval Mintz /* Ignore the VF request if we're forcing a vlan */ 25481a635e48SYuval Mintz if (!(p_vf->configured_features & BIT(VLAN_ADDR_FORCED))) { 254917b235c1SYuval Mintz p_data->update_inner_vlan_removal_flg = 1; 255017b235c1SYuval Mintz p_data->inner_vlan_removal_flg = p_vlan_tlv->remove_vlan; 255108feecd7SYuval Mintz } 255217b235c1SYuval Mintz 255317b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_VLAN_STRIP; 255417b235c1SYuval Mintz } 255517b235c1SYuval Mintz 255617b235c1SYuval Mintz static void 255717b235c1SYuval Mintz qed_iov_vp_update_tx_switch(struct qed_hwfn *p_hwfn, 255817b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 255917b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 256017b235c1SYuval Mintz { 256117b235c1SYuval Mintz struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv; 256217b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; 256317b235c1SYuval Mintz 256417b235c1SYuval Mintz p_tx_switch_tlv = (struct vfpf_vport_update_tx_switch_tlv *) 256517b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, 256617b235c1SYuval Mintz tlv); 256717b235c1SYuval Mintz if (!p_tx_switch_tlv) 256817b235c1SYuval Mintz return; 256917b235c1SYuval Mintz 257017b235c1SYuval Mintz p_data->update_tx_switching_flg = 1; 257117b235c1SYuval Mintz p_data->tx_switching_flg = p_tx_switch_tlv->tx_switching; 257217b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_TX_SWITCH; 257317b235c1SYuval Mintz } 257417b235c1SYuval Mintz 257517b235c1SYuval Mintz static void 2576dacd88d6SYuval Mintz qed_iov_vp_update_mcast_bin_param(struct qed_hwfn *p_hwfn, 2577dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2578dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2579dacd88d6SYuval Mintz { 2580dacd88d6SYuval Mintz struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv; 2581dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_MCAST; 2582dacd88d6SYuval Mintz 2583dacd88d6SYuval Mintz p_mcast_tlv = (struct vfpf_vport_update_mcast_bin_tlv *) 2584dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2585dacd88d6SYuval Mintz if (!p_mcast_tlv) 2586dacd88d6SYuval Mintz return; 2587dacd88d6SYuval Mintz 2588dacd88d6SYuval Mintz p_data->update_approx_mcast_flg = 1; 2589dacd88d6SYuval Mintz memcpy(p_data->bins, p_mcast_tlv->bins, 2590dacd88d6SYuval Mintz sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS); 2591dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_MCAST; 2592dacd88d6SYuval Mintz } 2593dacd88d6SYuval Mintz 2594dacd88d6SYuval Mintz static void 2595dacd88d6SYuval Mintz qed_iov_vp_update_accept_flag(struct qed_hwfn *p_hwfn, 2596dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2597dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2598dacd88d6SYuval Mintz { 2599dacd88d6SYuval Mintz struct qed_filter_accept_flags *p_flags = &p_data->accept_flags; 2600dacd88d6SYuval Mintz struct vfpf_vport_update_accept_param_tlv *p_accept_tlv; 2601dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; 2602dacd88d6SYuval Mintz 2603dacd88d6SYuval Mintz p_accept_tlv = (struct vfpf_vport_update_accept_param_tlv *) 2604dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2605dacd88d6SYuval Mintz if (!p_accept_tlv) 2606dacd88d6SYuval Mintz return; 2607dacd88d6SYuval Mintz 2608dacd88d6SYuval Mintz p_flags->update_rx_mode_config = p_accept_tlv->update_rx_mode; 2609dacd88d6SYuval Mintz p_flags->rx_accept_filter = p_accept_tlv->rx_accept_filter; 2610dacd88d6SYuval Mintz p_flags->update_tx_mode_config = p_accept_tlv->update_tx_mode; 2611dacd88d6SYuval Mintz p_flags->tx_accept_filter = p_accept_tlv->tx_accept_filter; 2612dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_ACCEPT_PARAM; 2613dacd88d6SYuval Mintz } 2614dacd88d6SYuval Mintz 2615dacd88d6SYuval Mintz static void 261617b235c1SYuval Mintz qed_iov_vp_update_accept_any_vlan(struct qed_hwfn *p_hwfn, 261717b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 261817b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 261917b235c1SYuval Mintz { 262017b235c1SYuval Mintz struct vfpf_vport_update_accept_any_vlan_tlv *p_accept_any_vlan; 262117b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; 262217b235c1SYuval Mintz 262317b235c1SYuval Mintz p_accept_any_vlan = (struct vfpf_vport_update_accept_any_vlan_tlv *) 262417b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, 262517b235c1SYuval Mintz tlv); 262617b235c1SYuval Mintz if (!p_accept_any_vlan) 262717b235c1SYuval Mintz return; 262817b235c1SYuval Mintz 262917b235c1SYuval Mintz p_data->accept_any_vlan = p_accept_any_vlan->accept_any_vlan; 263017b235c1SYuval Mintz p_data->update_accept_any_vlan_flg = 263117b235c1SYuval Mintz p_accept_any_vlan->update_accept_any_vlan_flg; 263217b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_ACCEPT_ANY_VLAN; 263317b235c1SYuval Mintz } 263417b235c1SYuval Mintz 263517b235c1SYuval Mintz static void 2636dacd88d6SYuval Mintz qed_iov_vp_update_rss_param(struct qed_hwfn *p_hwfn, 2637dacd88d6SYuval Mintz struct qed_vf_info *vf, 2638dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2639dacd88d6SYuval Mintz struct qed_rss_params *p_rss, 2640f29ffdb6SMintz, Yuval struct qed_iov_vf_mbx *p_mbx, 2641f29ffdb6SMintz, Yuval u16 *tlvs_mask, u16 *tlvs_accepted) 2642dacd88d6SYuval Mintz { 2643dacd88d6SYuval Mintz struct vfpf_vport_update_rss_tlv *p_rss_tlv; 2644dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_RSS; 2645f29ffdb6SMintz, Yuval bool b_reject = false; 2646dacd88d6SYuval Mintz u16 table_size; 2647f29ffdb6SMintz, Yuval u16 i, q_idx; 2648dacd88d6SYuval Mintz 2649dacd88d6SYuval Mintz p_rss_tlv = (struct vfpf_vport_update_rss_tlv *) 2650dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2651dacd88d6SYuval Mintz if (!p_rss_tlv) { 2652dacd88d6SYuval Mintz p_data->rss_params = NULL; 2653dacd88d6SYuval Mintz return; 2654dacd88d6SYuval Mintz } 2655dacd88d6SYuval Mintz 2656dacd88d6SYuval Mintz memset(p_rss, 0, sizeof(struct qed_rss_params)); 2657dacd88d6SYuval Mintz 2658dacd88d6SYuval Mintz p_rss->update_rss_config = !!(p_rss_tlv->update_rss_flags & 2659dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CONFIG_FLAG); 2660dacd88d6SYuval Mintz p_rss->update_rss_capabilities = !!(p_rss_tlv->update_rss_flags & 2661dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CAPS_FLAG); 2662dacd88d6SYuval Mintz p_rss->update_rss_ind_table = !!(p_rss_tlv->update_rss_flags & 2663dacd88d6SYuval Mintz VFPF_UPDATE_RSS_IND_TABLE_FLAG); 2664dacd88d6SYuval Mintz p_rss->update_rss_key = !!(p_rss_tlv->update_rss_flags & 2665dacd88d6SYuval Mintz VFPF_UPDATE_RSS_KEY_FLAG); 2666dacd88d6SYuval Mintz 2667dacd88d6SYuval Mintz p_rss->rss_enable = p_rss_tlv->rss_enable; 2668dacd88d6SYuval Mintz p_rss->rss_eng_id = vf->relative_vf_id + 1; 2669dacd88d6SYuval Mintz p_rss->rss_caps = p_rss_tlv->rss_caps; 2670dacd88d6SYuval Mintz p_rss->rss_table_size_log = p_rss_tlv->rss_table_size_log; 2671dacd88d6SYuval Mintz memcpy(p_rss->rss_key, p_rss_tlv->rss_key, sizeof(p_rss->rss_key)); 2672dacd88d6SYuval Mintz 2673dacd88d6SYuval Mintz table_size = min_t(u16, ARRAY_SIZE(p_rss->rss_ind_table), 2674dacd88d6SYuval Mintz (1 << p_rss_tlv->rss_table_size_log)); 2675dacd88d6SYuval Mintz 2676dacd88d6SYuval Mintz for (i = 0; i < table_size; i++) { 2677f29ffdb6SMintz, Yuval q_idx = p_rss_tlv->rss_ind_table[i]; 2678f109c240SMintz, Yuval if (!qed_iov_validate_rxq(p_hwfn, vf, q_idx, 2679f109c240SMintz, Yuval QED_IOV_VALIDATE_Q_ENABLE)) { 2680f29ffdb6SMintz, Yuval DP_VERBOSE(p_hwfn, 2681f29ffdb6SMintz, Yuval QED_MSG_IOV, 2682f29ffdb6SMintz, Yuval "VF[%d]: Omitting RSS due to wrong queue %04x\n", 2683f29ffdb6SMintz, Yuval vf->relative_vf_id, q_idx); 2684f29ffdb6SMintz, Yuval b_reject = true; 2685f29ffdb6SMintz, Yuval goto out; 2686f29ffdb6SMintz, Yuval } 2687dacd88d6SYuval Mintz 2688f29ffdb6SMintz, Yuval p_rss->rss_ind_table[i] = vf->vf_queues[q_idx].p_rx_cid; 2689dacd88d6SYuval Mintz } 2690dacd88d6SYuval Mintz 2691dacd88d6SYuval Mintz p_data->rss_params = p_rss; 2692f29ffdb6SMintz, Yuval out: 2693dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_RSS; 2694f29ffdb6SMintz, Yuval if (!b_reject) 2695f29ffdb6SMintz, Yuval *tlvs_accepted |= 1 << QED_IOV_VP_UPDATE_RSS; 2696dacd88d6SYuval Mintz } 2697dacd88d6SYuval Mintz 269817b235c1SYuval Mintz static void 269917b235c1SYuval Mintz qed_iov_vp_update_sge_tpa_param(struct qed_hwfn *p_hwfn, 270017b235c1SYuval Mintz struct qed_vf_info *vf, 270117b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 270217b235c1SYuval Mintz struct qed_sge_tpa_params *p_sge_tpa, 270317b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 270417b235c1SYuval Mintz { 270517b235c1SYuval Mintz struct vfpf_vport_update_sge_tpa_tlv *p_sge_tpa_tlv; 270617b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_SGE_TPA; 270717b235c1SYuval Mintz 270817b235c1SYuval Mintz p_sge_tpa_tlv = (struct vfpf_vport_update_sge_tpa_tlv *) 270917b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 271017b235c1SYuval Mintz 271117b235c1SYuval Mintz if (!p_sge_tpa_tlv) { 271217b235c1SYuval Mintz p_data->sge_tpa_params = NULL; 271317b235c1SYuval Mintz return; 271417b235c1SYuval Mintz } 271517b235c1SYuval Mintz 271617b235c1SYuval Mintz memset(p_sge_tpa, 0, sizeof(struct qed_sge_tpa_params)); 271717b235c1SYuval Mintz 271817b235c1SYuval Mintz p_sge_tpa->update_tpa_en_flg = 271917b235c1SYuval Mintz !!(p_sge_tpa_tlv->update_sge_tpa_flags & VFPF_UPDATE_TPA_EN_FLAG); 272017b235c1SYuval Mintz p_sge_tpa->update_tpa_param_flg = 272117b235c1SYuval Mintz !!(p_sge_tpa_tlv->update_sge_tpa_flags & 272217b235c1SYuval Mintz VFPF_UPDATE_TPA_PARAM_FLAG); 272317b235c1SYuval Mintz 272417b235c1SYuval Mintz p_sge_tpa->tpa_ipv4_en_flg = 272517b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_IPV4_EN_FLAG); 272617b235c1SYuval Mintz p_sge_tpa->tpa_ipv6_en_flg = 272717b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_IPV6_EN_FLAG); 272817b235c1SYuval Mintz p_sge_tpa->tpa_pkt_split_flg = 272917b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_PKT_SPLIT_FLAG); 273017b235c1SYuval Mintz p_sge_tpa->tpa_hdr_data_split_flg = 273117b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_HDR_DATA_SPLIT_FLAG); 273217b235c1SYuval Mintz p_sge_tpa->tpa_gro_consistent_flg = 273317b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_GRO_CONSIST_FLAG); 273417b235c1SYuval Mintz 273517b235c1SYuval Mintz p_sge_tpa->tpa_max_aggs_num = p_sge_tpa_tlv->tpa_max_aggs_num; 273617b235c1SYuval Mintz p_sge_tpa->tpa_max_size = p_sge_tpa_tlv->tpa_max_size; 273717b235c1SYuval Mintz p_sge_tpa->tpa_min_size_to_start = p_sge_tpa_tlv->tpa_min_size_to_start; 273817b235c1SYuval Mintz p_sge_tpa->tpa_min_size_to_cont = p_sge_tpa_tlv->tpa_min_size_to_cont; 273917b235c1SYuval Mintz p_sge_tpa->max_buffers_per_cqe = p_sge_tpa_tlv->max_buffers_per_cqe; 274017b235c1SYuval Mintz 274117b235c1SYuval Mintz p_data->sge_tpa_params = p_sge_tpa; 274217b235c1SYuval Mintz 274317b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_SGE_TPA; 274417b235c1SYuval Mintz } 274517b235c1SYuval Mintz 2746f990c82cSMintz, Yuval static int qed_iov_pre_update_vport(struct qed_hwfn *hwfn, 2747f990c82cSMintz, Yuval u8 vfid, 2748f990c82cSMintz, Yuval struct qed_sp_vport_update_params *params, 2749f990c82cSMintz, Yuval u16 *tlvs) 2750f990c82cSMintz, Yuval { 2751f990c82cSMintz, Yuval u8 mask = QED_ACCEPT_UCAST_UNMATCHED | QED_ACCEPT_MCAST_UNMATCHED; 2752f990c82cSMintz, Yuval struct qed_filter_accept_flags *flags = ¶ms->accept_flags; 2753f990c82cSMintz, Yuval struct qed_public_vf_info *vf_info; 2754f990c82cSMintz, Yuval 2755f990c82cSMintz, Yuval /* Untrusted VFs can't even be trusted to know that fact. 2756f990c82cSMintz, Yuval * Simply indicate everything is configured fine, and trace 2757f990c82cSMintz, Yuval * configuration 'behind their back'. 2758f990c82cSMintz, Yuval */ 2759f990c82cSMintz, Yuval if (!(*tlvs & BIT(QED_IOV_VP_UPDATE_ACCEPT_PARAM))) 2760f990c82cSMintz, Yuval return 0; 2761f990c82cSMintz, Yuval 2762f990c82cSMintz, Yuval vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true); 2763f990c82cSMintz, Yuval 2764f990c82cSMintz, Yuval if (flags->update_rx_mode_config) { 2765f990c82cSMintz, Yuval vf_info->rx_accept_mode = flags->rx_accept_filter; 2766f990c82cSMintz, Yuval if (!vf_info->is_trusted_configured) 2767f990c82cSMintz, Yuval flags->rx_accept_filter &= ~mask; 2768f990c82cSMintz, Yuval } 2769f990c82cSMintz, Yuval 2770f990c82cSMintz, Yuval if (flags->update_tx_mode_config) { 2771f990c82cSMintz, Yuval vf_info->tx_accept_mode = flags->tx_accept_filter; 2772f990c82cSMintz, Yuval if (!vf_info->is_trusted_configured) 2773f990c82cSMintz, Yuval flags->tx_accept_filter &= ~mask; 2774f990c82cSMintz, Yuval } 2775f990c82cSMintz, Yuval 2776f990c82cSMintz, Yuval return 0; 2777f990c82cSMintz, Yuval } 2778f990c82cSMintz, Yuval 2779dacd88d6SYuval Mintz static void qed_iov_vf_mbx_vport_update(struct qed_hwfn *p_hwfn, 2780dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 2781dacd88d6SYuval Mintz struct qed_vf_info *vf) 2782dacd88d6SYuval Mintz { 2783f29ffdb6SMintz, Yuval struct qed_rss_params *p_rss_params = NULL; 2784dacd88d6SYuval Mintz struct qed_sp_vport_update_params params; 2785dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 278617b235c1SYuval Mintz struct qed_sge_tpa_params sge_tpa_params; 2787f29ffdb6SMintz, Yuval u16 tlvs_mask = 0, tlvs_accepted = 0; 2788dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 2789dacd88d6SYuval Mintz u16 length; 2790dacd88d6SYuval Mintz int rc; 2791dacd88d6SYuval Mintz 279241086467SYuval Mintz /* Valiate PF can send such a request */ 279341086467SYuval Mintz if (!vf->vport_instance) { 279441086467SYuval Mintz DP_VERBOSE(p_hwfn, 279541086467SYuval Mintz QED_MSG_IOV, 279641086467SYuval Mintz "No VPORT instance available for VF[%d], failing vport update\n", 279741086467SYuval Mintz vf->abs_vf_id); 279841086467SYuval Mintz status = PFVF_STATUS_FAILURE; 279941086467SYuval Mintz goto out; 280041086467SYuval Mintz } 2801f29ffdb6SMintz, Yuval p_rss_params = vzalloc(sizeof(*p_rss_params)); 2802f29ffdb6SMintz, Yuval if (p_rss_params == NULL) { 2803f29ffdb6SMintz, Yuval status = PFVF_STATUS_FAILURE; 2804f29ffdb6SMintz, Yuval goto out; 2805f29ffdb6SMintz, Yuval } 280641086467SYuval Mintz 2807dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(params)); 2808dacd88d6SYuval Mintz params.opaque_fid = vf->opaque_fid; 2809dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 2810dacd88d6SYuval Mintz params.rss_params = NULL; 2811dacd88d6SYuval Mintz 2812dacd88d6SYuval Mintz /* Search for extended tlvs list and update values 2813dacd88d6SYuval Mintz * from VF in struct qed_sp_vport_update_params. 2814dacd88d6SYuval Mintz */ 2815dacd88d6SYuval Mintz qed_iov_vp_update_act_param(p_hwfn, ¶ms, mbx, &tlvs_mask); 281617b235c1SYuval Mintz qed_iov_vp_update_vlan_param(p_hwfn, ¶ms, vf, mbx, &tlvs_mask); 281717b235c1SYuval Mintz qed_iov_vp_update_tx_switch(p_hwfn, ¶ms, mbx, &tlvs_mask); 2818dacd88d6SYuval Mintz qed_iov_vp_update_mcast_bin_param(p_hwfn, ¶ms, mbx, &tlvs_mask); 2819dacd88d6SYuval Mintz qed_iov_vp_update_accept_flag(p_hwfn, ¶ms, mbx, &tlvs_mask); 282017b235c1SYuval Mintz qed_iov_vp_update_accept_any_vlan(p_hwfn, ¶ms, mbx, &tlvs_mask); 282117b235c1SYuval Mintz qed_iov_vp_update_sge_tpa_param(p_hwfn, vf, ¶ms, 282217b235c1SYuval Mintz &sge_tpa_params, mbx, &tlvs_mask); 2823dacd88d6SYuval Mintz 2824f29ffdb6SMintz, Yuval tlvs_accepted = tlvs_mask; 2825f29ffdb6SMintz, Yuval 2826f29ffdb6SMintz, Yuval /* Some of the extended TLVs need to be validated first; In that case, 2827f29ffdb6SMintz, Yuval * they can update the mask without updating the accepted [so that 2828f29ffdb6SMintz, Yuval * PF could communicate to VF it has rejected request]. 2829dacd88d6SYuval Mintz */ 2830f29ffdb6SMintz, Yuval qed_iov_vp_update_rss_param(p_hwfn, vf, ¶ms, p_rss_params, 2831f29ffdb6SMintz, Yuval mbx, &tlvs_mask, &tlvs_accepted); 2832f29ffdb6SMintz, Yuval 2833f990c82cSMintz, Yuval if (qed_iov_pre_update_vport(p_hwfn, vf->relative_vf_id, 2834f990c82cSMintz, Yuval ¶ms, &tlvs_accepted)) { 2835f990c82cSMintz, Yuval tlvs_accepted = 0; 2836f990c82cSMintz, Yuval status = PFVF_STATUS_NOT_SUPPORTED; 2837f990c82cSMintz, Yuval goto out; 2838f990c82cSMintz, Yuval } 2839f990c82cSMintz, Yuval 2840f29ffdb6SMintz, Yuval if (!tlvs_accepted) { 2841f29ffdb6SMintz, Yuval if (tlvs_mask) 2842f29ffdb6SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_IOV, 2843f29ffdb6SMintz, Yuval "Upper-layer prevents VF vport configuration\n"); 2844f29ffdb6SMintz, Yuval else 2845f29ffdb6SMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_IOV, 2846dacd88d6SYuval Mintz "No feature tlvs found for vport update\n"); 2847dacd88d6SYuval Mintz status = PFVF_STATUS_NOT_SUPPORTED; 2848dacd88d6SYuval Mintz goto out; 2849dacd88d6SYuval Mintz } 2850dacd88d6SYuval Mintz 2851dacd88d6SYuval Mintz rc = qed_sp_vport_update(p_hwfn, ¶ms, QED_SPQ_MODE_EBLOCK, NULL); 2852dacd88d6SYuval Mintz 2853dacd88d6SYuval Mintz if (rc) 2854dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 2855dacd88d6SYuval Mintz 2856dacd88d6SYuval Mintz out: 2857f29ffdb6SMintz, Yuval vfree(p_rss_params); 2858dacd88d6SYuval Mintz length = qed_iov_prep_vp_update_resp_tlvs(p_hwfn, vf, mbx, status, 2859f29ffdb6SMintz, Yuval tlvs_mask, tlvs_accepted); 2860dacd88d6SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, vf, length, status); 2861dacd88d6SYuval Mintz } 2862dacd88d6SYuval Mintz 28638246d0b4SYuval Mintz static int qed_iov_vf_update_vlan_shadow(struct qed_hwfn *p_hwfn, 286408feecd7SYuval Mintz struct qed_vf_info *p_vf, 286508feecd7SYuval Mintz struct qed_filter_ucast *p_params) 286608feecd7SYuval Mintz { 286708feecd7SYuval Mintz int i; 286808feecd7SYuval Mintz 286908feecd7SYuval Mintz /* First remove entries and then add new ones */ 287008feecd7SYuval Mintz if (p_params->opcode == QED_FILTER_REMOVE) { 287108feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) 287208feecd7SYuval Mintz if (p_vf->shadow_config.vlans[i].used && 287308feecd7SYuval Mintz p_vf->shadow_config.vlans[i].vid == 287408feecd7SYuval Mintz p_params->vlan) { 287508feecd7SYuval Mintz p_vf->shadow_config.vlans[i].used = false; 287608feecd7SYuval Mintz break; 287708feecd7SYuval Mintz } 287808feecd7SYuval Mintz if (i == QED_ETH_VF_NUM_VLAN_FILTERS + 1) { 287908feecd7SYuval Mintz DP_VERBOSE(p_hwfn, 288008feecd7SYuval Mintz QED_MSG_IOV, 288108feecd7SYuval Mintz "VF [%d] - Tries to remove a non-existing vlan\n", 288208feecd7SYuval Mintz p_vf->relative_vf_id); 288308feecd7SYuval Mintz return -EINVAL; 288408feecd7SYuval Mintz } 288508feecd7SYuval Mintz } else if (p_params->opcode == QED_FILTER_REPLACE || 288608feecd7SYuval Mintz p_params->opcode == QED_FILTER_FLUSH) { 288708feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) 288808feecd7SYuval Mintz p_vf->shadow_config.vlans[i].used = false; 288908feecd7SYuval Mintz } 289008feecd7SYuval Mintz 289108feecd7SYuval Mintz /* In forced mode, we're willing to remove entries - but we don't add 289208feecd7SYuval Mintz * new ones. 289308feecd7SYuval Mintz */ 28941a635e48SYuval Mintz if (p_vf->bulletin.p_virt->valid_bitmap & BIT(VLAN_ADDR_FORCED)) 289508feecd7SYuval Mintz return 0; 289608feecd7SYuval Mintz 289708feecd7SYuval Mintz if (p_params->opcode == QED_FILTER_ADD || 289808feecd7SYuval Mintz p_params->opcode == QED_FILTER_REPLACE) { 289908feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) { 290008feecd7SYuval Mintz if (p_vf->shadow_config.vlans[i].used) 290108feecd7SYuval Mintz continue; 290208feecd7SYuval Mintz 290308feecd7SYuval Mintz p_vf->shadow_config.vlans[i].used = true; 290408feecd7SYuval Mintz p_vf->shadow_config.vlans[i].vid = p_params->vlan; 290508feecd7SYuval Mintz break; 290608feecd7SYuval Mintz } 290708feecd7SYuval Mintz 290808feecd7SYuval Mintz if (i == QED_ETH_VF_NUM_VLAN_FILTERS + 1) { 290908feecd7SYuval Mintz DP_VERBOSE(p_hwfn, 291008feecd7SYuval Mintz QED_MSG_IOV, 291108feecd7SYuval Mintz "VF [%d] - Tries to configure more than %d vlan filters\n", 291208feecd7SYuval Mintz p_vf->relative_vf_id, 291308feecd7SYuval Mintz QED_ETH_VF_NUM_VLAN_FILTERS + 1); 291408feecd7SYuval Mintz return -EINVAL; 291508feecd7SYuval Mintz } 291608feecd7SYuval Mintz } 291708feecd7SYuval Mintz 291808feecd7SYuval Mintz return 0; 291908feecd7SYuval Mintz } 292008feecd7SYuval Mintz 29218246d0b4SYuval Mintz static int qed_iov_vf_update_mac_shadow(struct qed_hwfn *p_hwfn, 29228246d0b4SYuval Mintz struct qed_vf_info *p_vf, 29238246d0b4SYuval Mintz struct qed_filter_ucast *p_params) 29248246d0b4SYuval Mintz { 29258246d0b4SYuval Mintz int i; 29268246d0b4SYuval Mintz 29278246d0b4SYuval Mintz /* If we're in forced-mode, we don't allow any change */ 29281a635e48SYuval Mintz if (p_vf->bulletin.p_virt->valid_bitmap & BIT(MAC_ADDR_FORCED)) 29298246d0b4SYuval Mintz return 0; 29308246d0b4SYuval Mintz 29318246d0b4SYuval Mintz /* First remove entries and then add new ones */ 29328246d0b4SYuval Mintz if (p_params->opcode == QED_FILTER_REMOVE) { 29338246d0b4SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) { 29348246d0b4SYuval Mintz if (ether_addr_equal(p_vf->shadow_config.macs[i], 29358246d0b4SYuval Mintz p_params->mac)) { 29360ee28e31SShyam Saini eth_zero_addr(p_vf->shadow_config.macs[i]); 29378246d0b4SYuval Mintz break; 29388246d0b4SYuval Mintz } 29398246d0b4SYuval Mintz } 29408246d0b4SYuval Mintz 29418246d0b4SYuval Mintz if (i == QED_ETH_VF_NUM_MAC_FILTERS) { 29428246d0b4SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 29438246d0b4SYuval Mintz "MAC isn't configured\n"); 29448246d0b4SYuval Mintz return -EINVAL; 29458246d0b4SYuval Mintz } 29468246d0b4SYuval Mintz } else if (p_params->opcode == QED_FILTER_REPLACE || 29478246d0b4SYuval Mintz p_params->opcode == QED_FILTER_FLUSH) { 29488246d0b4SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) 29490ee28e31SShyam Saini eth_zero_addr(p_vf->shadow_config.macs[i]); 29508246d0b4SYuval Mintz } 29518246d0b4SYuval Mintz 29528246d0b4SYuval Mintz /* List the new MAC address */ 29538246d0b4SYuval Mintz if (p_params->opcode != QED_FILTER_ADD && 29548246d0b4SYuval Mintz p_params->opcode != QED_FILTER_REPLACE) 29558246d0b4SYuval Mintz return 0; 29568246d0b4SYuval Mintz 29578246d0b4SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) { 29588246d0b4SYuval Mintz if (is_zero_ether_addr(p_vf->shadow_config.macs[i])) { 29598246d0b4SYuval Mintz ether_addr_copy(p_vf->shadow_config.macs[i], 29608246d0b4SYuval Mintz p_params->mac); 29618246d0b4SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 29628246d0b4SYuval Mintz "Added MAC at %d entry in shadow\n", i); 29638246d0b4SYuval Mintz break; 29648246d0b4SYuval Mintz } 29658246d0b4SYuval Mintz } 29668246d0b4SYuval Mintz 29678246d0b4SYuval Mintz if (i == QED_ETH_VF_NUM_MAC_FILTERS) { 29688246d0b4SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "No available place for MAC\n"); 29698246d0b4SYuval Mintz return -EINVAL; 29708246d0b4SYuval Mintz } 29718246d0b4SYuval Mintz 29728246d0b4SYuval Mintz return 0; 29738246d0b4SYuval Mintz } 29748246d0b4SYuval Mintz 29758246d0b4SYuval Mintz static int 29768246d0b4SYuval Mintz qed_iov_vf_update_unicast_shadow(struct qed_hwfn *p_hwfn, 29778246d0b4SYuval Mintz struct qed_vf_info *p_vf, 29788246d0b4SYuval Mintz struct qed_filter_ucast *p_params) 29798246d0b4SYuval Mintz { 29808246d0b4SYuval Mintz int rc = 0; 29818246d0b4SYuval Mintz 29828246d0b4SYuval Mintz if (p_params->type == QED_FILTER_MAC) { 29838246d0b4SYuval Mintz rc = qed_iov_vf_update_mac_shadow(p_hwfn, p_vf, p_params); 29848246d0b4SYuval Mintz if (rc) 29858246d0b4SYuval Mintz return rc; 29868246d0b4SYuval Mintz } 29878246d0b4SYuval Mintz 29888246d0b4SYuval Mintz if (p_params->type == QED_FILTER_VLAN) 29898246d0b4SYuval Mintz rc = qed_iov_vf_update_vlan_shadow(p_hwfn, p_vf, p_params); 29908246d0b4SYuval Mintz 29918246d0b4SYuval Mintz return rc; 29928246d0b4SYuval Mintz } 29938246d0b4SYuval Mintz 2994ba56947aSBaoyou Xie static int qed_iov_chk_ucast(struct qed_hwfn *hwfn, 2995dacd88d6SYuval Mintz int vfid, struct qed_filter_ucast *params) 2996dacd88d6SYuval Mintz { 2997dacd88d6SYuval Mintz struct qed_public_vf_info *vf; 2998dacd88d6SYuval Mintz 2999dacd88d6SYuval Mintz vf = qed_iov_get_public_vf_info(hwfn, vfid, true); 3000dacd88d6SYuval Mintz if (!vf) 3001dacd88d6SYuval Mintz return -EINVAL; 3002dacd88d6SYuval Mintz 3003dacd88d6SYuval Mintz /* No real decision to make; Store the configured MAC */ 3004dacd88d6SYuval Mintz if (params->type == QED_FILTER_MAC || 3005dacd88d6SYuval Mintz params->type == QED_FILTER_MAC_VLAN) 3006dacd88d6SYuval Mintz ether_addr_copy(vf->mac, params->mac); 3007dacd88d6SYuval Mintz 3008dacd88d6SYuval Mintz return 0; 3009dacd88d6SYuval Mintz } 3010dacd88d6SYuval Mintz 3011dacd88d6SYuval Mintz static void qed_iov_vf_mbx_ucast_filter(struct qed_hwfn *p_hwfn, 3012dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 3013dacd88d6SYuval Mintz struct qed_vf_info *vf) 3014dacd88d6SYuval Mintz { 301508feecd7SYuval Mintz struct qed_bulletin_content *p_bulletin = vf->bulletin.p_virt; 3016dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 3017dacd88d6SYuval Mintz struct vfpf_ucast_filter_tlv *req; 3018dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 3019dacd88d6SYuval Mintz struct qed_filter_ucast params; 3020dacd88d6SYuval Mintz int rc; 3021dacd88d6SYuval Mintz 3022dacd88d6SYuval Mintz /* Prepare the unicast filter params */ 3023dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(struct qed_filter_ucast)); 3024dacd88d6SYuval Mintz req = &mbx->req_virt->ucast_filter; 3025dacd88d6SYuval Mintz params.opcode = (enum qed_filter_opcode)req->opcode; 3026dacd88d6SYuval Mintz params.type = (enum qed_filter_ucast_type)req->type; 3027dacd88d6SYuval Mintz 3028dacd88d6SYuval Mintz params.is_rx_filter = 1; 3029dacd88d6SYuval Mintz params.is_tx_filter = 1; 3030dacd88d6SYuval Mintz params.vport_to_remove_from = vf->vport_id; 3031dacd88d6SYuval Mintz params.vport_to_add_to = vf->vport_id; 3032dacd88d6SYuval Mintz memcpy(params.mac, req->mac, ETH_ALEN); 3033dacd88d6SYuval Mintz params.vlan = req->vlan; 3034dacd88d6SYuval Mintz 3035dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, 3036dacd88d6SYuval Mintz QED_MSG_IOV, 3037dacd88d6SYuval Mintz "VF[%d]: opcode 0x%02x type 0x%02x [%s %s] [vport 0x%02x] MAC %02x:%02x:%02x:%02x:%02x:%02x, vlan 0x%04x\n", 3038dacd88d6SYuval Mintz vf->abs_vf_id, params.opcode, params.type, 3039dacd88d6SYuval Mintz params.is_rx_filter ? "RX" : "", 3040dacd88d6SYuval Mintz params.is_tx_filter ? "TX" : "", 3041dacd88d6SYuval Mintz params.vport_to_add_to, 3042dacd88d6SYuval Mintz params.mac[0], params.mac[1], 3043dacd88d6SYuval Mintz params.mac[2], params.mac[3], 3044dacd88d6SYuval Mintz params.mac[4], params.mac[5], params.vlan); 3045dacd88d6SYuval Mintz 3046dacd88d6SYuval Mintz if (!vf->vport_instance) { 3047dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, 3048dacd88d6SYuval Mintz QED_MSG_IOV, 3049dacd88d6SYuval Mintz "No VPORT instance available for VF[%d], failing ucast MAC configuration\n", 3050dacd88d6SYuval Mintz vf->abs_vf_id); 3051dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 3052dacd88d6SYuval Mintz goto out; 3053dacd88d6SYuval Mintz } 3054dacd88d6SYuval Mintz 305508feecd7SYuval Mintz /* Update shadow copy of the VF configuration */ 305608feecd7SYuval Mintz if (qed_iov_vf_update_unicast_shadow(p_hwfn, vf, ¶ms)) { 305708feecd7SYuval Mintz status = PFVF_STATUS_FAILURE; 305808feecd7SYuval Mintz goto out; 305908feecd7SYuval Mintz } 306008feecd7SYuval Mintz 306108feecd7SYuval Mintz /* Determine if the unicast filtering is acceptible by PF */ 30621a635e48SYuval Mintz if ((p_bulletin->valid_bitmap & BIT(VLAN_ADDR_FORCED)) && 306308feecd7SYuval Mintz (params.type == QED_FILTER_VLAN || 306408feecd7SYuval Mintz params.type == QED_FILTER_MAC_VLAN)) { 306508feecd7SYuval Mintz /* Once VLAN is forced or PVID is set, do not allow 306608feecd7SYuval Mintz * to add/replace any further VLANs. 306708feecd7SYuval Mintz */ 306808feecd7SYuval Mintz if (params.opcode == QED_FILTER_ADD || 306908feecd7SYuval Mintz params.opcode == QED_FILTER_REPLACE) 307008feecd7SYuval Mintz status = PFVF_STATUS_FORCED; 307108feecd7SYuval Mintz goto out; 307208feecd7SYuval Mintz } 307308feecd7SYuval Mintz 30741a635e48SYuval Mintz if ((p_bulletin->valid_bitmap & BIT(MAC_ADDR_FORCED)) && 3075eff16960SYuval Mintz (params.type == QED_FILTER_MAC || 3076eff16960SYuval Mintz params.type == QED_FILTER_MAC_VLAN)) { 3077eff16960SYuval Mintz if (!ether_addr_equal(p_bulletin->mac, params.mac) || 3078eff16960SYuval Mintz (params.opcode != QED_FILTER_ADD && 3079eff16960SYuval Mintz params.opcode != QED_FILTER_REPLACE)) 3080eff16960SYuval Mintz status = PFVF_STATUS_FORCED; 3081eff16960SYuval Mintz goto out; 3082eff16960SYuval Mintz } 3083eff16960SYuval Mintz 3084dacd88d6SYuval Mintz rc = qed_iov_chk_ucast(p_hwfn, vf->relative_vf_id, ¶ms); 3085dacd88d6SYuval Mintz if (rc) { 3086dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 3087dacd88d6SYuval Mintz goto out; 3088dacd88d6SYuval Mintz } 3089dacd88d6SYuval Mintz 3090dacd88d6SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, vf->opaque_fid, ¶ms, 3091dacd88d6SYuval Mintz QED_SPQ_MODE_CB, NULL); 3092dacd88d6SYuval Mintz if (rc) 3093dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 3094dacd88d6SYuval Mintz 3095dacd88d6SYuval Mintz out: 3096dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UCAST_FILTER, 3097dacd88d6SYuval Mintz sizeof(struct pfvf_def_resp_tlv), status); 3098dacd88d6SYuval Mintz } 3099dacd88d6SYuval Mintz 31000b55e27dSYuval Mintz static void qed_iov_vf_mbx_int_cleanup(struct qed_hwfn *p_hwfn, 31010b55e27dSYuval Mintz struct qed_ptt *p_ptt, 31020b55e27dSYuval Mintz struct qed_vf_info *vf) 31030b55e27dSYuval Mintz { 31040b55e27dSYuval Mintz int i; 31050b55e27dSYuval Mintz 31060b55e27dSYuval Mintz /* Reset the SBs */ 31070b55e27dSYuval Mintz for (i = 0; i < vf->num_sbs; i++) 31080b55e27dSYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, 31090b55e27dSYuval Mintz vf->igu_sbs[i], 31100b55e27dSYuval Mintz vf->opaque_fid, false); 31110b55e27dSYuval Mintz 31120b55e27dSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_INT_CLEANUP, 31130b55e27dSYuval Mintz sizeof(struct pfvf_def_resp_tlv), 31140b55e27dSYuval Mintz PFVF_STATUS_SUCCESS); 31150b55e27dSYuval Mintz } 31160b55e27dSYuval Mintz 31170b55e27dSYuval Mintz static void qed_iov_vf_mbx_close(struct qed_hwfn *p_hwfn, 31180b55e27dSYuval Mintz struct qed_ptt *p_ptt, struct qed_vf_info *vf) 31190b55e27dSYuval Mintz { 31200b55e27dSYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 31210b55e27dSYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 31220b55e27dSYuval Mintz 31230b55e27dSYuval Mintz /* Disable Interrupts for VF */ 31240b55e27dSYuval Mintz qed_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0); 31250b55e27dSYuval Mintz 31260b55e27dSYuval Mintz /* Reset Permission table */ 31270b55e27dSYuval Mintz qed_iov_config_perm_table(p_hwfn, p_ptt, vf, 0); 31280b55e27dSYuval Mintz 31290b55e27dSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_CLOSE, 31300b55e27dSYuval Mintz length, status); 31310b55e27dSYuval Mintz } 31320b55e27dSYuval Mintz 31330b55e27dSYuval Mintz static void qed_iov_vf_mbx_release(struct qed_hwfn *p_hwfn, 31340b55e27dSYuval Mintz struct qed_ptt *p_ptt, 31350b55e27dSYuval Mintz struct qed_vf_info *p_vf) 31360b55e27dSYuval Mintz { 31370b55e27dSYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 31381fe614d1SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 31391fe614d1SYuval Mintz int rc = 0; 31400b55e27dSYuval Mintz 31410b55e27dSYuval Mintz qed_iov_vf_cleanup(p_hwfn, p_vf); 31420b55e27dSYuval Mintz 31431fe614d1SYuval Mintz if (p_vf->state != VF_STOPPED && p_vf->state != VF_FREE) { 31441fe614d1SYuval Mintz /* Stopping the VF */ 31451fe614d1SYuval Mintz rc = qed_sp_vf_stop(p_hwfn, p_vf->concrete_fid, 31461fe614d1SYuval Mintz p_vf->opaque_fid); 31471fe614d1SYuval Mintz 31481fe614d1SYuval Mintz if (rc) { 31491fe614d1SYuval Mintz DP_ERR(p_hwfn, "qed_sp_vf_stop returned error %d\n", 31501fe614d1SYuval Mintz rc); 31511fe614d1SYuval Mintz status = PFVF_STATUS_FAILURE; 31521fe614d1SYuval Mintz } 31531fe614d1SYuval Mintz 31541fe614d1SYuval Mintz p_vf->state = VF_STOPPED; 31551fe614d1SYuval Mintz } 31561fe614d1SYuval Mintz 31570b55e27dSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, CHANNEL_TLV_RELEASE, 31581fe614d1SYuval Mintz length, status); 31590b55e27dSYuval Mintz } 31600b55e27dSYuval Mintz 31610b55e27dSYuval Mintz static int 31620b55e27dSYuval Mintz qed_iov_vf_flr_poll_dorq(struct qed_hwfn *p_hwfn, 31630b55e27dSYuval Mintz struct qed_vf_info *p_vf, struct qed_ptt *p_ptt) 31640b55e27dSYuval Mintz { 31650b55e27dSYuval Mintz int cnt; 31660b55e27dSYuval Mintz u32 val; 31670b55e27dSYuval Mintz 31680b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_vf->concrete_fid); 31690b55e27dSYuval Mintz 31700b55e27dSYuval Mintz for (cnt = 0; cnt < 50; cnt++) { 31710b55e27dSYuval Mintz val = qed_rd(p_hwfn, p_ptt, DORQ_REG_VF_USAGE_CNT); 31720b55e27dSYuval Mintz if (!val) 31730b55e27dSYuval Mintz break; 31740b55e27dSYuval Mintz msleep(20); 31750b55e27dSYuval Mintz } 31760b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 31770b55e27dSYuval Mintz 31780b55e27dSYuval Mintz if (cnt == 50) { 31790b55e27dSYuval Mintz DP_ERR(p_hwfn, 31800b55e27dSYuval Mintz "VF[%d] - dorq failed to cleanup [usage 0x%08x]\n", 31810b55e27dSYuval Mintz p_vf->abs_vf_id, val); 31820b55e27dSYuval Mintz return -EBUSY; 31830b55e27dSYuval Mintz } 31840b55e27dSYuval Mintz 31850b55e27dSYuval Mintz return 0; 31860b55e27dSYuval Mintz } 31870b55e27dSYuval Mintz 31880b55e27dSYuval Mintz static int 31890b55e27dSYuval Mintz qed_iov_vf_flr_poll_pbf(struct qed_hwfn *p_hwfn, 31900b55e27dSYuval Mintz struct qed_vf_info *p_vf, struct qed_ptt *p_ptt) 31910b55e27dSYuval Mintz { 31920b55e27dSYuval Mintz u32 cons[MAX_NUM_VOQS], distance[MAX_NUM_VOQS]; 31930b55e27dSYuval Mintz int i, cnt; 31940b55e27dSYuval Mintz 31950b55e27dSYuval Mintz /* Read initial consumers & producers */ 31960b55e27dSYuval Mintz for (i = 0; i < MAX_NUM_VOQS; i++) { 31970b55e27dSYuval Mintz u32 prod; 31980b55e27dSYuval Mintz 31990b55e27dSYuval Mintz cons[i] = qed_rd(p_hwfn, p_ptt, 32000b55e27dSYuval Mintz PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0 + 32010b55e27dSYuval Mintz i * 0x40); 32020b55e27dSYuval Mintz prod = qed_rd(p_hwfn, p_ptt, 32030b55e27dSYuval Mintz PBF_REG_NUM_BLOCKS_ALLOCATED_PROD_VOQ0 + 32040b55e27dSYuval Mintz i * 0x40); 32050b55e27dSYuval Mintz distance[i] = prod - cons[i]; 32060b55e27dSYuval Mintz } 32070b55e27dSYuval Mintz 32080b55e27dSYuval Mintz /* Wait for consumers to pass the producers */ 32090b55e27dSYuval Mintz i = 0; 32100b55e27dSYuval Mintz for (cnt = 0; cnt < 50; cnt++) { 32110b55e27dSYuval Mintz for (; i < MAX_NUM_VOQS; i++) { 32120b55e27dSYuval Mintz u32 tmp; 32130b55e27dSYuval Mintz 32140b55e27dSYuval Mintz tmp = qed_rd(p_hwfn, p_ptt, 32150b55e27dSYuval Mintz PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0 + 32160b55e27dSYuval Mintz i * 0x40); 32170b55e27dSYuval Mintz if (distance[i] > tmp - cons[i]) 32180b55e27dSYuval Mintz break; 32190b55e27dSYuval Mintz } 32200b55e27dSYuval Mintz 32210b55e27dSYuval Mintz if (i == MAX_NUM_VOQS) 32220b55e27dSYuval Mintz break; 32230b55e27dSYuval Mintz 32240b55e27dSYuval Mintz msleep(20); 32250b55e27dSYuval Mintz } 32260b55e27dSYuval Mintz 32270b55e27dSYuval Mintz if (cnt == 50) { 32280b55e27dSYuval Mintz DP_ERR(p_hwfn, "VF[%d] - pbf polling failed on VOQ %d\n", 32290b55e27dSYuval Mintz p_vf->abs_vf_id, i); 32300b55e27dSYuval Mintz return -EBUSY; 32310b55e27dSYuval Mintz } 32320b55e27dSYuval Mintz 32330b55e27dSYuval Mintz return 0; 32340b55e27dSYuval Mintz } 32350b55e27dSYuval Mintz 32360b55e27dSYuval Mintz static int qed_iov_vf_flr_poll(struct qed_hwfn *p_hwfn, 32370b55e27dSYuval Mintz struct qed_vf_info *p_vf, struct qed_ptt *p_ptt) 32380b55e27dSYuval Mintz { 32390b55e27dSYuval Mintz int rc; 32400b55e27dSYuval Mintz 32410b55e27dSYuval Mintz rc = qed_iov_vf_flr_poll_dorq(p_hwfn, p_vf, p_ptt); 32420b55e27dSYuval Mintz if (rc) 32430b55e27dSYuval Mintz return rc; 32440b55e27dSYuval Mintz 32450b55e27dSYuval Mintz rc = qed_iov_vf_flr_poll_pbf(p_hwfn, p_vf, p_ptt); 32460b55e27dSYuval Mintz if (rc) 32470b55e27dSYuval Mintz return rc; 32480b55e27dSYuval Mintz 32490b55e27dSYuval Mintz return 0; 32500b55e27dSYuval Mintz } 32510b55e27dSYuval Mintz 32520b55e27dSYuval Mintz static int 32530b55e27dSYuval Mintz qed_iov_execute_vf_flr_cleanup(struct qed_hwfn *p_hwfn, 32540b55e27dSYuval Mintz struct qed_ptt *p_ptt, 32550b55e27dSYuval Mintz u16 rel_vf_id, u32 *ack_vfs) 32560b55e27dSYuval Mintz { 32570b55e27dSYuval Mintz struct qed_vf_info *p_vf; 32580b55e27dSYuval Mintz int rc = 0; 32590b55e27dSYuval Mintz 32600b55e27dSYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, false); 32610b55e27dSYuval Mintz if (!p_vf) 32620b55e27dSYuval Mintz return 0; 32630b55e27dSYuval Mintz 32640b55e27dSYuval Mintz if (p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] & 32650b55e27dSYuval Mintz (1ULL << (rel_vf_id % 64))) { 32660b55e27dSYuval Mintz u16 vfid = p_vf->abs_vf_id; 32670b55e27dSYuval Mintz 32680b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 32690b55e27dSYuval Mintz "VF[%d] - Handling FLR\n", vfid); 32700b55e27dSYuval Mintz 32710b55e27dSYuval Mintz qed_iov_vf_cleanup(p_hwfn, p_vf); 32720b55e27dSYuval Mintz 32730b55e27dSYuval Mintz /* If VF isn't active, no need for anything but SW */ 32740b55e27dSYuval Mintz if (!p_vf->b_init) 32750b55e27dSYuval Mintz goto cleanup; 32760b55e27dSYuval Mintz 32770b55e27dSYuval Mintz rc = qed_iov_vf_flr_poll(p_hwfn, p_vf, p_ptt); 32780b55e27dSYuval Mintz if (rc) 32790b55e27dSYuval Mintz goto cleanup; 32800b55e27dSYuval Mintz 32810b55e27dSYuval Mintz rc = qed_final_cleanup(p_hwfn, p_ptt, vfid, true); 32820b55e27dSYuval Mintz if (rc) { 32830b55e27dSYuval Mintz DP_ERR(p_hwfn, "Failed handle FLR of VF[%d]\n", vfid); 32840b55e27dSYuval Mintz return rc; 32850b55e27dSYuval Mintz } 32860b55e27dSYuval Mintz 32877eff82b0SYuval Mintz /* Workaround to make VF-PF channel ready, as FW 32887eff82b0SYuval Mintz * doesn't do that as a part of FLR. 32897eff82b0SYuval Mintz */ 32907eff82b0SYuval Mintz REG_WR(p_hwfn, 32917eff82b0SYuval Mintz GTT_BAR0_MAP_REG_USDM_RAM + 32927eff82b0SYuval Mintz USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1); 32937eff82b0SYuval Mintz 32940b55e27dSYuval Mintz /* VF_STOPPED has to be set only after final cleanup 32950b55e27dSYuval Mintz * but prior to re-enabling the VF. 32960b55e27dSYuval Mintz */ 32970b55e27dSYuval Mintz p_vf->state = VF_STOPPED; 32980b55e27dSYuval Mintz 32990b55e27dSYuval Mintz rc = qed_iov_enable_vf_access(p_hwfn, p_ptt, p_vf); 33000b55e27dSYuval Mintz if (rc) { 33010b55e27dSYuval Mintz DP_ERR(p_hwfn, "Failed to re-enable VF[%d] acces\n", 33020b55e27dSYuval Mintz vfid); 33030b55e27dSYuval Mintz return rc; 33040b55e27dSYuval Mintz } 33050b55e27dSYuval Mintz cleanup: 33060b55e27dSYuval Mintz /* Mark VF for ack and clean pending state */ 33070b55e27dSYuval Mintz if (p_vf->state == VF_RESET) 33080b55e27dSYuval Mintz p_vf->state = VF_STOPPED; 33091a635e48SYuval Mintz ack_vfs[vfid / 32] |= BIT((vfid % 32)); 33100b55e27dSYuval Mintz p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &= 33110b55e27dSYuval Mintz ~(1ULL << (rel_vf_id % 64)); 3312fd3c615aSMintz, Yuval p_vf->vf_mbx.b_pending_msg = false; 33130b55e27dSYuval Mintz } 33140b55e27dSYuval Mintz 33150b55e27dSYuval Mintz return rc; 33160b55e27dSYuval Mintz } 33170b55e27dSYuval Mintz 3318ba56947aSBaoyou Xie static int 3319ba56947aSBaoyou Xie qed_iov_vf_flr_cleanup(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 33200b55e27dSYuval Mintz { 33210b55e27dSYuval Mintz u32 ack_vfs[VF_MAX_STATIC / 32]; 33220b55e27dSYuval Mintz int rc = 0; 33230b55e27dSYuval Mintz u16 i; 33240b55e27dSYuval Mintz 33250b55e27dSYuval Mintz memset(ack_vfs, 0, sizeof(u32) * (VF_MAX_STATIC / 32)); 33260b55e27dSYuval Mintz 33270b55e27dSYuval Mintz /* Since BRB <-> PRS interface can't be tested as part of the flr 33280b55e27dSYuval Mintz * polling due to HW limitations, simply sleep a bit. And since 33290b55e27dSYuval Mintz * there's no need to wait per-vf, do it before looping. 33300b55e27dSYuval Mintz */ 33310b55e27dSYuval Mintz msleep(100); 33320b55e27dSYuval Mintz 33330b55e27dSYuval Mintz for (i = 0; i < p_hwfn->cdev->p_iov_info->total_vfs; i++) 33340b55e27dSYuval Mintz qed_iov_execute_vf_flr_cleanup(p_hwfn, p_ptt, i, ack_vfs); 33350b55e27dSYuval Mintz 33360b55e27dSYuval Mintz rc = qed_mcp_ack_vf_flr(p_hwfn, p_ptt, ack_vfs); 33370b55e27dSYuval Mintz return rc; 33380b55e27dSYuval Mintz } 33390b55e27dSYuval Mintz 3340cccf6f5cSMintz, Yuval bool qed_iov_mark_vf_flr(struct qed_hwfn *p_hwfn, u32 *p_disabled_vfs) 33410b55e27dSYuval Mintz { 3342cccf6f5cSMintz, Yuval bool found = false; 3343cccf6f5cSMintz, Yuval u16 i; 33440b55e27dSYuval Mintz 33450b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "Marking FLR-ed VFs\n"); 33460b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) 33470b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 33480b55e27dSYuval Mintz "[%08x,...,%08x]: %08x\n", 33490b55e27dSYuval Mintz i * 32, (i + 1) * 32 - 1, p_disabled_vfs[i]); 33500b55e27dSYuval Mintz 33510b55e27dSYuval Mintz if (!p_hwfn->cdev->p_iov_info) { 33520b55e27dSYuval Mintz DP_NOTICE(p_hwfn, "VF flr but no IOV\n"); 3353cccf6f5cSMintz, Yuval return false; 33540b55e27dSYuval Mintz } 33550b55e27dSYuval Mintz 33560b55e27dSYuval Mintz /* Mark VFs */ 33570b55e27dSYuval Mintz for (i = 0; i < p_hwfn->cdev->p_iov_info->total_vfs; i++) { 33580b55e27dSYuval Mintz struct qed_vf_info *p_vf; 33590b55e27dSYuval Mintz u8 vfid; 33600b55e27dSYuval Mintz 33610b55e27dSYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, i, false); 33620b55e27dSYuval Mintz if (!p_vf) 33630b55e27dSYuval Mintz continue; 33640b55e27dSYuval Mintz 33650b55e27dSYuval Mintz vfid = p_vf->abs_vf_id; 33661a635e48SYuval Mintz if (BIT((vfid % 32)) & p_disabled_vfs[vfid / 32]) { 33670b55e27dSYuval Mintz u64 *p_flr = p_hwfn->pf_iov_info->pending_flr; 33680b55e27dSYuval Mintz u16 rel_vf_id = p_vf->relative_vf_id; 33690b55e27dSYuval Mintz 33700b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 33710b55e27dSYuval Mintz "VF[%d] [rel %d] got FLR-ed\n", 33720b55e27dSYuval Mintz vfid, rel_vf_id); 33730b55e27dSYuval Mintz 33740b55e27dSYuval Mintz p_vf->state = VF_RESET; 33750b55e27dSYuval Mintz 33760b55e27dSYuval Mintz /* No need to lock here, since pending_flr should 33770b55e27dSYuval Mintz * only change here and before ACKing MFw. Since 33780b55e27dSYuval Mintz * MFW will not trigger an additional attention for 33790b55e27dSYuval Mintz * VF flr until ACKs, we're safe. 33800b55e27dSYuval Mintz */ 33810b55e27dSYuval Mintz p_flr[rel_vf_id / 64] |= 1ULL << (rel_vf_id % 64); 3382cccf6f5cSMintz, Yuval found = true; 33830b55e27dSYuval Mintz } 33840b55e27dSYuval Mintz } 33850b55e27dSYuval Mintz 33860b55e27dSYuval Mintz return found; 33870b55e27dSYuval Mintz } 33880b55e27dSYuval Mintz 338973390ac9SYuval Mintz static void qed_iov_get_link(struct qed_hwfn *p_hwfn, 339073390ac9SYuval Mintz u16 vfid, 339173390ac9SYuval Mintz struct qed_mcp_link_params *p_params, 339273390ac9SYuval Mintz struct qed_mcp_link_state *p_link, 339373390ac9SYuval Mintz struct qed_mcp_link_capabilities *p_caps) 339473390ac9SYuval Mintz { 339573390ac9SYuval Mintz struct qed_vf_info *p_vf = qed_iov_get_vf_info(p_hwfn, 339673390ac9SYuval Mintz vfid, 339773390ac9SYuval Mintz false); 339873390ac9SYuval Mintz struct qed_bulletin_content *p_bulletin; 339973390ac9SYuval Mintz 340073390ac9SYuval Mintz if (!p_vf) 340173390ac9SYuval Mintz return; 340273390ac9SYuval Mintz 340373390ac9SYuval Mintz p_bulletin = p_vf->bulletin.p_virt; 340473390ac9SYuval Mintz 340573390ac9SYuval Mintz if (p_params) 340673390ac9SYuval Mintz __qed_vf_get_link_params(p_hwfn, p_params, p_bulletin); 340773390ac9SYuval Mintz if (p_link) 340873390ac9SYuval Mintz __qed_vf_get_link_state(p_hwfn, p_link, p_bulletin); 340973390ac9SYuval Mintz if (p_caps) 341073390ac9SYuval Mintz __qed_vf_get_link_caps(p_hwfn, p_caps, p_bulletin); 341173390ac9SYuval Mintz } 341273390ac9SYuval Mintz 341337bff2b9SYuval Mintz static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn, 341437bff2b9SYuval Mintz struct qed_ptt *p_ptt, int vfid) 341537bff2b9SYuval Mintz { 341637bff2b9SYuval Mintz struct qed_iov_vf_mbx *mbx; 341737bff2b9SYuval Mintz struct qed_vf_info *p_vf; 341837bff2b9SYuval Mintz 341937bff2b9SYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 342037bff2b9SYuval Mintz if (!p_vf) 342137bff2b9SYuval Mintz return; 342237bff2b9SYuval Mintz 342337bff2b9SYuval Mintz mbx = &p_vf->vf_mbx; 342437bff2b9SYuval Mintz 342537bff2b9SYuval Mintz /* qed_iov_process_mbx_request */ 3426fd3c615aSMintz, Yuval if (!mbx->b_pending_msg) { 3427fd3c615aSMintz, Yuval DP_NOTICE(p_hwfn, 3428fd3c615aSMintz, Yuval "VF[%02x]: Trying to process mailbox message when none is pending\n", 3429fd3c615aSMintz, Yuval p_vf->abs_vf_id); 3430fd3c615aSMintz, Yuval return; 3431fd3c615aSMintz, Yuval } 3432fd3c615aSMintz, Yuval mbx->b_pending_msg = false; 343337bff2b9SYuval Mintz 343437bff2b9SYuval Mintz mbx->first_tlv = mbx->req_virt->first_tlv; 343537bff2b9SYuval Mintz 3436fd3c615aSMintz, Yuval DP_VERBOSE(p_hwfn, QED_MSG_IOV, 3437fd3c615aSMintz, Yuval "VF[%02x]: Processing mailbox message [type %04x]\n", 3438fd3c615aSMintz, Yuval p_vf->abs_vf_id, mbx->first_tlv.tl.type); 3439fd3c615aSMintz, Yuval 344037bff2b9SYuval Mintz /* check if tlv type is known */ 34417eff82b0SYuval Mintz if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) && 34427eff82b0SYuval Mintz !p_vf->b_malicious) { 34431408cc1fSYuval Mintz switch (mbx->first_tlv.tl.type) { 34441408cc1fSYuval Mintz case CHANNEL_TLV_ACQUIRE: 34451408cc1fSYuval Mintz qed_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf); 34461408cc1fSYuval Mintz break; 3447dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_START: 3448dacd88d6SYuval Mintz qed_iov_vf_mbx_start_vport(p_hwfn, p_ptt, p_vf); 3449dacd88d6SYuval Mintz break; 3450dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_TEARDOWN: 3451dacd88d6SYuval Mintz qed_iov_vf_mbx_stop_vport(p_hwfn, p_ptt, p_vf); 3452dacd88d6SYuval Mintz break; 3453dacd88d6SYuval Mintz case CHANNEL_TLV_START_RXQ: 3454dacd88d6SYuval Mintz qed_iov_vf_mbx_start_rxq(p_hwfn, p_ptt, p_vf); 3455dacd88d6SYuval Mintz break; 3456dacd88d6SYuval Mintz case CHANNEL_TLV_START_TXQ: 3457dacd88d6SYuval Mintz qed_iov_vf_mbx_start_txq(p_hwfn, p_ptt, p_vf); 3458dacd88d6SYuval Mintz break; 3459dacd88d6SYuval Mintz case CHANNEL_TLV_STOP_RXQS: 3460dacd88d6SYuval Mintz qed_iov_vf_mbx_stop_rxqs(p_hwfn, p_ptt, p_vf); 3461dacd88d6SYuval Mintz break; 3462dacd88d6SYuval Mintz case CHANNEL_TLV_STOP_TXQS: 3463dacd88d6SYuval Mintz qed_iov_vf_mbx_stop_txqs(p_hwfn, p_ptt, p_vf); 3464dacd88d6SYuval Mintz break; 346517b235c1SYuval Mintz case CHANNEL_TLV_UPDATE_RXQ: 346617b235c1SYuval Mintz qed_iov_vf_mbx_update_rxqs(p_hwfn, p_ptt, p_vf); 346717b235c1SYuval Mintz break; 3468dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE: 3469dacd88d6SYuval Mintz qed_iov_vf_mbx_vport_update(p_hwfn, p_ptt, p_vf); 3470dacd88d6SYuval Mintz break; 3471dacd88d6SYuval Mintz case CHANNEL_TLV_UCAST_FILTER: 3472dacd88d6SYuval Mintz qed_iov_vf_mbx_ucast_filter(p_hwfn, p_ptt, p_vf); 3473dacd88d6SYuval Mintz break; 34740b55e27dSYuval Mintz case CHANNEL_TLV_CLOSE: 34750b55e27dSYuval Mintz qed_iov_vf_mbx_close(p_hwfn, p_ptt, p_vf); 34760b55e27dSYuval Mintz break; 34770b55e27dSYuval Mintz case CHANNEL_TLV_INT_CLEANUP: 34780b55e27dSYuval Mintz qed_iov_vf_mbx_int_cleanup(p_hwfn, p_ptt, p_vf); 34790b55e27dSYuval Mintz break; 34800b55e27dSYuval Mintz case CHANNEL_TLV_RELEASE: 34810b55e27dSYuval Mintz qed_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf); 34820b55e27dSYuval Mintz break; 3483eaf3c0c6SChopra, Manish case CHANNEL_TLV_UPDATE_TUNN_PARAM: 3484eaf3c0c6SChopra, Manish qed_iov_vf_mbx_update_tunn_param(p_hwfn, p_ptt, p_vf); 3485eaf3c0c6SChopra, Manish break; 34861408cc1fSYuval Mintz } 34877eff82b0SYuval Mintz } else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) { 34887eff82b0SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 34897eff82b0SYuval Mintz "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n", 34907eff82b0SYuval Mintz p_vf->abs_vf_id, mbx->first_tlv.tl.type); 34917eff82b0SYuval Mintz 34927eff82b0SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, 34937eff82b0SYuval Mintz mbx->first_tlv.tl.type, 34947eff82b0SYuval Mintz sizeof(struct pfvf_def_resp_tlv), 34957eff82b0SYuval Mintz PFVF_STATUS_MALICIOUS); 349637bff2b9SYuval Mintz } else { 349737bff2b9SYuval Mintz /* unknown TLV - this may belong to a VF driver from the future 349837bff2b9SYuval Mintz * - a version written after this PF driver was written, which 349937bff2b9SYuval Mintz * supports features unknown as of yet. Too bad since we don't 350037bff2b9SYuval Mintz * support them. Or this may be because someone wrote a crappy 350137bff2b9SYuval Mintz * VF driver and is sending garbage over the channel. 350237bff2b9SYuval Mintz */ 350354fdd80fSYuval Mintz DP_NOTICE(p_hwfn, 350454fdd80fSYuval Mintz "VF[%02x]: unknown TLV. type %04x length %04x padding %08x reply address %llu\n", 350554fdd80fSYuval Mintz p_vf->abs_vf_id, 350654fdd80fSYuval Mintz mbx->first_tlv.tl.type, 350754fdd80fSYuval Mintz mbx->first_tlv.tl.length, 350854fdd80fSYuval Mintz mbx->first_tlv.padding, mbx->first_tlv.reply_address); 350937bff2b9SYuval Mintz 351054fdd80fSYuval Mintz /* Try replying in case reply address matches the acquisition's 351154fdd80fSYuval Mintz * posted address. 351254fdd80fSYuval Mintz */ 351354fdd80fSYuval Mintz if (p_vf->acquire.first_tlv.reply_address && 351454fdd80fSYuval Mintz (mbx->first_tlv.reply_address == 351554fdd80fSYuval Mintz p_vf->acquire.first_tlv.reply_address)) { 351654fdd80fSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, 351754fdd80fSYuval Mintz mbx->first_tlv.tl.type, 351854fdd80fSYuval Mintz sizeof(struct pfvf_def_resp_tlv), 351954fdd80fSYuval Mintz PFVF_STATUS_NOT_SUPPORTED); 352054fdd80fSYuval Mintz } else { 352137bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, 352237bff2b9SYuval Mintz QED_MSG_IOV, 352354fdd80fSYuval Mintz "VF[%02x]: Can't respond to TLV - no valid reply address\n", 352454fdd80fSYuval Mintz p_vf->abs_vf_id); 352537bff2b9SYuval Mintz } 352637bff2b9SYuval Mintz } 352737bff2b9SYuval Mintz } 352837bff2b9SYuval Mintz 3529fd3c615aSMintz, Yuval void qed_iov_pf_get_pending_events(struct qed_hwfn *p_hwfn, u64 *events) 353037bff2b9SYuval Mintz { 3531fd3c615aSMintz, Yuval int i; 353237bff2b9SYuval Mintz 3533fd3c615aSMintz, Yuval memset(events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH); 3534fd3c615aSMintz, Yuval 3535fd3c615aSMintz, Yuval qed_for_each_vf(p_hwfn, i) { 3536fd3c615aSMintz, Yuval struct qed_vf_info *p_vf; 3537fd3c615aSMintz, Yuval 3538fd3c615aSMintz, Yuval p_vf = &p_hwfn->pf_iov_info->vfs_array[i]; 3539fd3c615aSMintz, Yuval if (p_vf->vf_mbx.b_pending_msg) 3540fd3c615aSMintz, Yuval events[i / 64] |= 1ULL << (i % 64); 354137bff2b9SYuval Mintz } 354237bff2b9SYuval Mintz } 354337bff2b9SYuval Mintz 35447eff82b0SYuval Mintz static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn, 35457eff82b0SYuval Mintz u16 abs_vfid) 35467eff82b0SYuval Mintz { 35477eff82b0SYuval Mintz u8 min = (u8) p_hwfn->cdev->p_iov_info->first_vf_in_pf; 35487eff82b0SYuval Mintz 35497eff82b0SYuval Mintz if (!_qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) { 35507eff82b0SYuval Mintz DP_VERBOSE(p_hwfn, 35517eff82b0SYuval Mintz QED_MSG_IOV, 35527eff82b0SYuval Mintz "Got indication for VF [abs 0x%08x] that cannot be handled by PF\n", 35537eff82b0SYuval Mintz abs_vfid); 35547eff82b0SYuval Mintz return NULL; 35557eff82b0SYuval Mintz } 35567eff82b0SYuval Mintz 35577eff82b0SYuval Mintz return &p_hwfn->pf_iov_info->vfs_array[(u8) abs_vfid - min]; 35587eff82b0SYuval Mintz } 35597eff82b0SYuval Mintz 356037bff2b9SYuval Mintz static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn, 356137bff2b9SYuval Mintz u16 abs_vfid, struct regpair *vf_msg) 356237bff2b9SYuval Mintz { 35637eff82b0SYuval Mintz struct qed_vf_info *p_vf = qed_sriov_get_vf_from_absid(p_hwfn, 356437bff2b9SYuval Mintz abs_vfid); 35657eff82b0SYuval Mintz 35667eff82b0SYuval Mintz if (!p_vf) 356737bff2b9SYuval Mintz return 0; 356837bff2b9SYuval Mintz 356937bff2b9SYuval Mintz /* List the physical address of the request so that handler 357037bff2b9SYuval Mintz * could later on copy the message from it. 357137bff2b9SYuval Mintz */ 357237bff2b9SYuval Mintz p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) | vf_msg->lo; 357337bff2b9SYuval Mintz 357437bff2b9SYuval Mintz /* Mark the event and schedule the workqueue */ 3575fd3c615aSMintz, Yuval p_vf->vf_mbx.b_pending_msg = true; 357637bff2b9SYuval Mintz qed_schedule_iov(p_hwfn, QED_IOV_WQ_MSG_FLAG); 357737bff2b9SYuval Mintz 357837bff2b9SYuval Mintz return 0; 357937bff2b9SYuval Mintz } 358037bff2b9SYuval Mintz 35817eff82b0SYuval Mintz static void qed_sriov_vfpf_malicious(struct qed_hwfn *p_hwfn, 35827eff82b0SYuval Mintz struct malicious_vf_eqe_data *p_data) 35837eff82b0SYuval Mintz { 35847eff82b0SYuval Mintz struct qed_vf_info *p_vf; 35857eff82b0SYuval Mintz 35867eff82b0SYuval Mintz p_vf = qed_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id); 35877eff82b0SYuval Mintz 35887eff82b0SYuval Mintz if (!p_vf) 35897eff82b0SYuval Mintz return; 35907eff82b0SYuval Mintz 3591e99a21cbSMintz, Yuval if (!p_vf->b_malicious) { 3592e99a21cbSMintz, Yuval DP_NOTICE(p_hwfn, 35937eff82b0SYuval Mintz "VF [%d] - Malicious behavior [%02x]\n", 35947eff82b0SYuval Mintz p_vf->abs_vf_id, p_data->err_id); 35957eff82b0SYuval Mintz 35967eff82b0SYuval Mintz p_vf->b_malicious = true; 3597e99a21cbSMintz, Yuval } else { 3598e99a21cbSMintz, Yuval DP_INFO(p_hwfn, 3599e99a21cbSMintz, Yuval "VF [%d] - Malicious behavior [%02x]\n", 3600e99a21cbSMintz, Yuval p_vf->abs_vf_id, p_data->err_id); 3601e99a21cbSMintz, Yuval } 36027eff82b0SYuval Mintz } 36037eff82b0SYuval Mintz 360437bff2b9SYuval Mintz int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, 360537bff2b9SYuval Mintz u8 opcode, __le16 echo, union event_ring_data *data) 360637bff2b9SYuval Mintz { 360737bff2b9SYuval Mintz switch (opcode) { 360837bff2b9SYuval Mintz case COMMON_EVENT_VF_PF_CHANNEL: 360937bff2b9SYuval Mintz return qed_sriov_vfpf_msg(p_hwfn, le16_to_cpu(echo), 361037bff2b9SYuval Mintz &data->vf_pf_channel.msg_addr); 36117eff82b0SYuval Mintz case COMMON_EVENT_MALICIOUS_VF: 36127eff82b0SYuval Mintz qed_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf); 36137eff82b0SYuval Mintz return 0; 361437bff2b9SYuval Mintz default: 361537bff2b9SYuval Mintz DP_INFO(p_hwfn->cdev, "Unknown sriov eqe event 0x%02x\n", 361637bff2b9SYuval Mintz opcode); 361737bff2b9SYuval Mintz return -EINVAL; 361837bff2b9SYuval Mintz } 361937bff2b9SYuval Mintz } 362037bff2b9SYuval Mintz 362132a47e72SYuval Mintz u16 qed_iov_get_next_active_vf(struct qed_hwfn *p_hwfn, u16 rel_vf_id) 362232a47e72SYuval Mintz { 362332a47e72SYuval Mintz struct qed_hw_sriov_info *p_iov = p_hwfn->cdev->p_iov_info; 362432a47e72SYuval Mintz u16 i; 362532a47e72SYuval Mintz 362632a47e72SYuval Mintz if (!p_iov) 362732a47e72SYuval Mintz goto out; 362832a47e72SYuval Mintz 362932a47e72SYuval Mintz for (i = rel_vf_id; i < p_iov->total_vfs; i++) 36307eff82b0SYuval Mintz if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false)) 363132a47e72SYuval Mintz return i; 363232a47e72SYuval Mintz 363332a47e72SYuval Mintz out: 363432a47e72SYuval Mintz return MAX_NUM_VFS; 363532a47e72SYuval Mintz } 363637bff2b9SYuval Mintz 363737bff2b9SYuval Mintz static int qed_iov_copy_vf_msg(struct qed_hwfn *p_hwfn, struct qed_ptt *ptt, 363837bff2b9SYuval Mintz int vfid) 363937bff2b9SYuval Mintz { 364037bff2b9SYuval Mintz struct qed_dmae_params params; 364137bff2b9SYuval Mintz struct qed_vf_info *vf_info; 364237bff2b9SYuval Mintz 364337bff2b9SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 364437bff2b9SYuval Mintz if (!vf_info) 364537bff2b9SYuval Mintz return -EINVAL; 364637bff2b9SYuval Mintz 364737bff2b9SYuval Mintz memset(¶ms, 0, sizeof(struct qed_dmae_params)); 364837bff2b9SYuval Mintz params.flags = QED_DMAE_FLAG_VF_SRC | QED_DMAE_FLAG_COMPLETION_DST; 364937bff2b9SYuval Mintz params.src_vfid = vf_info->abs_vf_id; 365037bff2b9SYuval Mintz 365137bff2b9SYuval Mintz if (qed_dmae_host2host(p_hwfn, ptt, 365237bff2b9SYuval Mintz vf_info->vf_mbx.pending_req, 365337bff2b9SYuval Mintz vf_info->vf_mbx.req_phys, 365437bff2b9SYuval Mintz sizeof(union vfpf_tlvs) / 4, ¶ms)) { 365537bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 365637bff2b9SYuval Mintz "Failed to copy message from VF 0x%02x\n", vfid); 365737bff2b9SYuval Mintz 365837bff2b9SYuval Mintz return -EIO; 365937bff2b9SYuval Mintz } 366037bff2b9SYuval Mintz 366137bff2b9SYuval Mintz return 0; 366237bff2b9SYuval Mintz } 366337bff2b9SYuval Mintz 3664eff16960SYuval Mintz static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn, 3665eff16960SYuval Mintz u8 *mac, int vfid) 3666eff16960SYuval Mintz { 3667eff16960SYuval Mintz struct qed_vf_info *vf_info; 3668eff16960SYuval Mintz u64 feature; 3669eff16960SYuval Mintz 3670eff16960SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true); 3671eff16960SYuval Mintz if (!vf_info) { 3672eff16960SYuval Mintz DP_NOTICE(p_hwfn->cdev, 3673eff16960SYuval Mintz "Can not set forced MAC, invalid vfid [%d]\n", vfid); 3674eff16960SYuval Mintz return; 3675eff16960SYuval Mintz } 3676eff16960SYuval Mintz 36777eff82b0SYuval Mintz if (vf_info->b_malicious) { 36787eff82b0SYuval Mintz DP_NOTICE(p_hwfn->cdev, 36797eff82b0SYuval Mintz "Can't set forced MAC to malicious VF [%d]\n", vfid); 36807eff82b0SYuval Mintz return; 36817eff82b0SYuval Mintz } 36827eff82b0SYuval Mintz 3683eff16960SYuval Mintz feature = 1 << MAC_ADDR_FORCED; 3684eff16960SYuval Mintz memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN); 3685eff16960SYuval Mintz 3686eff16960SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap |= feature; 3687eff16960SYuval Mintz /* Forced MAC will disable MAC_ADDR */ 36881a635e48SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap &= ~BIT(VFPF_BULLETIN_MAC_ADDR); 3689eff16960SYuval Mintz 3690eff16960SYuval Mintz qed_iov_configure_vport_forced(p_hwfn, vf_info, feature); 3691eff16960SYuval Mintz } 3692eff16960SYuval Mintz 3693ba56947aSBaoyou Xie static void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn, 369408feecd7SYuval Mintz u16 pvid, int vfid) 369508feecd7SYuval Mintz { 369608feecd7SYuval Mintz struct qed_vf_info *vf_info; 369708feecd7SYuval Mintz u64 feature; 369808feecd7SYuval Mintz 369908feecd7SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 370008feecd7SYuval Mintz if (!vf_info) { 370108feecd7SYuval Mintz DP_NOTICE(p_hwfn->cdev, 370208feecd7SYuval Mintz "Can not set forced MAC, invalid vfid [%d]\n", vfid); 370308feecd7SYuval Mintz return; 370408feecd7SYuval Mintz } 370508feecd7SYuval Mintz 37067eff82b0SYuval Mintz if (vf_info->b_malicious) { 37077eff82b0SYuval Mintz DP_NOTICE(p_hwfn->cdev, 37087eff82b0SYuval Mintz "Can't set forced vlan to malicious VF [%d]\n", vfid); 37097eff82b0SYuval Mintz return; 37107eff82b0SYuval Mintz } 37117eff82b0SYuval Mintz 371208feecd7SYuval Mintz feature = 1 << VLAN_ADDR_FORCED; 371308feecd7SYuval Mintz vf_info->bulletin.p_virt->pvid = pvid; 371408feecd7SYuval Mintz if (pvid) 371508feecd7SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap |= feature; 371608feecd7SYuval Mintz else 371708feecd7SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap &= ~feature; 371808feecd7SYuval Mintz 371908feecd7SYuval Mintz qed_iov_configure_vport_forced(p_hwfn, vf_info, feature); 372008feecd7SYuval Mintz } 372108feecd7SYuval Mintz 372297379f15SChopra, Manish void qed_iov_bulletin_set_udp_ports(struct qed_hwfn *p_hwfn, 372397379f15SChopra, Manish int vfid, u16 vxlan_port, u16 geneve_port) 372497379f15SChopra, Manish { 372597379f15SChopra, Manish struct qed_vf_info *vf_info; 372697379f15SChopra, Manish 372797379f15SChopra, Manish vf_info = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true); 372897379f15SChopra, Manish if (!vf_info) { 372997379f15SChopra, Manish DP_NOTICE(p_hwfn->cdev, 373097379f15SChopra, Manish "Can not set udp ports, invalid vfid [%d]\n", vfid); 373197379f15SChopra, Manish return; 373297379f15SChopra, Manish } 373397379f15SChopra, Manish 373497379f15SChopra, Manish if (vf_info->b_malicious) { 373597379f15SChopra, Manish DP_VERBOSE(p_hwfn, QED_MSG_IOV, 373697379f15SChopra, Manish "Can not set udp ports to malicious VF [%d]\n", 373797379f15SChopra, Manish vfid); 373897379f15SChopra, Manish return; 373997379f15SChopra, Manish } 374097379f15SChopra, Manish 374197379f15SChopra, Manish vf_info->bulletin.p_virt->vxlan_udp_port = vxlan_port; 374297379f15SChopra, Manish vf_info->bulletin.p_virt->geneve_udp_port = geneve_port; 374397379f15SChopra, Manish } 374497379f15SChopra, Manish 37456ddc7608SYuval Mintz static bool qed_iov_vf_has_vport_instance(struct qed_hwfn *p_hwfn, int vfid) 37466ddc7608SYuval Mintz { 37476ddc7608SYuval Mintz struct qed_vf_info *p_vf_info; 37486ddc7608SYuval Mintz 37496ddc7608SYuval Mintz p_vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 37506ddc7608SYuval Mintz if (!p_vf_info) 37516ddc7608SYuval Mintz return false; 37526ddc7608SYuval Mintz 37536ddc7608SYuval Mintz return !!p_vf_info->vport_instance; 37546ddc7608SYuval Mintz } 37556ddc7608SYuval Mintz 3756ba56947aSBaoyou Xie static bool qed_iov_is_vf_stopped(struct qed_hwfn *p_hwfn, int vfid) 37570b55e27dSYuval Mintz { 37580b55e27dSYuval Mintz struct qed_vf_info *p_vf_info; 37590b55e27dSYuval Mintz 37600b55e27dSYuval Mintz p_vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 37610b55e27dSYuval Mintz if (!p_vf_info) 37620b55e27dSYuval Mintz return true; 37630b55e27dSYuval Mintz 37640b55e27dSYuval Mintz return p_vf_info->state == VF_STOPPED; 37650b55e27dSYuval Mintz } 37660b55e27dSYuval Mintz 376773390ac9SYuval Mintz static bool qed_iov_spoofchk_get(struct qed_hwfn *p_hwfn, int vfid) 376873390ac9SYuval Mintz { 376973390ac9SYuval Mintz struct qed_vf_info *vf_info; 377073390ac9SYuval Mintz 377173390ac9SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 377273390ac9SYuval Mintz if (!vf_info) 377373390ac9SYuval Mintz return false; 377473390ac9SYuval Mintz 377573390ac9SYuval Mintz return vf_info->spoof_chk; 377673390ac9SYuval Mintz } 377773390ac9SYuval Mintz 3778ba56947aSBaoyou Xie static int qed_iov_spoofchk_set(struct qed_hwfn *p_hwfn, int vfid, bool val) 37796ddc7608SYuval Mintz { 37806ddc7608SYuval Mintz struct qed_vf_info *vf; 37816ddc7608SYuval Mintz int rc = -EINVAL; 37826ddc7608SYuval Mintz 37836ddc7608SYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, vfid)) { 37846ddc7608SYuval Mintz DP_NOTICE(p_hwfn, 37856ddc7608SYuval Mintz "SR-IOV sanity check failed, can't set spoofchk\n"); 37866ddc7608SYuval Mintz goto out; 37876ddc7608SYuval Mintz } 37886ddc7608SYuval Mintz 37896ddc7608SYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 37906ddc7608SYuval Mintz if (!vf) 37916ddc7608SYuval Mintz goto out; 37926ddc7608SYuval Mintz 37936ddc7608SYuval Mintz if (!qed_iov_vf_has_vport_instance(p_hwfn, vfid)) { 37946ddc7608SYuval Mintz /* After VF VPORT start PF will configure spoof check */ 37956ddc7608SYuval Mintz vf->req_spoofchk_val = val; 37966ddc7608SYuval Mintz rc = 0; 37976ddc7608SYuval Mintz goto out; 37986ddc7608SYuval Mintz } 37996ddc7608SYuval Mintz 38006ddc7608SYuval Mintz rc = __qed_iov_spoofchk_set(p_hwfn, vf, val); 38016ddc7608SYuval Mintz 38026ddc7608SYuval Mintz out: 38036ddc7608SYuval Mintz return rc; 38046ddc7608SYuval Mintz } 38056ddc7608SYuval Mintz 3806eff16960SYuval Mintz static u8 *qed_iov_bulletin_get_forced_mac(struct qed_hwfn *p_hwfn, 3807eff16960SYuval Mintz u16 rel_vf_id) 3808eff16960SYuval Mintz { 3809eff16960SYuval Mintz struct qed_vf_info *p_vf; 3810eff16960SYuval Mintz 3811eff16960SYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true); 3812eff16960SYuval Mintz if (!p_vf || !p_vf->bulletin.p_virt) 3813eff16960SYuval Mintz return NULL; 3814eff16960SYuval Mintz 38151a635e48SYuval Mintz if (!(p_vf->bulletin.p_virt->valid_bitmap & BIT(MAC_ADDR_FORCED))) 3816eff16960SYuval Mintz return NULL; 3817eff16960SYuval Mintz 3818eff16960SYuval Mintz return p_vf->bulletin.p_virt->mac; 3819eff16960SYuval Mintz } 3820eff16960SYuval Mintz 3821ba56947aSBaoyou Xie static u16 3822ba56947aSBaoyou Xie qed_iov_bulletin_get_forced_vlan(struct qed_hwfn *p_hwfn, u16 rel_vf_id) 382308feecd7SYuval Mintz { 382408feecd7SYuval Mintz struct qed_vf_info *p_vf; 382508feecd7SYuval Mintz 382608feecd7SYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true); 382708feecd7SYuval Mintz if (!p_vf || !p_vf->bulletin.p_virt) 382808feecd7SYuval Mintz return 0; 382908feecd7SYuval Mintz 38301a635e48SYuval Mintz if (!(p_vf->bulletin.p_virt->valid_bitmap & BIT(VLAN_ADDR_FORCED))) 383108feecd7SYuval Mintz return 0; 383208feecd7SYuval Mintz 383308feecd7SYuval Mintz return p_vf->bulletin.p_virt->pvid; 383408feecd7SYuval Mintz } 383508feecd7SYuval Mintz 3836733def6aSYuval Mintz static int qed_iov_configure_tx_rate(struct qed_hwfn *p_hwfn, 3837733def6aSYuval Mintz struct qed_ptt *p_ptt, int vfid, int val) 3838733def6aSYuval Mintz { 3839733def6aSYuval Mintz struct qed_vf_info *vf; 3840733def6aSYuval Mintz u8 abs_vp_id = 0; 3841733def6aSYuval Mintz int rc; 3842733def6aSYuval Mintz 3843733def6aSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true); 3844733def6aSYuval Mintz if (!vf) 3845733def6aSYuval Mintz return -EINVAL; 3846733def6aSYuval Mintz 3847733def6aSYuval Mintz rc = qed_fw_vport(p_hwfn, vf->vport_id, &abs_vp_id); 3848733def6aSYuval Mintz if (rc) 3849733def6aSYuval Mintz return rc; 3850733def6aSYuval Mintz 3851733def6aSYuval Mintz return qed_init_vport_rl(p_hwfn, p_ptt, abs_vp_id, (u32)val); 3852733def6aSYuval Mintz } 3853733def6aSYuval Mintz 3854ba56947aSBaoyou Xie static int 3855ba56947aSBaoyou Xie qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate) 3856733def6aSYuval Mintz { 3857733def6aSYuval Mintz struct qed_vf_info *vf; 3858733def6aSYuval Mintz u8 vport_id; 3859733def6aSYuval Mintz int i; 3860733def6aSYuval Mintz 3861733def6aSYuval Mintz for_each_hwfn(cdev, i) { 3862733def6aSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 3863733def6aSYuval Mintz 3864733def6aSYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, vfid)) { 3865733def6aSYuval Mintz DP_NOTICE(p_hwfn, 3866733def6aSYuval Mintz "SR-IOV sanity check failed, can't set min rate\n"); 3867733def6aSYuval Mintz return -EINVAL; 3868733def6aSYuval Mintz } 3869733def6aSYuval Mintz } 3870733def6aSYuval Mintz 3871733def6aSYuval Mintz vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true); 3872733def6aSYuval Mintz vport_id = vf->vport_id; 3873733def6aSYuval Mintz 3874733def6aSYuval Mintz return qed_configure_vport_wfq(cdev, vport_id, rate); 3875733def6aSYuval Mintz } 3876733def6aSYuval Mintz 387773390ac9SYuval Mintz static int qed_iov_get_vf_min_rate(struct qed_hwfn *p_hwfn, int vfid) 387873390ac9SYuval Mintz { 387973390ac9SYuval Mintz struct qed_wfq_data *vf_vp_wfq; 388073390ac9SYuval Mintz struct qed_vf_info *vf_info; 388173390ac9SYuval Mintz 388273390ac9SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 388373390ac9SYuval Mintz if (!vf_info) 388473390ac9SYuval Mintz return 0; 388573390ac9SYuval Mintz 388673390ac9SYuval Mintz vf_vp_wfq = &p_hwfn->qm_info.wfq_data[vf_info->vport_id]; 388773390ac9SYuval Mintz 388873390ac9SYuval Mintz if (vf_vp_wfq->configured) 388973390ac9SYuval Mintz return vf_vp_wfq->min_speed; 389073390ac9SYuval Mintz else 389173390ac9SYuval Mintz return 0; 389273390ac9SYuval Mintz } 389373390ac9SYuval Mintz 389437bff2b9SYuval Mintz /** 389537bff2b9SYuval Mintz * qed_schedule_iov - schedules IOV task for VF and PF 389637bff2b9SYuval Mintz * @hwfn: hardware function pointer 389737bff2b9SYuval Mintz * @flag: IOV flag for VF/PF 389837bff2b9SYuval Mintz */ 389937bff2b9SYuval Mintz void qed_schedule_iov(struct qed_hwfn *hwfn, enum qed_iov_wq_flag flag) 390037bff2b9SYuval Mintz { 390137bff2b9SYuval Mintz smp_mb__before_atomic(); 390237bff2b9SYuval Mintz set_bit(flag, &hwfn->iov_task_flags); 390337bff2b9SYuval Mintz smp_mb__after_atomic(); 390437bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, "Scheduling iov task [Flag: %d]\n", flag); 390537bff2b9SYuval Mintz queue_delayed_work(hwfn->iov_wq, &hwfn->iov_task, 0); 390637bff2b9SYuval Mintz } 390737bff2b9SYuval Mintz 39081408cc1fSYuval Mintz void qed_vf_start_iov_wq(struct qed_dev *cdev) 39091408cc1fSYuval Mintz { 39101408cc1fSYuval Mintz int i; 39111408cc1fSYuval Mintz 39121408cc1fSYuval Mintz for_each_hwfn(cdev, i) 39131408cc1fSYuval Mintz queue_delayed_work(cdev->hwfns[i].iov_wq, 39141408cc1fSYuval Mintz &cdev->hwfns[i].iov_task, 0); 39151408cc1fSYuval Mintz } 39161408cc1fSYuval Mintz 39170b55e27dSYuval Mintz int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) 39180b55e27dSYuval Mintz { 39190b55e27dSYuval Mintz int i, j; 39200b55e27dSYuval Mintz 39210b55e27dSYuval Mintz for_each_hwfn(cdev, i) 39220b55e27dSYuval Mintz if (cdev->hwfns[i].iov_wq) 39230b55e27dSYuval Mintz flush_workqueue(cdev->hwfns[i].iov_wq); 39240b55e27dSYuval Mintz 39250b55e27dSYuval Mintz /* Mark VFs for disablement */ 39260b55e27dSYuval Mintz qed_iov_set_vfs_to_disable(cdev, true); 39270b55e27dSYuval Mintz 39280b55e27dSYuval Mintz if (cdev->p_iov_info && cdev->p_iov_info->num_vfs && pci_enabled) 39290b55e27dSYuval Mintz pci_disable_sriov(cdev->pdev); 39300b55e27dSYuval Mintz 39310b55e27dSYuval Mintz for_each_hwfn(cdev, i) { 39320b55e27dSYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 39330b55e27dSYuval Mintz struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 39340b55e27dSYuval Mintz 39350b55e27dSYuval Mintz /* Failure to acquire the ptt in 100g creates an odd error 39360b55e27dSYuval Mintz * where the first engine has already relased IOV. 39370b55e27dSYuval Mintz */ 39380b55e27dSYuval Mintz if (!ptt) { 39390b55e27dSYuval Mintz DP_ERR(hwfn, "Failed to acquire ptt\n"); 39400b55e27dSYuval Mintz return -EBUSY; 39410b55e27dSYuval Mintz } 39420b55e27dSYuval Mintz 3943733def6aSYuval Mintz /* Clean WFQ db and configure equal weight for all vports */ 3944733def6aSYuval Mintz qed_clean_wfq_db(hwfn, ptt); 3945733def6aSYuval Mintz 39460b55e27dSYuval Mintz qed_for_each_vf(hwfn, j) { 39470b55e27dSYuval Mintz int k; 39480b55e27dSYuval Mintz 39497eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(hwfn, j, true, false)) 39500b55e27dSYuval Mintz continue; 39510b55e27dSYuval Mintz 39520b55e27dSYuval Mintz /* Wait until VF is disabled before releasing */ 39530b55e27dSYuval Mintz for (k = 0; k < 100; k++) { 39540b55e27dSYuval Mintz if (!qed_iov_is_vf_stopped(hwfn, j)) 39550b55e27dSYuval Mintz msleep(20); 39560b55e27dSYuval Mintz else 39570b55e27dSYuval Mintz break; 39580b55e27dSYuval Mintz } 39590b55e27dSYuval Mintz 39600b55e27dSYuval Mintz if (k < 100) 39610b55e27dSYuval Mintz qed_iov_release_hw_for_vf(&cdev->hwfns[i], 39620b55e27dSYuval Mintz ptt, j); 39630b55e27dSYuval Mintz else 39640b55e27dSYuval Mintz DP_ERR(hwfn, 39650b55e27dSYuval Mintz "Timeout waiting for VF's FLR to end\n"); 39660b55e27dSYuval Mintz } 39670b55e27dSYuval Mintz 39680b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 39690b55e27dSYuval Mintz } 39700b55e27dSYuval Mintz 39710b55e27dSYuval Mintz qed_iov_set_vfs_to_disable(cdev, false); 39720b55e27dSYuval Mintz 39730b55e27dSYuval Mintz return 0; 39740b55e27dSYuval Mintz } 39750b55e27dSYuval Mintz 39763da7a37aSMintz, Yuval static void qed_sriov_enable_qid_config(struct qed_hwfn *hwfn, 39773da7a37aSMintz, Yuval u16 vfid, 39783da7a37aSMintz, Yuval struct qed_iov_vf_init_params *params) 39793da7a37aSMintz, Yuval { 39803da7a37aSMintz, Yuval u16 base, i; 39813da7a37aSMintz, Yuval 39823da7a37aSMintz, Yuval /* Since we have an equal resource distribution per-VF, and we assume 39833da7a37aSMintz, Yuval * PF has acquired the QED_PF_L2_QUE first queues, we start setting 39843da7a37aSMintz, Yuval * sequentially from there. 39853da7a37aSMintz, Yuval */ 39863da7a37aSMintz, Yuval base = FEAT_NUM(hwfn, QED_PF_L2_QUE) + vfid * params->num_queues; 39873da7a37aSMintz, Yuval 39883da7a37aSMintz, Yuval params->rel_vf_id = vfid; 39893da7a37aSMintz, Yuval for (i = 0; i < params->num_queues; i++) { 39903da7a37aSMintz, Yuval params->req_rx_queue[i] = base + i; 39913da7a37aSMintz, Yuval params->req_tx_queue[i] = base + i; 39923da7a37aSMintz, Yuval } 39933da7a37aSMintz, Yuval } 39943da7a37aSMintz, Yuval 39950b55e27dSYuval Mintz static int qed_sriov_enable(struct qed_dev *cdev, int num) 39960b55e27dSYuval Mintz { 39973da7a37aSMintz, Yuval struct qed_iov_vf_init_params params; 39980b55e27dSYuval Mintz int i, j, rc; 39990b55e27dSYuval Mintz 40000b55e27dSYuval Mintz if (num >= RESC_NUM(&cdev->hwfns[0], QED_VPORT)) { 40010b55e27dSYuval Mintz DP_NOTICE(cdev, "Can start at most %d VFs\n", 40020b55e27dSYuval Mintz RESC_NUM(&cdev->hwfns[0], QED_VPORT) - 1); 40030b55e27dSYuval Mintz return -EINVAL; 40040b55e27dSYuval Mintz } 40050b55e27dSYuval Mintz 40063da7a37aSMintz, Yuval memset(¶ms, 0, sizeof(params)); 40073da7a37aSMintz, Yuval 40080b55e27dSYuval Mintz /* Initialize HW for VF access */ 40090b55e27dSYuval Mintz for_each_hwfn(cdev, j) { 40100b55e27dSYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[j]; 40110b55e27dSYuval Mintz struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 40125a1f965aSMintz, Yuval 40135a1f965aSMintz, Yuval /* Make sure not to use more than 16 queues per VF */ 40143da7a37aSMintz, Yuval params.num_queues = min_t(int, 40153da7a37aSMintz, Yuval FEAT_NUM(hwfn, QED_VF_L2_QUE) / num, 40163da7a37aSMintz, Yuval 16); 40170b55e27dSYuval Mintz 40180b55e27dSYuval Mintz if (!ptt) { 40190b55e27dSYuval Mintz DP_ERR(hwfn, "Failed to acquire ptt\n"); 40200b55e27dSYuval Mintz rc = -EBUSY; 40210b55e27dSYuval Mintz goto err; 40220b55e27dSYuval Mintz } 40230b55e27dSYuval Mintz 40240b55e27dSYuval Mintz for (i = 0; i < num; i++) { 40257eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(hwfn, i, false, true)) 40260b55e27dSYuval Mintz continue; 40270b55e27dSYuval Mintz 40283da7a37aSMintz, Yuval qed_sriov_enable_qid_config(hwfn, i, ¶ms); 40293da7a37aSMintz, Yuval rc = qed_iov_init_hw_for_vf(hwfn, ptt, ¶ms); 40300b55e27dSYuval Mintz if (rc) { 40310b55e27dSYuval Mintz DP_ERR(cdev, "Failed to enable VF[%d]\n", i); 40320b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 40330b55e27dSYuval Mintz goto err; 40340b55e27dSYuval Mintz } 40350b55e27dSYuval Mintz } 40360b55e27dSYuval Mintz 40370b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 40380b55e27dSYuval Mintz } 40390b55e27dSYuval Mintz 40400b55e27dSYuval Mintz /* Enable SRIOV PCIe functions */ 40410b55e27dSYuval Mintz rc = pci_enable_sriov(cdev->pdev, num); 40420b55e27dSYuval Mintz if (rc) { 40430b55e27dSYuval Mintz DP_ERR(cdev, "Failed to enable sriov [%d]\n", rc); 40440b55e27dSYuval Mintz goto err; 40450b55e27dSYuval Mintz } 40460b55e27dSYuval Mintz 40470b55e27dSYuval Mintz return num; 40480b55e27dSYuval Mintz 40490b55e27dSYuval Mintz err: 40500b55e27dSYuval Mintz qed_sriov_disable(cdev, false); 40510b55e27dSYuval Mintz return rc; 40520b55e27dSYuval Mintz } 40530b55e27dSYuval Mintz 40540b55e27dSYuval Mintz static int qed_sriov_configure(struct qed_dev *cdev, int num_vfs_param) 40550b55e27dSYuval Mintz { 40560b55e27dSYuval Mintz if (!IS_QED_SRIOV(cdev)) { 40570b55e27dSYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, "SR-IOV is not supported\n"); 40580b55e27dSYuval Mintz return -EOPNOTSUPP; 40590b55e27dSYuval Mintz } 40600b55e27dSYuval Mintz 40610b55e27dSYuval Mintz if (num_vfs_param) 40620b55e27dSYuval Mintz return qed_sriov_enable(cdev, num_vfs_param); 40630b55e27dSYuval Mintz else 40640b55e27dSYuval Mintz return qed_sriov_disable(cdev, true); 40650b55e27dSYuval Mintz } 40660b55e27dSYuval Mintz 4067eff16960SYuval Mintz static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid) 4068eff16960SYuval Mintz { 4069eff16960SYuval Mintz int i; 4070eff16960SYuval Mintz 4071eff16960SYuval Mintz if (!IS_QED_SRIOV(cdev) || !IS_PF_SRIOV_ALLOC(&cdev->hwfns[0])) { 4072eff16960SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 4073eff16960SYuval Mintz "Cannot set a VF MAC; Sriov is not enabled\n"); 4074eff16960SYuval Mintz return -EINVAL; 4075eff16960SYuval Mintz } 4076eff16960SYuval Mintz 40777eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) { 4078eff16960SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 4079eff16960SYuval Mintz "Cannot set VF[%d] MAC (VF is not active)\n", vfid); 4080eff16960SYuval Mintz return -EINVAL; 4081eff16960SYuval Mintz } 4082eff16960SYuval Mintz 4083eff16960SYuval Mintz for_each_hwfn(cdev, i) { 4084eff16960SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 4085eff16960SYuval Mintz struct qed_public_vf_info *vf_info; 4086eff16960SYuval Mintz 4087eff16960SYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true); 4088eff16960SYuval Mintz if (!vf_info) 4089eff16960SYuval Mintz continue; 4090eff16960SYuval Mintz 4091eff16960SYuval Mintz /* Set the forced MAC, and schedule the IOV task */ 4092eff16960SYuval Mintz ether_addr_copy(vf_info->forced_mac, mac); 4093eff16960SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_SET_UNICAST_FILTER_FLAG); 4094eff16960SYuval Mintz } 4095eff16960SYuval Mintz 4096eff16960SYuval Mintz return 0; 4097eff16960SYuval Mintz } 4098eff16960SYuval Mintz 409908feecd7SYuval Mintz static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid) 410008feecd7SYuval Mintz { 410108feecd7SYuval Mintz int i; 410208feecd7SYuval Mintz 410308feecd7SYuval Mintz if (!IS_QED_SRIOV(cdev) || !IS_PF_SRIOV_ALLOC(&cdev->hwfns[0])) { 410408feecd7SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 410508feecd7SYuval Mintz "Cannot set a VF MAC; Sriov is not enabled\n"); 410608feecd7SYuval Mintz return -EINVAL; 410708feecd7SYuval Mintz } 410808feecd7SYuval Mintz 41097eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) { 411008feecd7SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 411108feecd7SYuval Mintz "Cannot set VF[%d] MAC (VF is not active)\n", vfid); 411208feecd7SYuval Mintz return -EINVAL; 411308feecd7SYuval Mintz } 411408feecd7SYuval Mintz 411508feecd7SYuval Mintz for_each_hwfn(cdev, i) { 411608feecd7SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 411708feecd7SYuval Mintz struct qed_public_vf_info *vf_info; 411808feecd7SYuval Mintz 411908feecd7SYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true); 412008feecd7SYuval Mintz if (!vf_info) 412108feecd7SYuval Mintz continue; 412208feecd7SYuval Mintz 412308feecd7SYuval Mintz /* Set the forced vlan, and schedule the IOV task */ 412408feecd7SYuval Mintz vf_info->forced_vlan = vid; 412508feecd7SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_SET_UNICAST_FILTER_FLAG); 412608feecd7SYuval Mintz } 412708feecd7SYuval Mintz 412808feecd7SYuval Mintz return 0; 412908feecd7SYuval Mintz } 413008feecd7SYuval Mintz 413173390ac9SYuval Mintz static int qed_get_vf_config(struct qed_dev *cdev, 413273390ac9SYuval Mintz int vf_id, struct ifla_vf_info *ivi) 413373390ac9SYuval Mintz { 413473390ac9SYuval Mintz struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 413573390ac9SYuval Mintz struct qed_public_vf_info *vf_info; 413673390ac9SYuval Mintz struct qed_mcp_link_state link; 413773390ac9SYuval Mintz u32 tx_rate; 413873390ac9SYuval Mintz 413973390ac9SYuval Mintz /* Sanitize request */ 414073390ac9SYuval Mintz if (IS_VF(cdev)) 414173390ac9SYuval Mintz return -EINVAL; 414273390ac9SYuval Mintz 41437eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, false)) { 414473390ac9SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 414573390ac9SYuval Mintz "VF index [%d] isn't active\n", vf_id); 414673390ac9SYuval Mintz return -EINVAL; 414773390ac9SYuval Mintz } 414873390ac9SYuval Mintz 414973390ac9SYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, vf_id, true); 415073390ac9SYuval Mintz 415173390ac9SYuval Mintz qed_iov_get_link(hwfn, vf_id, NULL, &link, NULL); 415273390ac9SYuval Mintz 415373390ac9SYuval Mintz /* Fill information about VF */ 415473390ac9SYuval Mintz ivi->vf = vf_id; 415573390ac9SYuval Mintz 415673390ac9SYuval Mintz if (is_valid_ether_addr(vf_info->forced_mac)) 415773390ac9SYuval Mintz ether_addr_copy(ivi->mac, vf_info->forced_mac); 415873390ac9SYuval Mintz else 415973390ac9SYuval Mintz ether_addr_copy(ivi->mac, vf_info->mac); 416073390ac9SYuval Mintz 416173390ac9SYuval Mintz ivi->vlan = vf_info->forced_vlan; 416273390ac9SYuval Mintz ivi->spoofchk = qed_iov_spoofchk_get(hwfn, vf_id); 416373390ac9SYuval Mintz ivi->linkstate = vf_info->link_state; 416473390ac9SYuval Mintz tx_rate = vf_info->tx_rate; 416573390ac9SYuval Mintz ivi->max_tx_rate = tx_rate ? tx_rate : link.speed; 416673390ac9SYuval Mintz ivi->min_tx_rate = qed_iov_get_vf_min_rate(hwfn, vf_id); 416773390ac9SYuval Mintz 416873390ac9SYuval Mintz return 0; 416973390ac9SYuval Mintz } 417073390ac9SYuval Mintz 417136558c3dSYuval Mintz void qed_inform_vf_link_state(struct qed_hwfn *hwfn) 417236558c3dSYuval Mintz { 4173e50728efSMintz, Yuval struct qed_hwfn *lead_hwfn = QED_LEADING_HWFN(hwfn->cdev); 417436558c3dSYuval Mintz struct qed_mcp_link_capabilities caps; 417536558c3dSYuval Mintz struct qed_mcp_link_params params; 417636558c3dSYuval Mintz struct qed_mcp_link_state link; 417736558c3dSYuval Mintz int i; 417836558c3dSYuval Mintz 417936558c3dSYuval Mintz if (!hwfn->pf_iov_info) 418036558c3dSYuval Mintz return; 418136558c3dSYuval Mintz 418236558c3dSYuval Mintz /* Update bulletin of all future possible VFs with link configuration */ 418336558c3dSYuval Mintz for (i = 0; i < hwfn->cdev->p_iov_info->total_vfs; i++) { 4184733def6aSYuval Mintz struct qed_public_vf_info *vf_info; 4185733def6aSYuval Mintz 4186733def6aSYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, i, false); 4187733def6aSYuval Mintz if (!vf_info) 4188733def6aSYuval Mintz continue; 4189733def6aSYuval Mintz 4190e50728efSMintz, Yuval /* Only hwfn0 is actually interested in the link speed. 4191e50728efSMintz, Yuval * But since only it would receive an MFW indication of link, 4192e50728efSMintz, Yuval * need to take configuration from it - otherwise things like 4193e50728efSMintz, Yuval * rate limiting for hwfn1 VF would not work. 4194e50728efSMintz, Yuval */ 4195e50728efSMintz, Yuval memcpy(¶ms, qed_mcp_get_link_params(lead_hwfn), 4196e50728efSMintz, Yuval sizeof(params)); 4197e50728efSMintz, Yuval memcpy(&link, qed_mcp_get_link_state(lead_hwfn), sizeof(link)); 4198e50728efSMintz, Yuval memcpy(&caps, qed_mcp_get_link_capabilities(lead_hwfn), 419936558c3dSYuval Mintz sizeof(caps)); 420036558c3dSYuval Mintz 4201733def6aSYuval Mintz /* Modify link according to the VF's configured link state */ 4202733def6aSYuval Mintz switch (vf_info->link_state) { 4203733def6aSYuval Mintz case IFLA_VF_LINK_STATE_DISABLE: 4204733def6aSYuval Mintz link.link_up = false; 4205733def6aSYuval Mintz break; 4206733def6aSYuval Mintz case IFLA_VF_LINK_STATE_ENABLE: 4207733def6aSYuval Mintz link.link_up = true; 4208733def6aSYuval Mintz /* Set speed according to maximum supported by HW. 4209733def6aSYuval Mintz * that is 40G for regular devices and 100G for CMT 4210733def6aSYuval Mintz * mode devices. 4211733def6aSYuval Mintz */ 4212733def6aSYuval Mintz link.speed = (hwfn->cdev->num_hwfns > 1) ? 4213733def6aSYuval Mintz 100000 : 40000; 4214733def6aSYuval Mintz default: 4215733def6aSYuval Mintz /* In auto mode pass PF link image to VF */ 4216733def6aSYuval Mintz break; 4217733def6aSYuval Mintz } 4218733def6aSYuval Mintz 4219733def6aSYuval Mintz if (link.link_up && vf_info->tx_rate) { 4220733def6aSYuval Mintz struct qed_ptt *ptt; 4221733def6aSYuval Mintz int rate; 4222733def6aSYuval Mintz 4223733def6aSYuval Mintz rate = min_t(int, vf_info->tx_rate, link.speed); 4224733def6aSYuval Mintz 4225733def6aSYuval Mintz ptt = qed_ptt_acquire(hwfn); 4226733def6aSYuval Mintz if (!ptt) { 4227733def6aSYuval Mintz DP_NOTICE(hwfn, "Failed to acquire PTT\n"); 4228733def6aSYuval Mintz return; 4229733def6aSYuval Mintz } 4230733def6aSYuval Mintz 4231733def6aSYuval Mintz if (!qed_iov_configure_tx_rate(hwfn, ptt, i, rate)) { 4232733def6aSYuval Mintz vf_info->tx_rate = rate; 4233733def6aSYuval Mintz link.speed = rate; 4234733def6aSYuval Mintz } 4235733def6aSYuval Mintz 4236733def6aSYuval Mintz qed_ptt_release(hwfn, ptt); 4237733def6aSYuval Mintz } 4238733def6aSYuval Mintz 423936558c3dSYuval Mintz qed_iov_set_link(hwfn, i, ¶ms, &link, &caps); 424036558c3dSYuval Mintz } 424136558c3dSYuval Mintz 424236558c3dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 424336558c3dSYuval Mintz } 424436558c3dSYuval Mintz 4245733def6aSYuval Mintz static int qed_set_vf_link_state(struct qed_dev *cdev, 4246733def6aSYuval Mintz int vf_id, int link_state) 4247733def6aSYuval Mintz { 4248733def6aSYuval Mintz int i; 4249733def6aSYuval Mintz 4250733def6aSYuval Mintz /* Sanitize request */ 4251733def6aSYuval Mintz if (IS_VF(cdev)) 4252733def6aSYuval Mintz return -EINVAL; 4253733def6aSYuval Mintz 42547eff82b0SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, true)) { 4255733def6aSYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 4256733def6aSYuval Mintz "VF index [%d] isn't active\n", vf_id); 4257733def6aSYuval Mintz return -EINVAL; 4258733def6aSYuval Mintz } 4259733def6aSYuval Mintz 4260733def6aSYuval Mintz /* Handle configuration of link state */ 4261733def6aSYuval Mintz for_each_hwfn(cdev, i) { 4262733def6aSYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 4263733def6aSYuval Mintz struct qed_public_vf_info *vf; 4264733def6aSYuval Mintz 4265733def6aSYuval Mintz vf = qed_iov_get_public_vf_info(hwfn, vf_id, true); 4266733def6aSYuval Mintz if (!vf) 4267733def6aSYuval Mintz continue; 4268733def6aSYuval Mintz 4269733def6aSYuval Mintz if (vf->link_state == link_state) 4270733def6aSYuval Mintz continue; 4271733def6aSYuval Mintz 4272733def6aSYuval Mintz vf->link_state = link_state; 4273733def6aSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 4274733def6aSYuval Mintz } 4275733def6aSYuval Mintz 4276733def6aSYuval Mintz return 0; 4277733def6aSYuval Mintz } 4278733def6aSYuval Mintz 42796ddc7608SYuval Mintz static int qed_spoof_configure(struct qed_dev *cdev, int vfid, bool val) 42806ddc7608SYuval Mintz { 42816ddc7608SYuval Mintz int i, rc = -EINVAL; 42826ddc7608SYuval Mintz 42836ddc7608SYuval Mintz for_each_hwfn(cdev, i) { 42846ddc7608SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 42856ddc7608SYuval Mintz 42866ddc7608SYuval Mintz rc = qed_iov_spoofchk_set(p_hwfn, vfid, val); 42876ddc7608SYuval Mintz if (rc) 42886ddc7608SYuval Mintz break; 42896ddc7608SYuval Mintz } 42906ddc7608SYuval Mintz 42916ddc7608SYuval Mintz return rc; 42926ddc7608SYuval Mintz } 42936ddc7608SYuval Mintz 4294733def6aSYuval Mintz static int qed_configure_max_vf_rate(struct qed_dev *cdev, int vfid, int rate) 4295733def6aSYuval Mintz { 4296733def6aSYuval Mintz int i; 4297733def6aSYuval Mintz 4298733def6aSYuval Mintz for_each_hwfn(cdev, i) { 4299733def6aSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 4300733def6aSYuval Mintz struct qed_public_vf_info *vf; 4301733def6aSYuval Mintz 4302733def6aSYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, vfid)) { 4303733def6aSYuval Mintz DP_NOTICE(p_hwfn, 4304733def6aSYuval Mintz "SR-IOV sanity check failed, can't set tx rate\n"); 4305733def6aSYuval Mintz return -EINVAL; 4306733def6aSYuval Mintz } 4307733def6aSYuval Mintz 4308733def6aSYuval Mintz vf = qed_iov_get_public_vf_info(p_hwfn, vfid, true); 4309733def6aSYuval Mintz 4310733def6aSYuval Mintz vf->tx_rate = rate; 4311733def6aSYuval Mintz 4312733def6aSYuval Mintz qed_inform_vf_link_state(p_hwfn); 4313733def6aSYuval Mintz } 4314733def6aSYuval Mintz 4315733def6aSYuval Mintz return 0; 4316733def6aSYuval Mintz } 4317733def6aSYuval Mintz 4318733def6aSYuval Mintz static int qed_set_vf_rate(struct qed_dev *cdev, 4319733def6aSYuval Mintz int vfid, u32 min_rate, u32 max_rate) 4320733def6aSYuval Mintz { 4321733def6aSYuval Mintz int rc_min = 0, rc_max = 0; 4322733def6aSYuval Mintz 4323733def6aSYuval Mintz if (max_rate) 4324733def6aSYuval Mintz rc_max = qed_configure_max_vf_rate(cdev, vfid, max_rate); 4325733def6aSYuval Mintz 4326733def6aSYuval Mintz if (min_rate) 4327733def6aSYuval Mintz rc_min = qed_iov_configure_min_tx_rate(cdev, vfid, min_rate); 4328733def6aSYuval Mintz 4329733def6aSYuval Mintz if (rc_max | rc_min) 4330733def6aSYuval Mintz return -EINVAL; 4331733def6aSYuval Mintz 4332733def6aSYuval Mintz return 0; 4333733def6aSYuval Mintz } 4334733def6aSYuval Mintz 4335f990c82cSMintz, Yuval static int qed_set_vf_trust(struct qed_dev *cdev, int vfid, bool trust) 4336f990c82cSMintz, Yuval { 4337f990c82cSMintz, Yuval int i; 4338f990c82cSMintz, Yuval 4339f990c82cSMintz, Yuval for_each_hwfn(cdev, i) { 4340f990c82cSMintz, Yuval struct qed_hwfn *hwfn = &cdev->hwfns[i]; 4341f990c82cSMintz, Yuval struct qed_public_vf_info *vf; 4342f990c82cSMintz, Yuval 4343f990c82cSMintz, Yuval if (!qed_iov_pf_sanity_check(hwfn, vfid)) { 4344f990c82cSMintz, Yuval DP_NOTICE(hwfn, 4345f990c82cSMintz, Yuval "SR-IOV sanity check failed, can't set trust\n"); 4346f990c82cSMintz, Yuval return -EINVAL; 4347f990c82cSMintz, Yuval } 4348f990c82cSMintz, Yuval 4349f990c82cSMintz, Yuval vf = qed_iov_get_public_vf_info(hwfn, vfid, true); 4350f990c82cSMintz, Yuval 4351f990c82cSMintz, Yuval if (vf->is_trusted_request == trust) 4352f990c82cSMintz, Yuval return 0; 4353f990c82cSMintz, Yuval vf->is_trusted_request = trust; 4354f990c82cSMintz, Yuval 4355f990c82cSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_TRUST_FLAG); 4356f990c82cSMintz, Yuval } 4357f990c82cSMintz, Yuval 4358f990c82cSMintz, Yuval return 0; 4359f990c82cSMintz, Yuval } 4360f990c82cSMintz, Yuval 436137bff2b9SYuval Mintz static void qed_handle_vf_msg(struct qed_hwfn *hwfn) 436237bff2b9SYuval Mintz { 436337bff2b9SYuval Mintz u64 events[QED_VF_ARRAY_LENGTH]; 436437bff2b9SYuval Mintz struct qed_ptt *ptt; 436537bff2b9SYuval Mintz int i; 436637bff2b9SYuval Mintz 436737bff2b9SYuval Mintz ptt = qed_ptt_acquire(hwfn); 436837bff2b9SYuval Mintz if (!ptt) { 436937bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, 437037bff2b9SYuval Mintz "Can't acquire PTT; re-scheduling\n"); 437137bff2b9SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_MSG_FLAG); 437237bff2b9SYuval Mintz return; 437337bff2b9SYuval Mintz } 437437bff2b9SYuval Mintz 4375fd3c615aSMintz, Yuval qed_iov_pf_get_pending_events(hwfn, events); 437637bff2b9SYuval Mintz 437737bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, 437837bff2b9SYuval Mintz "Event mask of VF events: 0x%llx 0x%llx 0x%llx\n", 437937bff2b9SYuval Mintz events[0], events[1], events[2]); 438037bff2b9SYuval Mintz 438137bff2b9SYuval Mintz qed_for_each_vf(hwfn, i) { 438237bff2b9SYuval Mintz /* Skip VFs with no pending messages */ 438337bff2b9SYuval Mintz if (!(events[i / 64] & (1ULL << (i % 64)))) 438437bff2b9SYuval Mintz continue; 438537bff2b9SYuval Mintz 438637bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, 438737bff2b9SYuval Mintz "Handling VF message from VF 0x%02x [Abs 0x%02x]\n", 438837bff2b9SYuval Mintz i, hwfn->cdev->p_iov_info->first_vf_in_pf + i); 438937bff2b9SYuval Mintz 439037bff2b9SYuval Mintz /* Copy VF's message to PF's request buffer for that VF */ 439137bff2b9SYuval Mintz if (qed_iov_copy_vf_msg(hwfn, ptt, i)) 439237bff2b9SYuval Mintz continue; 439337bff2b9SYuval Mintz 439437bff2b9SYuval Mintz qed_iov_process_mbx_req(hwfn, ptt, i); 439537bff2b9SYuval Mintz } 439637bff2b9SYuval Mintz 439737bff2b9SYuval Mintz qed_ptt_release(hwfn, ptt); 439837bff2b9SYuval Mintz } 439937bff2b9SYuval Mintz 440008feecd7SYuval Mintz static void qed_handle_pf_set_vf_unicast(struct qed_hwfn *hwfn) 440108feecd7SYuval Mintz { 440208feecd7SYuval Mintz int i; 440308feecd7SYuval Mintz 440408feecd7SYuval Mintz qed_for_each_vf(hwfn, i) { 440508feecd7SYuval Mintz struct qed_public_vf_info *info; 440608feecd7SYuval Mintz bool update = false; 4407eff16960SYuval Mintz u8 *mac; 440808feecd7SYuval Mintz 440908feecd7SYuval Mintz info = qed_iov_get_public_vf_info(hwfn, i, true); 441008feecd7SYuval Mintz if (!info) 441108feecd7SYuval Mintz continue; 441208feecd7SYuval Mintz 441308feecd7SYuval Mintz /* Update data on bulletin board */ 4414eff16960SYuval Mintz mac = qed_iov_bulletin_get_forced_mac(hwfn, i); 4415eff16960SYuval Mintz if (is_valid_ether_addr(info->forced_mac) && 4416eff16960SYuval Mintz (!mac || !ether_addr_equal(mac, info->forced_mac))) { 4417eff16960SYuval Mintz DP_VERBOSE(hwfn, 4418eff16960SYuval Mintz QED_MSG_IOV, 4419eff16960SYuval Mintz "Handling PF setting of VF MAC to VF 0x%02x [Abs 0x%02x]\n", 4420eff16960SYuval Mintz i, 4421eff16960SYuval Mintz hwfn->cdev->p_iov_info->first_vf_in_pf + i); 4422eff16960SYuval Mintz 4423eff16960SYuval Mintz /* Update bulletin board with forced MAC */ 4424eff16960SYuval Mintz qed_iov_bulletin_set_forced_mac(hwfn, 4425eff16960SYuval Mintz info->forced_mac, i); 4426eff16960SYuval Mintz update = true; 4427eff16960SYuval Mintz } 442808feecd7SYuval Mintz 442908feecd7SYuval Mintz if (qed_iov_bulletin_get_forced_vlan(hwfn, i) ^ 443008feecd7SYuval Mintz info->forced_vlan) { 443108feecd7SYuval Mintz DP_VERBOSE(hwfn, 443208feecd7SYuval Mintz QED_MSG_IOV, 443308feecd7SYuval Mintz "Handling PF setting of pvid [0x%04x] to VF 0x%02x [Abs 0x%02x]\n", 443408feecd7SYuval Mintz info->forced_vlan, 443508feecd7SYuval Mintz i, 443608feecd7SYuval Mintz hwfn->cdev->p_iov_info->first_vf_in_pf + i); 443708feecd7SYuval Mintz qed_iov_bulletin_set_forced_vlan(hwfn, 443808feecd7SYuval Mintz info->forced_vlan, i); 443908feecd7SYuval Mintz update = true; 444008feecd7SYuval Mintz } 444108feecd7SYuval Mintz 444208feecd7SYuval Mintz if (update) 444308feecd7SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 444408feecd7SYuval Mintz } 444508feecd7SYuval Mintz } 444608feecd7SYuval Mintz 444736558c3dSYuval Mintz static void qed_handle_bulletin_post(struct qed_hwfn *hwfn) 444836558c3dSYuval Mintz { 444936558c3dSYuval Mintz struct qed_ptt *ptt; 445036558c3dSYuval Mintz int i; 445136558c3dSYuval Mintz 445236558c3dSYuval Mintz ptt = qed_ptt_acquire(hwfn); 445336558c3dSYuval Mintz if (!ptt) { 445436558c3dSYuval Mintz DP_NOTICE(hwfn, "Failed allocating a ptt entry\n"); 445536558c3dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 445636558c3dSYuval Mintz return; 445736558c3dSYuval Mintz } 445836558c3dSYuval Mintz 445936558c3dSYuval Mintz qed_for_each_vf(hwfn, i) 446036558c3dSYuval Mintz qed_iov_post_vf_bulletin(hwfn, i, ptt); 446136558c3dSYuval Mintz 446236558c3dSYuval Mintz qed_ptt_release(hwfn, ptt); 446336558c3dSYuval Mintz } 446436558c3dSYuval Mintz 4465f990c82cSMintz, Yuval static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn) 4466f990c82cSMintz, Yuval { 4467f990c82cSMintz, Yuval struct qed_sp_vport_update_params params; 4468f990c82cSMintz, Yuval struct qed_filter_accept_flags *flags; 4469f990c82cSMintz, Yuval struct qed_public_vf_info *vf_info; 4470f990c82cSMintz, Yuval struct qed_vf_info *vf; 4471f990c82cSMintz, Yuval u8 mask; 4472f990c82cSMintz, Yuval int i; 4473f990c82cSMintz, Yuval 4474f990c82cSMintz, Yuval mask = QED_ACCEPT_UCAST_UNMATCHED | QED_ACCEPT_MCAST_UNMATCHED; 4475f990c82cSMintz, Yuval flags = ¶ms.accept_flags; 4476f990c82cSMintz, Yuval 4477f990c82cSMintz, Yuval qed_for_each_vf(hwfn, i) { 4478f990c82cSMintz, Yuval /* Need to make sure current requested configuration didn't 4479f990c82cSMintz, Yuval * flip so that we'll end up configuring something that's not 4480f990c82cSMintz, Yuval * needed. 4481f990c82cSMintz, Yuval */ 4482f990c82cSMintz, Yuval vf_info = qed_iov_get_public_vf_info(hwfn, i, true); 4483f990c82cSMintz, Yuval if (vf_info->is_trusted_configured == 4484f990c82cSMintz, Yuval vf_info->is_trusted_request) 4485f990c82cSMintz, Yuval continue; 4486f990c82cSMintz, Yuval vf_info->is_trusted_configured = vf_info->is_trusted_request; 4487f990c82cSMintz, Yuval 4488f990c82cSMintz, Yuval /* Validate that the VF has a configured vport */ 4489f990c82cSMintz, Yuval vf = qed_iov_get_vf_info(hwfn, i, true); 4490f990c82cSMintz, Yuval if (!vf->vport_instance) 4491f990c82cSMintz, Yuval continue; 4492f990c82cSMintz, Yuval 4493f990c82cSMintz, Yuval memset(¶ms, 0, sizeof(params)); 4494f990c82cSMintz, Yuval params.opaque_fid = vf->opaque_fid; 4495f990c82cSMintz, Yuval params.vport_id = vf->vport_id; 4496f990c82cSMintz, Yuval 4497f990c82cSMintz, Yuval if (vf_info->rx_accept_mode & mask) { 4498f990c82cSMintz, Yuval flags->update_rx_mode_config = 1; 4499f990c82cSMintz, Yuval flags->rx_accept_filter = vf_info->rx_accept_mode; 4500f990c82cSMintz, Yuval } 4501f990c82cSMintz, Yuval 4502f990c82cSMintz, Yuval if (vf_info->tx_accept_mode & mask) { 4503f990c82cSMintz, Yuval flags->update_tx_mode_config = 1; 4504f990c82cSMintz, Yuval flags->tx_accept_filter = vf_info->tx_accept_mode; 4505f990c82cSMintz, Yuval } 4506f990c82cSMintz, Yuval 4507f990c82cSMintz, Yuval /* Remove if needed; Otherwise this would set the mask */ 4508f990c82cSMintz, Yuval if (!vf_info->is_trusted_configured) { 4509f990c82cSMintz, Yuval flags->rx_accept_filter &= ~mask; 4510f990c82cSMintz, Yuval flags->tx_accept_filter &= ~mask; 4511f990c82cSMintz, Yuval } 4512f990c82cSMintz, Yuval 4513f990c82cSMintz, Yuval if (flags->update_rx_mode_config || 4514f990c82cSMintz, Yuval flags->update_tx_mode_config) 4515f990c82cSMintz, Yuval qed_sp_vport_update(hwfn, ¶ms, 4516f990c82cSMintz, Yuval QED_SPQ_MODE_EBLOCK, NULL); 4517f990c82cSMintz, Yuval } 4518f990c82cSMintz, Yuval } 4519f990c82cSMintz, Yuval 4520ba56947aSBaoyou Xie static void qed_iov_pf_task(struct work_struct *work) 4521ba56947aSBaoyou Xie 452237bff2b9SYuval Mintz { 452337bff2b9SYuval Mintz struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn, 452437bff2b9SYuval Mintz iov_task.work); 45250b55e27dSYuval Mintz int rc; 452637bff2b9SYuval Mintz 452737bff2b9SYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_STOP_WQ_FLAG, &hwfn->iov_task_flags)) 452837bff2b9SYuval Mintz return; 452937bff2b9SYuval Mintz 45300b55e27dSYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_FLR_FLAG, &hwfn->iov_task_flags)) { 45310b55e27dSYuval Mintz struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 45320b55e27dSYuval Mintz 45330b55e27dSYuval Mintz if (!ptt) { 45340b55e27dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_FLR_FLAG); 45350b55e27dSYuval Mintz return; 45360b55e27dSYuval Mintz } 45370b55e27dSYuval Mintz 45380b55e27dSYuval Mintz rc = qed_iov_vf_flr_cleanup(hwfn, ptt); 45390b55e27dSYuval Mintz if (rc) 45400b55e27dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_FLR_FLAG); 45410b55e27dSYuval Mintz 45420b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 45430b55e27dSYuval Mintz } 45440b55e27dSYuval Mintz 454537bff2b9SYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_MSG_FLAG, &hwfn->iov_task_flags)) 454637bff2b9SYuval Mintz qed_handle_vf_msg(hwfn); 454708feecd7SYuval Mintz 454808feecd7SYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_SET_UNICAST_FILTER_FLAG, 454908feecd7SYuval Mintz &hwfn->iov_task_flags)) 455008feecd7SYuval Mintz qed_handle_pf_set_vf_unicast(hwfn); 455108feecd7SYuval Mintz 455236558c3dSYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_BULLETIN_UPDATE_FLAG, 455336558c3dSYuval Mintz &hwfn->iov_task_flags)) 455436558c3dSYuval Mintz qed_handle_bulletin_post(hwfn); 4555f990c82cSMintz, Yuval 4556f990c82cSMintz, Yuval if (test_and_clear_bit(QED_IOV_WQ_TRUST_FLAG, &hwfn->iov_task_flags)) 4557f990c82cSMintz, Yuval qed_iov_handle_trust_change(hwfn); 455837bff2b9SYuval Mintz } 455937bff2b9SYuval Mintz 456037bff2b9SYuval Mintz void qed_iov_wq_stop(struct qed_dev *cdev, bool schedule_first) 456137bff2b9SYuval Mintz { 456237bff2b9SYuval Mintz int i; 456337bff2b9SYuval Mintz 456437bff2b9SYuval Mintz for_each_hwfn(cdev, i) { 456537bff2b9SYuval Mintz if (!cdev->hwfns[i].iov_wq) 456637bff2b9SYuval Mintz continue; 456737bff2b9SYuval Mintz 456837bff2b9SYuval Mintz if (schedule_first) { 456937bff2b9SYuval Mintz qed_schedule_iov(&cdev->hwfns[i], 457037bff2b9SYuval Mintz QED_IOV_WQ_STOP_WQ_FLAG); 457137bff2b9SYuval Mintz cancel_delayed_work_sync(&cdev->hwfns[i].iov_task); 457237bff2b9SYuval Mintz } 457337bff2b9SYuval Mintz 457437bff2b9SYuval Mintz flush_workqueue(cdev->hwfns[i].iov_wq); 457537bff2b9SYuval Mintz destroy_workqueue(cdev->hwfns[i].iov_wq); 457637bff2b9SYuval Mintz } 457737bff2b9SYuval Mintz } 457837bff2b9SYuval Mintz 457937bff2b9SYuval Mintz int qed_iov_wq_start(struct qed_dev *cdev) 458037bff2b9SYuval Mintz { 458137bff2b9SYuval Mintz char name[NAME_SIZE]; 458237bff2b9SYuval Mintz int i; 458337bff2b9SYuval Mintz 458437bff2b9SYuval Mintz for_each_hwfn(cdev, i) { 458537bff2b9SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 458637bff2b9SYuval Mintz 458736558c3dSYuval Mintz /* PFs needs a dedicated workqueue only if they support IOV. 458836558c3dSYuval Mintz * VFs always require one. 458936558c3dSYuval Mintz */ 459036558c3dSYuval Mintz if (IS_PF(p_hwfn->cdev) && !IS_PF_SRIOV(p_hwfn)) 459137bff2b9SYuval Mintz continue; 459237bff2b9SYuval Mintz 459337bff2b9SYuval Mintz snprintf(name, NAME_SIZE, "iov-%02x:%02x.%02x", 459437bff2b9SYuval Mintz cdev->pdev->bus->number, 459537bff2b9SYuval Mintz PCI_SLOT(cdev->pdev->devfn), p_hwfn->abs_pf_id); 459637bff2b9SYuval Mintz 459737bff2b9SYuval Mintz p_hwfn->iov_wq = create_singlethread_workqueue(name); 459837bff2b9SYuval Mintz if (!p_hwfn->iov_wq) { 459937bff2b9SYuval Mintz DP_NOTICE(p_hwfn, "Cannot create iov workqueue\n"); 460037bff2b9SYuval Mintz return -ENOMEM; 460137bff2b9SYuval Mintz } 460237bff2b9SYuval Mintz 460336558c3dSYuval Mintz if (IS_PF(cdev)) 460437bff2b9SYuval Mintz INIT_DELAYED_WORK(&p_hwfn->iov_task, qed_iov_pf_task); 460536558c3dSYuval Mintz else 460636558c3dSYuval Mintz INIT_DELAYED_WORK(&p_hwfn->iov_task, qed_iov_vf_task); 460737bff2b9SYuval Mintz } 460837bff2b9SYuval Mintz 460937bff2b9SYuval Mintz return 0; 461037bff2b9SYuval Mintz } 46110b55e27dSYuval Mintz 46120b55e27dSYuval Mintz const struct qed_iov_hv_ops qed_iov_ops_pass = { 46130b55e27dSYuval Mintz .configure = &qed_sriov_configure, 4614eff16960SYuval Mintz .set_mac = &qed_sriov_pf_set_mac, 461508feecd7SYuval Mintz .set_vlan = &qed_sriov_pf_set_vlan, 461673390ac9SYuval Mintz .get_config = &qed_get_vf_config, 4617733def6aSYuval Mintz .set_link_state = &qed_set_vf_link_state, 46186ddc7608SYuval Mintz .set_spoof = &qed_spoof_configure, 4619733def6aSYuval Mintz .set_rate = &qed_set_vf_rate, 4620f990c82cSMintz, Yuval .set_trust = &qed_set_vf_trust, 46210b55e27dSYuval Mintz }; 4622