132a47e72SYuval Mintz /* QLogic qed NIC Driver 232a47e72SYuval Mintz * Copyright (c) 2015 QLogic Corporation 332a47e72SYuval Mintz * 432a47e72SYuval Mintz * This software is available under the terms of the GNU General Public License 532a47e72SYuval Mintz * (GPL) Version 2, available from the file COPYING in the main directory of 632a47e72SYuval Mintz * this source tree. 732a47e72SYuval Mintz */ 832a47e72SYuval Mintz 9dacd88d6SYuval Mintz #include <linux/etherdevice.h> 1036558c3dSYuval Mintz #include <linux/crc32.h> 110b55e27dSYuval Mintz #include <linux/qed/qed_iov_if.h> 121408cc1fSYuval Mintz #include "qed_cxt.h" 131408cc1fSYuval Mintz #include "qed_hsi.h" 1432a47e72SYuval Mintz #include "qed_hw.h" 151408cc1fSYuval Mintz #include "qed_init_ops.h" 1632a47e72SYuval Mintz #include "qed_int.h" 171408cc1fSYuval Mintz #include "qed_mcp.h" 1832a47e72SYuval Mintz #include "qed_reg_addr.h" 191408cc1fSYuval Mintz #include "qed_sp.h" 2032a47e72SYuval Mintz #include "qed_sriov.h" 2132a47e72SYuval Mintz #include "qed_vf.h" 2232a47e72SYuval Mintz 231408cc1fSYuval Mintz /* IOV ramrods */ 241fe614d1SYuval Mintz static int qed_sp_vf_start(struct qed_hwfn *p_hwfn, struct qed_vf_info *p_vf) 251408cc1fSYuval Mintz { 261408cc1fSYuval Mintz struct vf_start_ramrod_data *p_ramrod = NULL; 271408cc1fSYuval Mintz struct qed_spq_entry *p_ent = NULL; 281408cc1fSYuval Mintz struct qed_sp_init_data init_data; 291408cc1fSYuval Mintz int rc = -EINVAL; 301fe614d1SYuval Mintz u8 fp_minor; 311408cc1fSYuval Mintz 321408cc1fSYuval Mintz /* Get SPQ entry */ 331408cc1fSYuval Mintz memset(&init_data, 0, sizeof(init_data)); 341408cc1fSYuval Mintz init_data.cid = qed_spq_get_cid(p_hwfn); 351fe614d1SYuval Mintz init_data.opaque_fid = p_vf->opaque_fid; 361408cc1fSYuval Mintz init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 371408cc1fSYuval Mintz 381408cc1fSYuval Mintz rc = qed_sp_init_request(p_hwfn, &p_ent, 391408cc1fSYuval Mintz COMMON_RAMROD_VF_START, 401408cc1fSYuval Mintz PROTOCOLID_COMMON, &init_data); 411408cc1fSYuval Mintz if (rc) 421408cc1fSYuval Mintz return rc; 431408cc1fSYuval Mintz 441408cc1fSYuval Mintz p_ramrod = &p_ent->ramrod.vf_start; 451408cc1fSYuval Mintz 461fe614d1SYuval Mintz p_ramrod->vf_id = GET_FIELD(p_vf->concrete_fid, PXP_CONCRETE_FID_VFID); 471fe614d1SYuval Mintz p_ramrod->opaque_fid = cpu_to_le16(p_vf->opaque_fid); 481408cc1fSYuval Mintz 491fe614d1SYuval Mintz switch (p_hwfn->hw_info.personality) { 501fe614d1SYuval Mintz case QED_PCI_ETH: 511408cc1fSYuval Mintz p_ramrod->personality = PERSONALITY_ETH; 521fe614d1SYuval Mintz break; 531fe614d1SYuval Mintz case QED_PCI_ETH_ROCE: 541fe614d1SYuval Mintz p_ramrod->personality = PERSONALITY_RDMA_AND_ETH; 551fe614d1SYuval Mintz break; 561fe614d1SYuval Mintz default: 571fe614d1SYuval Mintz DP_NOTICE(p_hwfn, "Unknown VF personality %d\n", 581fe614d1SYuval Mintz p_hwfn->hw_info.personality); 591fe614d1SYuval Mintz return -EINVAL; 601fe614d1SYuval Mintz } 611fe614d1SYuval Mintz 621fe614d1SYuval Mintz fp_minor = p_vf->acquire.vfdev_info.eth_fp_hsi_minor; 631fe614d1SYuval Mintz if (fp_minor > ETH_HSI_VER_MINOR) { 641fe614d1SYuval Mintz DP_VERBOSE(p_hwfn, 651fe614d1SYuval Mintz QED_MSG_IOV, 661fe614d1SYuval Mintz "VF [%d] - Requested fp hsi %02x.%02x which is slightly newer than PF's %02x.%02x; Configuring PFs version\n", 671fe614d1SYuval Mintz p_vf->abs_vf_id, 681fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, 691fe614d1SYuval Mintz fp_minor, ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR); 701fe614d1SYuval Mintz fp_minor = ETH_HSI_VER_MINOR; 711fe614d1SYuval Mintz } 721fe614d1SYuval Mintz 73351a4dedSYuval Mintz p_ramrod->hsi_fp_ver.major_ver_arr[ETH_VER_KEY] = ETH_HSI_VER_MAJOR; 741fe614d1SYuval Mintz p_ramrod->hsi_fp_ver.minor_ver_arr[ETH_VER_KEY] = fp_minor; 751fe614d1SYuval Mintz 761fe614d1SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 771fe614d1SYuval Mintz "VF[%d] - Starting using HSI %02x.%02x\n", 781fe614d1SYuval Mintz p_vf->abs_vf_id, ETH_HSI_VER_MAJOR, fp_minor); 791408cc1fSYuval Mintz 801408cc1fSYuval Mintz return qed_spq_post(p_hwfn, p_ent, NULL); 811408cc1fSYuval Mintz } 821408cc1fSYuval Mintz 830b55e27dSYuval Mintz static int qed_sp_vf_stop(struct qed_hwfn *p_hwfn, 840b55e27dSYuval Mintz u32 concrete_vfid, u16 opaque_vfid) 850b55e27dSYuval Mintz { 860b55e27dSYuval Mintz struct vf_stop_ramrod_data *p_ramrod = NULL; 870b55e27dSYuval Mintz struct qed_spq_entry *p_ent = NULL; 880b55e27dSYuval Mintz struct qed_sp_init_data init_data; 890b55e27dSYuval Mintz int rc = -EINVAL; 900b55e27dSYuval Mintz 910b55e27dSYuval Mintz /* Get SPQ entry */ 920b55e27dSYuval Mintz memset(&init_data, 0, sizeof(init_data)); 930b55e27dSYuval Mintz init_data.cid = qed_spq_get_cid(p_hwfn); 940b55e27dSYuval Mintz init_data.opaque_fid = opaque_vfid; 950b55e27dSYuval Mintz init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 960b55e27dSYuval Mintz 970b55e27dSYuval Mintz rc = qed_sp_init_request(p_hwfn, &p_ent, 980b55e27dSYuval Mintz COMMON_RAMROD_VF_STOP, 990b55e27dSYuval Mintz PROTOCOLID_COMMON, &init_data); 1000b55e27dSYuval Mintz if (rc) 1010b55e27dSYuval Mintz return rc; 1020b55e27dSYuval Mintz 1030b55e27dSYuval Mintz p_ramrod = &p_ent->ramrod.vf_stop; 1040b55e27dSYuval Mintz 1050b55e27dSYuval Mintz p_ramrod->vf_id = GET_FIELD(concrete_vfid, PXP_CONCRETE_FID_VFID); 1060b55e27dSYuval Mintz 1070b55e27dSYuval Mintz return qed_spq_post(p_hwfn, p_ent, NULL); 1080b55e27dSYuval Mintz } 1090b55e27dSYuval Mintz 11032a47e72SYuval Mintz bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn, 11132a47e72SYuval Mintz int rel_vf_id, bool b_enabled_only) 11232a47e72SYuval Mintz { 11332a47e72SYuval Mintz if (!p_hwfn->pf_iov_info) { 11432a47e72SYuval Mintz DP_NOTICE(p_hwfn->cdev, "No iov info\n"); 11532a47e72SYuval Mintz return false; 11632a47e72SYuval Mintz } 11732a47e72SYuval Mintz 11832a47e72SYuval Mintz if ((rel_vf_id >= p_hwfn->cdev->p_iov_info->total_vfs) || 11932a47e72SYuval Mintz (rel_vf_id < 0)) 12032a47e72SYuval Mintz return false; 12132a47e72SYuval Mintz 12232a47e72SYuval Mintz if ((!p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_init) && 12332a47e72SYuval Mintz b_enabled_only) 12432a47e72SYuval Mintz return false; 12532a47e72SYuval Mintz 12632a47e72SYuval Mintz return true; 12732a47e72SYuval Mintz } 12832a47e72SYuval Mintz 12937bff2b9SYuval Mintz static struct qed_vf_info *qed_iov_get_vf_info(struct qed_hwfn *p_hwfn, 13037bff2b9SYuval Mintz u16 relative_vf_id, 13137bff2b9SYuval Mintz bool b_enabled_only) 13237bff2b9SYuval Mintz { 13337bff2b9SYuval Mintz struct qed_vf_info *vf = NULL; 13437bff2b9SYuval Mintz 13537bff2b9SYuval Mintz if (!p_hwfn->pf_iov_info) { 13637bff2b9SYuval Mintz DP_NOTICE(p_hwfn->cdev, "No iov info\n"); 13737bff2b9SYuval Mintz return NULL; 13837bff2b9SYuval Mintz } 13937bff2b9SYuval Mintz 14037bff2b9SYuval Mintz if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only)) 14137bff2b9SYuval Mintz vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id]; 14237bff2b9SYuval Mintz else 14337bff2b9SYuval Mintz DP_ERR(p_hwfn, "qed_iov_get_vf_info: VF[%d] is not enabled\n", 14437bff2b9SYuval Mintz relative_vf_id); 14537bff2b9SYuval Mintz 14637bff2b9SYuval Mintz return vf; 14737bff2b9SYuval Mintz } 14837bff2b9SYuval Mintz 14941086467SYuval Mintz static bool qed_iov_validate_rxq(struct qed_hwfn *p_hwfn, 15041086467SYuval Mintz struct qed_vf_info *p_vf, u16 rx_qid) 15141086467SYuval Mintz { 15241086467SYuval Mintz if (rx_qid >= p_vf->num_rxqs) 15341086467SYuval Mintz DP_VERBOSE(p_hwfn, 15441086467SYuval Mintz QED_MSG_IOV, 15541086467SYuval Mintz "VF[0x%02x] - can't touch Rx queue[%04x]; Only 0x%04x are allocated\n", 15641086467SYuval Mintz p_vf->abs_vf_id, rx_qid, p_vf->num_rxqs); 15741086467SYuval Mintz return rx_qid < p_vf->num_rxqs; 15841086467SYuval Mintz } 15941086467SYuval Mintz 16041086467SYuval Mintz static bool qed_iov_validate_txq(struct qed_hwfn *p_hwfn, 16141086467SYuval Mintz struct qed_vf_info *p_vf, u16 tx_qid) 16241086467SYuval Mintz { 16341086467SYuval Mintz if (tx_qid >= p_vf->num_txqs) 16441086467SYuval Mintz DP_VERBOSE(p_hwfn, 16541086467SYuval Mintz QED_MSG_IOV, 16641086467SYuval Mintz "VF[0x%02x] - can't touch Tx queue[%04x]; Only 0x%04x are allocated\n", 16741086467SYuval Mintz p_vf->abs_vf_id, tx_qid, p_vf->num_txqs); 16841086467SYuval Mintz return tx_qid < p_vf->num_txqs; 16941086467SYuval Mintz } 17041086467SYuval Mintz 17141086467SYuval Mintz static bool qed_iov_validate_sb(struct qed_hwfn *p_hwfn, 17241086467SYuval Mintz struct qed_vf_info *p_vf, u16 sb_idx) 17341086467SYuval Mintz { 17441086467SYuval Mintz int i; 17541086467SYuval Mintz 17641086467SYuval Mintz for (i = 0; i < p_vf->num_sbs; i++) 17741086467SYuval Mintz if (p_vf->igu_sbs[i] == sb_idx) 17841086467SYuval Mintz return true; 17941086467SYuval Mintz 18041086467SYuval Mintz DP_VERBOSE(p_hwfn, 18141086467SYuval Mintz QED_MSG_IOV, 18241086467SYuval Mintz "VF[0%02x] - tried using sb_idx %04x which doesn't exist as one of its 0x%02x SBs\n", 18341086467SYuval Mintz p_vf->abs_vf_id, sb_idx, p_vf->num_sbs); 18441086467SYuval Mintz 18541086467SYuval Mintz return false; 18641086467SYuval Mintz } 18741086467SYuval Mintz 18836558c3dSYuval Mintz int qed_iov_post_vf_bulletin(struct qed_hwfn *p_hwfn, 18936558c3dSYuval Mintz int vfid, struct qed_ptt *p_ptt) 19036558c3dSYuval Mintz { 19136558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin; 19236558c3dSYuval Mintz int crc_size = sizeof(p_bulletin->crc); 19336558c3dSYuval Mintz struct qed_dmae_params params; 19436558c3dSYuval Mintz struct qed_vf_info *p_vf; 19536558c3dSYuval Mintz 19636558c3dSYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 19736558c3dSYuval Mintz if (!p_vf) 19836558c3dSYuval Mintz return -EINVAL; 19936558c3dSYuval Mintz 20036558c3dSYuval Mintz if (!p_vf->vf_bulletin) 20136558c3dSYuval Mintz return -EINVAL; 20236558c3dSYuval Mintz 20336558c3dSYuval Mintz p_bulletin = p_vf->bulletin.p_virt; 20436558c3dSYuval Mintz 20536558c3dSYuval Mintz /* Increment bulletin board version and compute crc */ 20636558c3dSYuval Mintz p_bulletin->version++; 20736558c3dSYuval Mintz p_bulletin->crc = crc32(0, (u8 *)p_bulletin + crc_size, 20836558c3dSYuval Mintz p_vf->bulletin.size - crc_size); 20936558c3dSYuval Mintz 21036558c3dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 21136558c3dSYuval Mintz "Posting Bulletin 0x%08x to VF[%d] (CRC 0x%08x)\n", 21236558c3dSYuval Mintz p_bulletin->version, p_vf->relative_vf_id, p_bulletin->crc); 21336558c3dSYuval Mintz 21436558c3dSYuval Mintz /* propagate bulletin board via dmae to vm memory */ 21536558c3dSYuval Mintz memset(¶ms, 0, sizeof(params)); 21636558c3dSYuval Mintz params.flags = QED_DMAE_FLAG_VF_DST; 21736558c3dSYuval Mintz params.dst_vfid = p_vf->abs_vf_id; 21836558c3dSYuval Mintz return qed_dmae_host2host(p_hwfn, p_ptt, p_vf->bulletin.phys, 21936558c3dSYuval Mintz p_vf->vf_bulletin, p_vf->bulletin.size / 4, 22036558c3dSYuval Mintz ¶ms); 22136558c3dSYuval Mintz } 22236558c3dSYuval Mintz 22332a47e72SYuval Mintz static int qed_iov_pci_cfg_info(struct qed_dev *cdev) 22432a47e72SYuval Mintz { 22532a47e72SYuval Mintz struct qed_hw_sriov_info *iov = cdev->p_iov_info; 22632a47e72SYuval Mintz int pos = iov->pos; 22732a47e72SYuval Mintz 22832a47e72SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, "sriov ext pos %d\n", pos); 22932a47e72SYuval Mintz pci_read_config_word(cdev->pdev, pos + PCI_SRIOV_CTRL, &iov->ctrl); 23032a47e72SYuval Mintz 23132a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 23232a47e72SYuval Mintz pos + PCI_SRIOV_TOTAL_VF, &iov->total_vfs); 23332a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 23432a47e72SYuval Mintz pos + PCI_SRIOV_INITIAL_VF, &iov->initial_vfs); 23532a47e72SYuval Mintz 23632a47e72SYuval Mintz pci_read_config_word(cdev->pdev, pos + PCI_SRIOV_NUM_VF, &iov->num_vfs); 23732a47e72SYuval Mintz if (iov->num_vfs) { 23832a47e72SYuval Mintz DP_VERBOSE(cdev, 23932a47e72SYuval Mintz QED_MSG_IOV, 24032a47e72SYuval Mintz "Number of VFs are already set to non-zero value. Ignoring PCI configuration value\n"); 24132a47e72SYuval Mintz iov->num_vfs = 0; 24232a47e72SYuval Mintz } 24332a47e72SYuval Mintz 24432a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 24532a47e72SYuval Mintz pos + PCI_SRIOV_VF_OFFSET, &iov->offset); 24632a47e72SYuval Mintz 24732a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 24832a47e72SYuval Mintz pos + PCI_SRIOV_VF_STRIDE, &iov->stride); 24932a47e72SYuval Mintz 25032a47e72SYuval Mintz pci_read_config_word(cdev->pdev, 25132a47e72SYuval Mintz pos + PCI_SRIOV_VF_DID, &iov->vf_device_id); 25232a47e72SYuval Mintz 25332a47e72SYuval Mintz pci_read_config_dword(cdev->pdev, 25432a47e72SYuval Mintz pos + PCI_SRIOV_SUP_PGSIZE, &iov->pgsz); 25532a47e72SYuval Mintz 25632a47e72SYuval Mintz pci_read_config_dword(cdev->pdev, pos + PCI_SRIOV_CAP, &iov->cap); 25732a47e72SYuval Mintz 25832a47e72SYuval Mintz pci_read_config_byte(cdev->pdev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); 25932a47e72SYuval Mintz 26032a47e72SYuval Mintz DP_VERBOSE(cdev, 26132a47e72SYuval Mintz QED_MSG_IOV, 26232a47e72SYuval 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", 26332a47e72SYuval Mintz iov->nres, 26432a47e72SYuval Mintz iov->cap, 26532a47e72SYuval Mintz iov->ctrl, 26632a47e72SYuval Mintz iov->total_vfs, 26732a47e72SYuval Mintz iov->initial_vfs, 26832a47e72SYuval Mintz iov->nr_virtfn, iov->offset, iov->stride, iov->pgsz); 26932a47e72SYuval Mintz 27032a47e72SYuval Mintz /* Some sanity checks */ 27132a47e72SYuval Mintz if (iov->num_vfs > NUM_OF_VFS(cdev) || 27232a47e72SYuval Mintz iov->total_vfs > NUM_OF_VFS(cdev)) { 27332a47e72SYuval Mintz /* This can happen only due to a bug. In this case we set 27432a47e72SYuval Mintz * num_vfs to zero to avoid memory corruption in the code that 27532a47e72SYuval Mintz * assumes max number of vfs 27632a47e72SYuval Mintz */ 27732a47e72SYuval Mintz DP_NOTICE(cdev, 27832a47e72SYuval Mintz "IOV: Unexpected number of vfs set: %d setting num_vf to zero\n", 27932a47e72SYuval Mintz iov->num_vfs); 28032a47e72SYuval Mintz 28132a47e72SYuval Mintz iov->num_vfs = 0; 28232a47e72SYuval Mintz iov->total_vfs = 0; 28332a47e72SYuval Mintz } 28432a47e72SYuval Mintz 28532a47e72SYuval Mintz return 0; 28632a47e72SYuval Mintz } 28732a47e72SYuval Mintz 28832a47e72SYuval Mintz static void qed_iov_clear_vf_igu_blocks(struct qed_hwfn *p_hwfn, 28932a47e72SYuval Mintz struct qed_ptt *p_ptt) 29032a47e72SYuval Mintz { 29132a47e72SYuval Mintz struct qed_igu_block *p_sb; 29232a47e72SYuval Mintz u16 sb_id; 29332a47e72SYuval Mintz u32 val; 29432a47e72SYuval Mintz 29532a47e72SYuval Mintz if (!p_hwfn->hw_info.p_igu_info) { 29632a47e72SYuval Mintz DP_ERR(p_hwfn, 29732a47e72SYuval Mintz "qed_iov_clear_vf_igu_blocks IGU Info not initialized\n"); 29832a47e72SYuval Mintz return; 29932a47e72SYuval Mintz } 30032a47e72SYuval Mintz 30132a47e72SYuval Mintz for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); 30232a47e72SYuval Mintz sb_id++) { 30332a47e72SYuval Mintz p_sb = &p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks[sb_id]; 30432a47e72SYuval Mintz if ((p_sb->status & QED_IGU_STATUS_FREE) && 30532a47e72SYuval Mintz !(p_sb->status & QED_IGU_STATUS_PF)) { 30632a47e72SYuval Mintz val = qed_rd(p_hwfn, p_ptt, 30732a47e72SYuval Mintz IGU_REG_MAPPING_MEMORY + sb_id * 4); 30832a47e72SYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0); 30932a47e72SYuval Mintz qed_wr(p_hwfn, p_ptt, 31032a47e72SYuval Mintz IGU_REG_MAPPING_MEMORY + 4 * sb_id, val); 31132a47e72SYuval Mintz } 31232a47e72SYuval Mintz } 31332a47e72SYuval Mintz } 31432a47e72SYuval Mintz 31532a47e72SYuval Mintz static void qed_iov_setup_vfdb(struct qed_hwfn *p_hwfn) 31632a47e72SYuval Mintz { 31732a47e72SYuval Mintz struct qed_hw_sriov_info *p_iov = p_hwfn->cdev->p_iov_info; 31832a47e72SYuval Mintz struct qed_pf_iov *p_iov_info = p_hwfn->pf_iov_info; 31932a47e72SYuval Mintz struct qed_bulletin_content *p_bulletin_virt; 32032a47e72SYuval Mintz dma_addr_t req_p, rply_p, bulletin_p; 32132a47e72SYuval Mintz union pfvf_tlvs *p_reply_virt_addr; 32232a47e72SYuval Mintz union vfpf_tlvs *p_req_virt_addr; 32332a47e72SYuval Mintz u8 idx = 0; 32432a47e72SYuval Mintz 32532a47e72SYuval Mintz memset(p_iov_info->vfs_array, 0, sizeof(p_iov_info->vfs_array)); 32632a47e72SYuval Mintz 32732a47e72SYuval Mintz p_req_virt_addr = p_iov_info->mbx_msg_virt_addr; 32832a47e72SYuval Mintz req_p = p_iov_info->mbx_msg_phys_addr; 32932a47e72SYuval Mintz p_reply_virt_addr = p_iov_info->mbx_reply_virt_addr; 33032a47e72SYuval Mintz rply_p = p_iov_info->mbx_reply_phys_addr; 33132a47e72SYuval Mintz p_bulletin_virt = p_iov_info->p_bulletins; 33232a47e72SYuval Mintz bulletin_p = p_iov_info->bulletins_phys; 33332a47e72SYuval Mintz if (!p_req_virt_addr || !p_reply_virt_addr || !p_bulletin_virt) { 33432a47e72SYuval Mintz DP_ERR(p_hwfn, 33532a47e72SYuval Mintz "qed_iov_setup_vfdb called without allocating mem first\n"); 33632a47e72SYuval Mintz return; 33732a47e72SYuval Mintz } 33832a47e72SYuval Mintz 33932a47e72SYuval Mintz for (idx = 0; idx < p_iov->total_vfs; idx++) { 34032a47e72SYuval Mintz struct qed_vf_info *vf = &p_iov_info->vfs_array[idx]; 34132a47e72SYuval Mintz u32 concrete; 34232a47e72SYuval Mintz 34332a47e72SYuval Mintz vf->vf_mbx.req_virt = p_req_virt_addr + idx; 34432a47e72SYuval Mintz vf->vf_mbx.req_phys = req_p + idx * sizeof(union vfpf_tlvs); 34532a47e72SYuval Mintz vf->vf_mbx.reply_virt = p_reply_virt_addr + idx; 34632a47e72SYuval Mintz vf->vf_mbx.reply_phys = rply_p + idx * sizeof(union pfvf_tlvs); 34732a47e72SYuval Mintz 34832a47e72SYuval Mintz vf->state = VF_STOPPED; 34932a47e72SYuval Mintz vf->b_init = false; 35032a47e72SYuval Mintz 35132a47e72SYuval Mintz vf->bulletin.phys = idx * 35232a47e72SYuval Mintz sizeof(struct qed_bulletin_content) + 35332a47e72SYuval Mintz bulletin_p; 35432a47e72SYuval Mintz vf->bulletin.p_virt = p_bulletin_virt + idx; 35532a47e72SYuval Mintz vf->bulletin.size = sizeof(struct qed_bulletin_content); 35632a47e72SYuval Mintz 35732a47e72SYuval Mintz vf->relative_vf_id = idx; 35832a47e72SYuval Mintz vf->abs_vf_id = idx + p_iov->first_vf_in_pf; 35932a47e72SYuval Mintz concrete = qed_vfid_to_concrete(p_hwfn, vf->abs_vf_id); 36032a47e72SYuval Mintz vf->concrete_fid = concrete; 36132a47e72SYuval Mintz vf->opaque_fid = (p_hwfn->hw_info.opaque_fid & 0xff) | 36232a47e72SYuval Mintz (vf->abs_vf_id << 8); 36332a47e72SYuval Mintz vf->vport_id = idx + 1; 3641cf2b1a9SYuval Mintz 3651cf2b1a9SYuval Mintz vf->num_mac_filters = QED_ETH_VF_NUM_MAC_FILTERS; 3661cf2b1a9SYuval Mintz vf->num_vlan_filters = QED_ETH_VF_NUM_VLAN_FILTERS; 36732a47e72SYuval Mintz } 36832a47e72SYuval Mintz } 36932a47e72SYuval Mintz 37032a47e72SYuval Mintz static int qed_iov_allocate_vfdb(struct qed_hwfn *p_hwfn) 37132a47e72SYuval Mintz { 37232a47e72SYuval Mintz struct qed_pf_iov *p_iov_info = p_hwfn->pf_iov_info; 37332a47e72SYuval Mintz void **p_v_addr; 37432a47e72SYuval Mintz u16 num_vfs = 0; 37532a47e72SYuval Mintz 37632a47e72SYuval Mintz num_vfs = p_hwfn->cdev->p_iov_info->total_vfs; 37732a47e72SYuval Mintz 37832a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 37932a47e72SYuval Mintz "qed_iov_allocate_vfdb for %d VFs\n", num_vfs); 38032a47e72SYuval Mintz 38132a47e72SYuval Mintz /* Allocate PF Mailbox buffer (per-VF) */ 38232a47e72SYuval Mintz p_iov_info->mbx_msg_size = sizeof(union vfpf_tlvs) * num_vfs; 38332a47e72SYuval Mintz p_v_addr = &p_iov_info->mbx_msg_virt_addr; 38432a47e72SYuval Mintz *p_v_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 38532a47e72SYuval Mintz p_iov_info->mbx_msg_size, 38632a47e72SYuval Mintz &p_iov_info->mbx_msg_phys_addr, 38732a47e72SYuval Mintz GFP_KERNEL); 38832a47e72SYuval Mintz if (!*p_v_addr) 38932a47e72SYuval Mintz return -ENOMEM; 39032a47e72SYuval Mintz 39132a47e72SYuval Mintz /* Allocate PF Mailbox Reply buffer (per-VF) */ 39232a47e72SYuval Mintz p_iov_info->mbx_reply_size = sizeof(union pfvf_tlvs) * num_vfs; 39332a47e72SYuval Mintz p_v_addr = &p_iov_info->mbx_reply_virt_addr; 39432a47e72SYuval Mintz *p_v_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 39532a47e72SYuval Mintz p_iov_info->mbx_reply_size, 39632a47e72SYuval Mintz &p_iov_info->mbx_reply_phys_addr, 39732a47e72SYuval Mintz GFP_KERNEL); 39832a47e72SYuval Mintz if (!*p_v_addr) 39932a47e72SYuval Mintz return -ENOMEM; 40032a47e72SYuval Mintz 40132a47e72SYuval Mintz p_iov_info->bulletins_size = sizeof(struct qed_bulletin_content) * 40232a47e72SYuval Mintz num_vfs; 40332a47e72SYuval Mintz p_v_addr = &p_iov_info->p_bulletins; 40432a47e72SYuval Mintz *p_v_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 40532a47e72SYuval Mintz p_iov_info->bulletins_size, 40632a47e72SYuval Mintz &p_iov_info->bulletins_phys, 40732a47e72SYuval Mintz GFP_KERNEL); 40832a47e72SYuval Mintz if (!*p_v_addr) 40932a47e72SYuval Mintz return -ENOMEM; 41032a47e72SYuval Mintz 41132a47e72SYuval Mintz DP_VERBOSE(p_hwfn, 41232a47e72SYuval Mintz QED_MSG_IOV, 41332a47e72SYuval Mintz "PF's Requests mailbox [%p virt 0x%llx phys], Response mailbox [%p virt 0x%llx phys] Bulletins [%p virt 0x%llx phys]\n", 41432a47e72SYuval Mintz p_iov_info->mbx_msg_virt_addr, 41532a47e72SYuval Mintz (u64) p_iov_info->mbx_msg_phys_addr, 41632a47e72SYuval Mintz p_iov_info->mbx_reply_virt_addr, 41732a47e72SYuval Mintz (u64) p_iov_info->mbx_reply_phys_addr, 41832a47e72SYuval Mintz p_iov_info->p_bulletins, (u64) p_iov_info->bulletins_phys); 41932a47e72SYuval Mintz 42032a47e72SYuval Mintz return 0; 42132a47e72SYuval Mintz } 42232a47e72SYuval Mintz 42332a47e72SYuval Mintz static void qed_iov_free_vfdb(struct qed_hwfn *p_hwfn) 42432a47e72SYuval Mintz { 42532a47e72SYuval Mintz struct qed_pf_iov *p_iov_info = p_hwfn->pf_iov_info; 42632a47e72SYuval Mintz 42732a47e72SYuval Mintz if (p_hwfn->pf_iov_info->mbx_msg_virt_addr) 42832a47e72SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 42932a47e72SYuval Mintz p_iov_info->mbx_msg_size, 43032a47e72SYuval Mintz p_iov_info->mbx_msg_virt_addr, 43132a47e72SYuval Mintz p_iov_info->mbx_msg_phys_addr); 43232a47e72SYuval Mintz 43332a47e72SYuval Mintz if (p_hwfn->pf_iov_info->mbx_reply_virt_addr) 43432a47e72SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 43532a47e72SYuval Mintz p_iov_info->mbx_reply_size, 43632a47e72SYuval Mintz p_iov_info->mbx_reply_virt_addr, 43732a47e72SYuval Mintz p_iov_info->mbx_reply_phys_addr); 43832a47e72SYuval Mintz 43932a47e72SYuval Mintz if (p_iov_info->p_bulletins) 44032a47e72SYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 44132a47e72SYuval Mintz p_iov_info->bulletins_size, 44232a47e72SYuval Mintz p_iov_info->p_bulletins, 44332a47e72SYuval Mintz p_iov_info->bulletins_phys); 44432a47e72SYuval Mintz } 44532a47e72SYuval Mintz 44632a47e72SYuval Mintz int qed_iov_alloc(struct qed_hwfn *p_hwfn) 44732a47e72SYuval Mintz { 44832a47e72SYuval Mintz struct qed_pf_iov *p_sriov; 44932a47e72SYuval Mintz 45032a47e72SYuval Mintz if (!IS_PF_SRIOV(p_hwfn)) { 45132a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 45232a47e72SYuval Mintz "No SR-IOV - no need for IOV db\n"); 45332a47e72SYuval Mintz return 0; 45432a47e72SYuval Mintz } 45532a47e72SYuval Mintz 45632a47e72SYuval Mintz p_sriov = kzalloc(sizeof(*p_sriov), GFP_KERNEL); 45732a47e72SYuval Mintz if (!p_sriov) { 45832a47e72SYuval Mintz DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sriov'\n"); 45932a47e72SYuval Mintz return -ENOMEM; 46032a47e72SYuval Mintz } 46132a47e72SYuval Mintz 46232a47e72SYuval Mintz p_hwfn->pf_iov_info = p_sriov; 46332a47e72SYuval Mintz 46432a47e72SYuval Mintz return qed_iov_allocate_vfdb(p_hwfn); 46532a47e72SYuval Mintz } 46632a47e72SYuval Mintz 46732a47e72SYuval Mintz void qed_iov_setup(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 46832a47e72SYuval Mintz { 46932a47e72SYuval Mintz if (!IS_PF_SRIOV(p_hwfn) || !IS_PF_SRIOV_ALLOC(p_hwfn)) 47032a47e72SYuval Mintz return; 47132a47e72SYuval Mintz 47232a47e72SYuval Mintz qed_iov_setup_vfdb(p_hwfn); 47332a47e72SYuval Mintz qed_iov_clear_vf_igu_blocks(p_hwfn, p_ptt); 47432a47e72SYuval Mintz } 47532a47e72SYuval Mintz 47632a47e72SYuval Mintz void qed_iov_free(struct qed_hwfn *p_hwfn) 47732a47e72SYuval Mintz { 47832a47e72SYuval Mintz if (IS_PF_SRIOV_ALLOC(p_hwfn)) { 47932a47e72SYuval Mintz qed_iov_free_vfdb(p_hwfn); 48032a47e72SYuval Mintz kfree(p_hwfn->pf_iov_info); 48132a47e72SYuval Mintz } 48232a47e72SYuval Mintz } 48332a47e72SYuval Mintz 48432a47e72SYuval Mintz void qed_iov_free_hw_info(struct qed_dev *cdev) 48532a47e72SYuval Mintz { 48632a47e72SYuval Mintz kfree(cdev->p_iov_info); 48732a47e72SYuval Mintz cdev->p_iov_info = NULL; 48832a47e72SYuval Mintz } 48932a47e72SYuval Mintz 49032a47e72SYuval Mintz int qed_iov_hw_info(struct qed_hwfn *p_hwfn) 49132a47e72SYuval Mintz { 49232a47e72SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev; 49332a47e72SYuval Mintz int pos; 49432a47e72SYuval Mintz int rc; 49532a47e72SYuval Mintz 4961408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev)) 4971408cc1fSYuval Mintz return 0; 4981408cc1fSYuval Mintz 49932a47e72SYuval Mintz /* Learn the PCI configuration */ 50032a47e72SYuval Mintz pos = pci_find_ext_capability(p_hwfn->cdev->pdev, 50132a47e72SYuval Mintz PCI_EXT_CAP_ID_SRIOV); 50232a47e72SYuval Mintz if (!pos) { 50332a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "No PCIe IOV support\n"); 50432a47e72SYuval Mintz return 0; 50532a47e72SYuval Mintz } 50632a47e72SYuval Mintz 50732a47e72SYuval Mintz /* Allocate a new struct for IOV information */ 50832a47e72SYuval Mintz cdev->p_iov_info = kzalloc(sizeof(*cdev->p_iov_info), GFP_KERNEL); 50932a47e72SYuval Mintz if (!cdev->p_iov_info) { 51032a47e72SYuval Mintz DP_NOTICE(p_hwfn, "Can't support IOV due to lack of memory\n"); 51132a47e72SYuval Mintz return -ENOMEM; 51232a47e72SYuval Mintz } 51332a47e72SYuval Mintz cdev->p_iov_info->pos = pos; 51432a47e72SYuval Mintz 51532a47e72SYuval Mintz rc = qed_iov_pci_cfg_info(cdev); 51632a47e72SYuval Mintz if (rc) 51732a47e72SYuval Mintz return rc; 51832a47e72SYuval Mintz 51932a47e72SYuval Mintz /* We want PF IOV to be synonemous with the existance of p_iov_info; 52032a47e72SYuval Mintz * In case the capability is published but there are no VFs, simply 52132a47e72SYuval Mintz * de-allocate the struct. 52232a47e72SYuval Mintz */ 52332a47e72SYuval Mintz if (!cdev->p_iov_info->total_vfs) { 52432a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 52532a47e72SYuval Mintz "IOV capabilities, but no VFs are published\n"); 52632a47e72SYuval Mintz kfree(cdev->p_iov_info); 52732a47e72SYuval Mintz cdev->p_iov_info = NULL; 52832a47e72SYuval Mintz return 0; 52932a47e72SYuval Mintz } 53032a47e72SYuval Mintz 53132a47e72SYuval Mintz /* Calculate the first VF index - this is a bit tricky; Basically, 53232a47e72SYuval Mintz * VFs start at offset 16 relative to PF0, and 2nd engine VFs begin 53332a47e72SYuval Mintz * after the first engine's VFs. 53432a47e72SYuval Mintz */ 53532a47e72SYuval Mintz cdev->p_iov_info->first_vf_in_pf = p_hwfn->cdev->p_iov_info->offset + 53632a47e72SYuval Mintz p_hwfn->abs_pf_id - 16; 53732a47e72SYuval Mintz if (QED_PATH_ID(p_hwfn)) 53832a47e72SYuval Mintz cdev->p_iov_info->first_vf_in_pf -= MAX_NUM_VFS_BB; 53932a47e72SYuval Mintz 54032a47e72SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 54132a47e72SYuval Mintz "First VF in hwfn 0x%08x\n", 54232a47e72SYuval Mintz cdev->p_iov_info->first_vf_in_pf); 54332a47e72SYuval Mintz 54432a47e72SYuval Mintz return 0; 54532a47e72SYuval Mintz } 54632a47e72SYuval Mintz 54737bff2b9SYuval Mintz static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid) 54837bff2b9SYuval Mintz { 54937bff2b9SYuval Mintz /* Check PF supports sriov */ 550b0409fa0SYuval Mintz if (IS_VF(p_hwfn->cdev) || !IS_QED_SRIOV(p_hwfn->cdev) || 551b0409fa0SYuval Mintz !IS_PF_SRIOV_ALLOC(p_hwfn)) 55237bff2b9SYuval Mintz return false; 55337bff2b9SYuval Mintz 55437bff2b9SYuval Mintz /* Check VF validity */ 555b0409fa0SYuval Mintz if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true)) 55637bff2b9SYuval Mintz return false; 55737bff2b9SYuval Mintz 55837bff2b9SYuval Mintz return true; 55937bff2b9SYuval Mintz } 56037bff2b9SYuval Mintz 5610b55e27dSYuval Mintz static void qed_iov_set_vf_to_disable(struct qed_dev *cdev, 5620b55e27dSYuval Mintz u16 rel_vf_id, u8 to_disable) 5630b55e27dSYuval Mintz { 5640b55e27dSYuval Mintz struct qed_vf_info *vf; 5650b55e27dSYuval Mintz int i; 5660b55e27dSYuval Mintz 5670b55e27dSYuval Mintz for_each_hwfn(cdev, i) { 5680b55e27dSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 5690b55e27dSYuval Mintz 5700b55e27dSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, false); 5710b55e27dSYuval Mintz if (!vf) 5720b55e27dSYuval Mintz continue; 5730b55e27dSYuval Mintz 5740b55e27dSYuval Mintz vf->to_disable = to_disable; 5750b55e27dSYuval Mintz } 5760b55e27dSYuval Mintz } 5770b55e27dSYuval Mintz 5780b55e27dSYuval Mintz void qed_iov_set_vfs_to_disable(struct qed_dev *cdev, u8 to_disable) 5790b55e27dSYuval Mintz { 5800b55e27dSYuval Mintz u16 i; 5810b55e27dSYuval Mintz 5820b55e27dSYuval Mintz if (!IS_QED_SRIOV(cdev)) 5830b55e27dSYuval Mintz return; 5840b55e27dSYuval Mintz 5850b55e27dSYuval Mintz for (i = 0; i < cdev->p_iov_info->total_vfs; i++) 5860b55e27dSYuval Mintz qed_iov_set_vf_to_disable(cdev, i, to_disable); 5870b55e27dSYuval Mintz } 5880b55e27dSYuval Mintz 5891408cc1fSYuval Mintz static void qed_iov_vf_pglue_clear_err(struct qed_hwfn *p_hwfn, 5901408cc1fSYuval Mintz struct qed_ptt *p_ptt, u8 abs_vfid) 5911408cc1fSYuval Mintz { 5921408cc1fSYuval Mintz qed_wr(p_hwfn, p_ptt, 5931408cc1fSYuval Mintz PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR + (abs_vfid >> 5) * 4, 5941408cc1fSYuval Mintz 1 << (abs_vfid & 0x1f)); 5951408cc1fSYuval Mintz } 5961408cc1fSYuval Mintz 597dacd88d6SYuval Mintz static void qed_iov_vf_igu_reset(struct qed_hwfn *p_hwfn, 598dacd88d6SYuval Mintz struct qed_ptt *p_ptt, struct qed_vf_info *vf) 599dacd88d6SYuval Mintz { 600dacd88d6SYuval Mintz int i; 601dacd88d6SYuval Mintz 602dacd88d6SYuval Mintz /* Set VF masks and configuration - pretend */ 603dacd88d6SYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) vf->concrete_fid); 604dacd88d6SYuval Mintz 605dacd88d6SYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_STATISTIC_NUM_VF_MSG_SENT, 0); 606dacd88d6SYuval Mintz 607dacd88d6SYuval Mintz /* unpretend */ 608dacd88d6SYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 609dacd88d6SYuval Mintz 610dacd88d6SYuval Mintz /* iterate over all queues, clear sb consumer */ 611b2b897ebSYuval Mintz for (i = 0; i < vf->num_sbs; i++) 612b2b897ebSYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, 613b2b897ebSYuval Mintz vf->igu_sbs[i], 614b2b897ebSYuval Mintz vf->opaque_fid, true); 615dacd88d6SYuval Mintz } 616dacd88d6SYuval Mintz 6170b55e27dSYuval Mintz static void qed_iov_vf_igu_set_int(struct qed_hwfn *p_hwfn, 6180b55e27dSYuval Mintz struct qed_ptt *p_ptt, 6190b55e27dSYuval Mintz struct qed_vf_info *vf, bool enable) 6200b55e27dSYuval Mintz { 6210b55e27dSYuval Mintz u32 igu_vf_conf; 6220b55e27dSYuval Mintz 6230b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) vf->concrete_fid); 6240b55e27dSYuval Mintz 6250b55e27dSYuval Mintz igu_vf_conf = qed_rd(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION); 6260b55e27dSYuval Mintz 6270b55e27dSYuval Mintz if (enable) 6280b55e27dSYuval Mintz igu_vf_conf |= IGU_VF_CONF_MSI_MSIX_EN; 6290b55e27dSYuval Mintz else 6300b55e27dSYuval Mintz igu_vf_conf &= ~IGU_VF_CONF_MSI_MSIX_EN; 6310b55e27dSYuval Mintz 6320b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION, igu_vf_conf); 6330b55e27dSYuval Mintz 6340b55e27dSYuval Mintz /* unpretend */ 6350b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 6360b55e27dSYuval Mintz } 6370b55e27dSYuval Mintz 6381408cc1fSYuval Mintz static int qed_iov_enable_vf_access(struct qed_hwfn *p_hwfn, 6391408cc1fSYuval Mintz struct qed_ptt *p_ptt, 6401408cc1fSYuval Mintz struct qed_vf_info *vf) 6411408cc1fSYuval Mintz { 6421408cc1fSYuval Mintz u32 igu_vf_conf = IGU_VF_CONF_FUNC_EN; 6431408cc1fSYuval Mintz int rc; 6441408cc1fSYuval Mintz 6450b55e27dSYuval Mintz if (vf->to_disable) 6460b55e27dSYuval Mintz return 0; 6470b55e27dSYuval Mintz 6481408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 6491408cc1fSYuval Mintz QED_MSG_IOV, 6501408cc1fSYuval Mintz "Enable internal access for vf %x [abs %x]\n", 6511408cc1fSYuval Mintz vf->abs_vf_id, QED_VF_ABS_ID(p_hwfn, vf)); 6521408cc1fSYuval Mintz 6531408cc1fSYuval Mintz qed_iov_vf_pglue_clear_err(p_hwfn, p_ptt, QED_VF_ABS_ID(p_hwfn, vf)); 6541408cc1fSYuval Mintz 655b2b897ebSYuval Mintz qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf); 656b2b897ebSYuval Mintz 6571408cc1fSYuval Mintz rc = qed_mcp_config_vf_msix(p_hwfn, p_ptt, vf->abs_vf_id, vf->num_sbs); 6581408cc1fSYuval Mintz if (rc) 6591408cc1fSYuval Mintz return rc; 6601408cc1fSYuval Mintz 6611408cc1fSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) vf->concrete_fid); 6621408cc1fSYuval Mintz 6631408cc1fSYuval Mintz SET_FIELD(igu_vf_conf, IGU_VF_CONF_PARENT, p_hwfn->rel_pf_id); 6641408cc1fSYuval Mintz STORE_RT_REG(p_hwfn, IGU_REG_VF_CONFIGURATION_RT_OFFSET, igu_vf_conf); 6651408cc1fSYuval Mintz 6661408cc1fSYuval Mintz qed_init_run(p_hwfn, p_ptt, PHASE_VF, vf->abs_vf_id, 6671408cc1fSYuval Mintz p_hwfn->hw_info.hw_mode); 6681408cc1fSYuval Mintz 6691408cc1fSYuval Mintz /* unpretend */ 6701408cc1fSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 6711408cc1fSYuval Mintz 6721408cc1fSYuval Mintz vf->state = VF_FREE; 6731408cc1fSYuval Mintz 6741408cc1fSYuval Mintz return rc; 6751408cc1fSYuval Mintz } 6761408cc1fSYuval Mintz 6770b55e27dSYuval Mintz /** 6780b55e27dSYuval Mintz * @brief qed_iov_config_perm_table - configure the permission 6790b55e27dSYuval Mintz * zone table. 6800b55e27dSYuval Mintz * In E4, queue zone permission table size is 320x9. There 6810b55e27dSYuval Mintz * are 320 VF queues for single engine device (256 for dual 6820b55e27dSYuval Mintz * engine device), and each entry has the following format: 6830b55e27dSYuval Mintz * {Valid, VF[7:0]} 6840b55e27dSYuval Mintz * @param p_hwfn 6850b55e27dSYuval Mintz * @param p_ptt 6860b55e27dSYuval Mintz * @param vf 6870b55e27dSYuval Mintz * @param enable 6880b55e27dSYuval Mintz */ 6890b55e27dSYuval Mintz static void qed_iov_config_perm_table(struct qed_hwfn *p_hwfn, 6900b55e27dSYuval Mintz struct qed_ptt *p_ptt, 6910b55e27dSYuval Mintz struct qed_vf_info *vf, u8 enable) 6920b55e27dSYuval Mintz { 6930b55e27dSYuval Mintz u32 reg_addr, val; 6940b55e27dSYuval Mintz u16 qzone_id = 0; 6950b55e27dSYuval Mintz int qid; 6960b55e27dSYuval Mintz 6970b55e27dSYuval Mintz for (qid = 0; qid < vf->num_rxqs; qid++) { 6980b55e27dSYuval Mintz qed_fw_l2_queue(p_hwfn, vf->vf_queues[qid].fw_rx_qid, 6990b55e27dSYuval Mintz &qzone_id); 7000b55e27dSYuval Mintz 7010b55e27dSYuval Mintz reg_addr = PSWHST_REG_ZONE_PERMISSION_TABLE + qzone_id * 4; 7020b55e27dSYuval Mintz val = enable ? (vf->abs_vf_id | (1 << 8)) : 0; 7030b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, reg_addr, val); 7040b55e27dSYuval Mintz } 7050b55e27dSYuval Mintz } 7060b55e27dSYuval Mintz 707dacd88d6SYuval Mintz static void qed_iov_enable_vf_traffic(struct qed_hwfn *p_hwfn, 708dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 709dacd88d6SYuval Mintz struct qed_vf_info *vf) 710dacd88d6SYuval Mintz { 711dacd88d6SYuval Mintz /* Reset vf in IGU - interrupts are still disabled */ 712dacd88d6SYuval Mintz qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf); 713dacd88d6SYuval Mintz 714dacd88d6SYuval Mintz qed_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 1); 715dacd88d6SYuval Mintz 716dacd88d6SYuval Mintz /* Permission Table */ 717dacd88d6SYuval Mintz qed_iov_config_perm_table(p_hwfn, p_ptt, vf, true); 718dacd88d6SYuval Mintz } 719dacd88d6SYuval Mintz 7201408cc1fSYuval Mintz static u8 qed_iov_alloc_vf_igu_sbs(struct qed_hwfn *p_hwfn, 7211408cc1fSYuval Mintz struct qed_ptt *p_ptt, 7221408cc1fSYuval Mintz struct qed_vf_info *vf, u16 num_rx_queues) 7231408cc1fSYuval Mintz { 7241408cc1fSYuval Mintz struct qed_igu_block *igu_blocks; 7251408cc1fSYuval Mintz int qid = 0, igu_id = 0; 7261408cc1fSYuval Mintz u32 val = 0; 7271408cc1fSYuval Mintz 7281408cc1fSYuval Mintz igu_blocks = p_hwfn->hw_info.p_igu_info->igu_map.igu_blocks; 7291408cc1fSYuval Mintz 7301408cc1fSYuval Mintz if (num_rx_queues > p_hwfn->hw_info.p_igu_info->free_blks) 7311408cc1fSYuval Mintz num_rx_queues = p_hwfn->hw_info.p_igu_info->free_blks; 7321408cc1fSYuval Mintz p_hwfn->hw_info.p_igu_info->free_blks -= num_rx_queues; 7331408cc1fSYuval Mintz 7341408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER, vf->abs_vf_id); 7351408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VALID, 1); 7361408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, 0); 7371408cc1fSYuval Mintz 7381408cc1fSYuval Mintz while ((qid < num_rx_queues) && 7391408cc1fSYuval Mintz (igu_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev))) { 7401408cc1fSYuval Mintz if (igu_blocks[igu_id].status & QED_IGU_STATUS_FREE) { 7411408cc1fSYuval Mintz struct cau_sb_entry sb_entry; 7421408cc1fSYuval Mintz 7431408cc1fSYuval Mintz vf->igu_sbs[qid] = (u16)igu_id; 7441408cc1fSYuval Mintz igu_blocks[igu_id].status &= ~QED_IGU_STATUS_FREE; 7451408cc1fSYuval Mintz 7461408cc1fSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER, qid); 7471408cc1fSYuval Mintz 7481408cc1fSYuval Mintz qed_wr(p_hwfn, p_ptt, 7491408cc1fSYuval Mintz IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_id, 7501408cc1fSYuval Mintz val); 7511408cc1fSYuval Mintz 7521408cc1fSYuval Mintz /* Configure igu sb in CAU which were marked valid */ 7531408cc1fSYuval Mintz qed_init_cau_sb_entry(p_hwfn, &sb_entry, 7541408cc1fSYuval Mintz p_hwfn->rel_pf_id, 7551408cc1fSYuval Mintz vf->abs_vf_id, 1); 7561408cc1fSYuval Mintz qed_dmae_host2grc(p_hwfn, p_ptt, 7571408cc1fSYuval Mintz (u64)(uintptr_t)&sb_entry, 7581408cc1fSYuval Mintz CAU_REG_SB_VAR_MEMORY + 7591408cc1fSYuval Mintz igu_id * sizeof(u64), 2, 0); 7601408cc1fSYuval Mintz qid++; 7611408cc1fSYuval Mintz } 7621408cc1fSYuval Mintz igu_id++; 7631408cc1fSYuval Mintz } 7641408cc1fSYuval Mintz 7651408cc1fSYuval Mintz vf->num_sbs = (u8) num_rx_queues; 7661408cc1fSYuval Mintz 7671408cc1fSYuval Mintz return vf->num_sbs; 7681408cc1fSYuval Mintz } 7691408cc1fSYuval Mintz 7700b55e27dSYuval Mintz static void qed_iov_free_vf_igu_sbs(struct qed_hwfn *p_hwfn, 7710b55e27dSYuval Mintz struct qed_ptt *p_ptt, 7720b55e27dSYuval Mintz struct qed_vf_info *vf) 7730b55e27dSYuval Mintz { 7740b55e27dSYuval Mintz struct qed_igu_info *p_info = p_hwfn->hw_info.p_igu_info; 7750b55e27dSYuval Mintz int idx, igu_id; 7760b55e27dSYuval Mintz u32 addr, val; 7770b55e27dSYuval Mintz 7780b55e27dSYuval Mintz /* Invalidate igu CAM lines and mark them as free */ 7790b55e27dSYuval Mintz for (idx = 0; idx < vf->num_sbs; idx++) { 7800b55e27dSYuval Mintz igu_id = vf->igu_sbs[idx]; 7810b55e27dSYuval Mintz addr = IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_id; 7820b55e27dSYuval Mintz 7830b55e27dSYuval Mintz val = qed_rd(p_hwfn, p_ptt, addr); 7840b55e27dSYuval Mintz SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0); 7850b55e27dSYuval Mintz qed_wr(p_hwfn, p_ptt, addr, val); 7860b55e27dSYuval Mintz 7870b55e27dSYuval Mintz p_info->igu_map.igu_blocks[igu_id].status |= 7880b55e27dSYuval Mintz QED_IGU_STATUS_FREE; 7890b55e27dSYuval Mintz 7900b55e27dSYuval Mintz p_hwfn->hw_info.p_igu_info->free_blks++; 7910b55e27dSYuval Mintz } 7920b55e27dSYuval Mintz 7930b55e27dSYuval Mintz vf->num_sbs = 0; 7940b55e27dSYuval Mintz } 7950b55e27dSYuval Mintz 7961408cc1fSYuval Mintz static int qed_iov_init_hw_for_vf(struct qed_hwfn *p_hwfn, 7971408cc1fSYuval Mintz struct qed_ptt *p_ptt, 7981408cc1fSYuval Mintz u16 rel_vf_id, u16 num_rx_queues) 7991408cc1fSYuval Mintz { 8001408cc1fSYuval Mintz u8 num_of_vf_avaiable_chains = 0; 8011408cc1fSYuval Mintz struct qed_vf_info *vf = NULL; 8021408cc1fSYuval Mintz int rc = 0; 8031408cc1fSYuval Mintz u32 cids; 8041408cc1fSYuval Mintz u8 i; 8051408cc1fSYuval Mintz 8061408cc1fSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, false); 8071408cc1fSYuval Mintz if (!vf) { 8081408cc1fSYuval Mintz DP_ERR(p_hwfn, "qed_iov_init_hw_for_vf : vf is NULL\n"); 8091408cc1fSYuval Mintz return -EINVAL; 8101408cc1fSYuval Mintz } 8111408cc1fSYuval Mintz 8121408cc1fSYuval Mintz if (vf->b_init) { 8131408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "VF[%d] is already active.\n", rel_vf_id); 8141408cc1fSYuval Mintz return -EINVAL; 8151408cc1fSYuval Mintz } 8161408cc1fSYuval Mintz 8171408cc1fSYuval Mintz /* Limit number of queues according to number of CIDs */ 8181408cc1fSYuval Mintz qed_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH, &cids); 8191408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 8201408cc1fSYuval Mintz QED_MSG_IOV, 8211408cc1fSYuval Mintz "VF[%d] - requesting to initialize for 0x%04x queues [0x%04x CIDs available]\n", 8221408cc1fSYuval Mintz vf->relative_vf_id, num_rx_queues, (u16) cids); 8231408cc1fSYuval Mintz num_rx_queues = min_t(u16, num_rx_queues, ((u16) cids)); 8241408cc1fSYuval Mintz 8251408cc1fSYuval Mintz num_of_vf_avaiable_chains = qed_iov_alloc_vf_igu_sbs(p_hwfn, 8261408cc1fSYuval Mintz p_ptt, 8271408cc1fSYuval Mintz vf, 8281408cc1fSYuval Mintz num_rx_queues); 8291408cc1fSYuval Mintz if (!num_of_vf_avaiable_chains) { 8301408cc1fSYuval Mintz DP_ERR(p_hwfn, "no available igu sbs\n"); 8311408cc1fSYuval Mintz return -ENOMEM; 8321408cc1fSYuval Mintz } 8331408cc1fSYuval Mintz 8341408cc1fSYuval Mintz /* Choose queue number and index ranges */ 8351408cc1fSYuval Mintz vf->num_rxqs = num_of_vf_avaiable_chains; 8361408cc1fSYuval Mintz vf->num_txqs = num_of_vf_avaiable_chains; 8371408cc1fSYuval Mintz 8381408cc1fSYuval Mintz for (i = 0; i < vf->num_rxqs; i++) { 8391408cc1fSYuval Mintz u16 queue_id = qed_int_queue_id_from_sb_id(p_hwfn, 8401408cc1fSYuval Mintz vf->igu_sbs[i]); 8411408cc1fSYuval Mintz 8421408cc1fSYuval Mintz if (queue_id > RESC_NUM(p_hwfn, QED_L2_QUEUE)) { 8431408cc1fSYuval Mintz DP_NOTICE(p_hwfn, 8441408cc1fSYuval Mintz "VF[%d] will require utilizing of out-of-bounds queues - %04x\n", 8451408cc1fSYuval Mintz vf->relative_vf_id, queue_id); 8461408cc1fSYuval Mintz return -EINVAL; 8471408cc1fSYuval Mintz } 8481408cc1fSYuval Mintz 8491408cc1fSYuval Mintz /* CIDs are per-VF, so no problem having them 0-based. */ 8501408cc1fSYuval Mintz vf->vf_queues[i].fw_rx_qid = queue_id; 8511408cc1fSYuval Mintz vf->vf_queues[i].fw_tx_qid = queue_id; 8521408cc1fSYuval Mintz vf->vf_queues[i].fw_cid = i; 8531408cc1fSYuval Mintz 8541408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 8551408cc1fSYuval Mintz "VF[%d] - [%d] SB %04x, Tx/Rx queue %04x CID %04x\n", 8561408cc1fSYuval Mintz vf->relative_vf_id, i, vf->igu_sbs[i], queue_id, i); 8571408cc1fSYuval Mintz } 8581408cc1fSYuval Mintz rc = qed_iov_enable_vf_access(p_hwfn, p_ptt, vf); 8591408cc1fSYuval Mintz if (!rc) { 8601408cc1fSYuval Mintz vf->b_init = true; 8611408cc1fSYuval Mintz 8621408cc1fSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) 8631408cc1fSYuval Mintz p_hwfn->cdev->p_iov_info->num_vfs++; 8641408cc1fSYuval Mintz } 8651408cc1fSYuval Mintz 8661408cc1fSYuval Mintz return rc; 8671408cc1fSYuval Mintz } 8681408cc1fSYuval Mintz 869079d20a6SManish Chopra static void qed_iov_set_link(struct qed_hwfn *p_hwfn, 870079d20a6SManish Chopra u16 vfid, 871079d20a6SManish Chopra struct qed_mcp_link_params *params, 872079d20a6SManish Chopra struct qed_mcp_link_state *link, 873079d20a6SManish Chopra struct qed_mcp_link_capabilities *p_caps) 874079d20a6SManish Chopra { 875079d20a6SManish Chopra struct qed_vf_info *p_vf = qed_iov_get_vf_info(p_hwfn, 876079d20a6SManish Chopra vfid, 877079d20a6SManish Chopra false); 878079d20a6SManish Chopra struct qed_bulletin_content *p_bulletin; 879079d20a6SManish Chopra 880079d20a6SManish Chopra if (!p_vf) 881079d20a6SManish Chopra return; 882079d20a6SManish Chopra 883079d20a6SManish Chopra p_bulletin = p_vf->bulletin.p_virt; 884079d20a6SManish Chopra p_bulletin->req_autoneg = params->speed.autoneg; 885079d20a6SManish Chopra p_bulletin->req_adv_speed = params->speed.advertised_speeds; 886079d20a6SManish Chopra p_bulletin->req_forced_speed = params->speed.forced_speed; 887079d20a6SManish Chopra p_bulletin->req_autoneg_pause = params->pause.autoneg; 888079d20a6SManish Chopra p_bulletin->req_forced_rx = params->pause.forced_rx; 889079d20a6SManish Chopra p_bulletin->req_forced_tx = params->pause.forced_tx; 890079d20a6SManish Chopra p_bulletin->req_loopback = params->loopback_mode; 891079d20a6SManish Chopra 892079d20a6SManish Chopra p_bulletin->link_up = link->link_up; 893079d20a6SManish Chopra p_bulletin->speed = link->speed; 894079d20a6SManish Chopra p_bulletin->full_duplex = link->full_duplex; 895079d20a6SManish Chopra p_bulletin->autoneg = link->an; 896079d20a6SManish Chopra p_bulletin->autoneg_complete = link->an_complete; 897079d20a6SManish Chopra p_bulletin->parallel_detection = link->parallel_detection; 898079d20a6SManish Chopra p_bulletin->pfc_enabled = link->pfc_enabled; 899079d20a6SManish Chopra p_bulletin->partner_adv_speed = link->partner_adv_speed; 900079d20a6SManish Chopra p_bulletin->partner_tx_flow_ctrl_en = link->partner_tx_flow_ctrl_en; 901079d20a6SManish Chopra p_bulletin->partner_rx_flow_ctrl_en = link->partner_rx_flow_ctrl_en; 902079d20a6SManish Chopra p_bulletin->partner_adv_pause = link->partner_adv_pause; 903079d20a6SManish Chopra p_bulletin->sfp_tx_fault = link->sfp_tx_fault; 904079d20a6SManish Chopra 905079d20a6SManish Chopra p_bulletin->capability_speed = p_caps->speed_capabilities; 906079d20a6SManish Chopra } 907079d20a6SManish Chopra 9080b55e27dSYuval Mintz static int qed_iov_release_hw_for_vf(struct qed_hwfn *p_hwfn, 9090b55e27dSYuval Mintz struct qed_ptt *p_ptt, u16 rel_vf_id) 9100b55e27dSYuval Mintz { 911079d20a6SManish Chopra struct qed_mcp_link_capabilities caps; 912079d20a6SManish Chopra struct qed_mcp_link_params params; 913079d20a6SManish Chopra struct qed_mcp_link_state link; 9140b55e27dSYuval Mintz struct qed_vf_info *vf = NULL; 9150b55e27dSYuval Mintz 9160b55e27dSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true); 9170b55e27dSYuval Mintz if (!vf) { 9180b55e27dSYuval Mintz DP_ERR(p_hwfn, "qed_iov_release_hw_for_vf : vf is NULL\n"); 9190b55e27dSYuval Mintz return -EINVAL; 9200b55e27dSYuval Mintz } 9210b55e27dSYuval Mintz 92236558c3dSYuval Mintz if (vf->bulletin.p_virt) 92336558c3dSYuval Mintz memset(vf->bulletin.p_virt, 0, sizeof(*vf->bulletin.p_virt)); 92436558c3dSYuval Mintz 92536558c3dSYuval Mintz memset(&vf->p_vf_info, 0, sizeof(vf->p_vf_info)); 92636558c3dSYuval Mintz 927079d20a6SManish Chopra /* Get the link configuration back in bulletin so 928079d20a6SManish Chopra * that when VFs are re-enabled they get the actual 929079d20a6SManish Chopra * link configuration. 930079d20a6SManish Chopra */ 931079d20a6SManish Chopra memcpy(¶ms, qed_mcp_get_link_params(p_hwfn), sizeof(params)); 932079d20a6SManish Chopra memcpy(&link, qed_mcp_get_link_state(p_hwfn), sizeof(link)); 933079d20a6SManish Chopra memcpy(&caps, qed_mcp_get_link_capabilities(p_hwfn), sizeof(caps)); 934079d20a6SManish Chopra qed_iov_set_link(p_hwfn, rel_vf_id, ¶ms, &link, &caps); 935079d20a6SManish Chopra 9361fe614d1SYuval Mintz /* Forget the VF's acquisition message */ 9371fe614d1SYuval Mintz memset(&vf->acquire, 0, sizeof(vf->acquire)); 9380b55e27dSYuval Mintz 9390b55e27dSYuval Mintz /* disablng interrupts and resetting permission table was done during 9400b55e27dSYuval Mintz * vf-close, however, we could get here without going through vf_close 9410b55e27dSYuval Mintz */ 9420b55e27dSYuval Mintz /* Disable Interrupts for VF */ 9430b55e27dSYuval Mintz qed_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0); 9440b55e27dSYuval Mintz 9450b55e27dSYuval Mintz /* Reset Permission table */ 9460b55e27dSYuval Mintz qed_iov_config_perm_table(p_hwfn, p_ptt, vf, 0); 9470b55e27dSYuval Mintz 9480b55e27dSYuval Mintz vf->num_rxqs = 0; 9490b55e27dSYuval Mintz vf->num_txqs = 0; 9500b55e27dSYuval Mintz qed_iov_free_vf_igu_sbs(p_hwfn, p_ptt, vf); 9510b55e27dSYuval Mintz 9520b55e27dSYuval Mintz if (vf->b_init) { 9530b55e27dSYuval Mintz vf->b_init = false; 9540b55e27dSYuval Mintz 9550b55e27dSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) 9560b55e27dSYuval Mintz p_hwfn->cdev->p_iov_info->num_vfs--; 9570b55e27dSYuval Mintz } 9580b55e27dSYuval Mintz 9590b55e27dSYuval Mintz return 0; 9600b55e27dSYuval Mintz } 9610b55e27dSYuval Mintz 96237bff2b9SYuval Mintz static bool qed_iov_tlv_supported(u16 tlvtype) 96337bff2b9SYuval Mintz { 96437bff2b9SYuval Mintz return CHANNEL_TLV_NONE < tlvtype && tlvtype < CHANNEL_TLV_MAX; 96537bff2b9SYuval Mintz } 96637bff2b9SYuval Mintz 96737bff2b9SYuval Mintz /* place a given tlv on the tlv buffer, continuing current tlv list */ 96837bff2b9SYuval Mintz void *qed_add_tlv(struct qed_hwfn *p_hwfn, u8 **offset, u16 type, u16 length) 96937bff2b9SYuval Mintz { 97037bff2b9SYuval Mintz struct channel_tlv *tl = (struct channel_tlv *)*offset; 97137bff2b9SYuval Mintz 97237bff2b9SYuval Mintz tl->type = type; 97337bff2b9SYuval Mintz tl->length = length; 97437bff2b9SYuval Mintz 97537bff2b9SYuval Mintz /* Offset should keep pointing to next TLV (the end of the last) */ 97637bff2b9SYuval Mintz *offset += length; 97737bff2b9SYuval Mintz 97837bff2b9SYuval Mintz /* Return a pointer to the start of the added tlv */ 97937bff2b9SYuval Mintz return *offset - length; 98037bff2b9SYuval Mintz } 98137bff2b9SYuval Mintz 98237bff2b9SYuval Mintz /* list the types and lengths of the tlvs on the buffer */ 98337bff2b9SYuval Mintz void qed_dp_tlv_list(struct qed_hwfn *p_hwfn, void *tlvs_list) 98437bff2b9SYuval Mintz { 98537bff2b9SYuval Mintz u16 i = 1, total_length = 0; 98637bff2b9SYuval Mintz struct channel_tlv *tlv; 98737bff2b9SYuval Mintz 98837bff2b9SYuval Mintz do { 98937bff2b9SYuval Mintz tlv = (struct channel_tlv *)((u8 *)tlvs_list + total_length); 99037bff2b9SYuval Mintz 99137bff2b9SYuval Mintz /* output tlv */ 99237bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 99337bff2b9SYuval Mintz "TLV number %d: type %d, length %d\n", 99437bff2b9SYuval Mintz i, tlv->type, tlv->length); 99537bff2b9SYuval Mintz 99637bff2b9SYuval Mintz if (tlv->type == CHANNEL_TLV_LIST_END) 99737bff2b9SYuval Mintz return; 99837bff2b9SYuval Mintz 99937bff2b9SYuval Mintz /* Validate entry - protect against malicious VFs */ 100037bff2b9SYuval Mintz if (!tlv->length) { 100137bff2b9SYuval Mintz DP_NOTICE(p_hwfn, "TLV of length 0 found\n"); 100237bff2b9SYuval Mintz return; 100337bff2b9SYuval Mintz } 100437bff2b9SYuval Mintz 100537bff2b9SYuval Mintz total_length += tlv->length; 100637bff2b9SYuval Mintz 100737bff2b9SYuval Mintz if (total_length >= sizeof(struct tlv_buffer_size)) { 100837bff2b9SYuval Mintz DP_NOTICE(p_hwfn, "TLV ==> Buffer overflow\n"); 100937bff2b9SYuval Mintz return; 101037bff2b9SYuval Mintz } 101137bff2b9SYuval Mintz 101237bff2b9SYuval Mintz i++; 101337bff2b9SYuval Mintz } while (1); 101437bff2b9SYuval Mintz } 101537bff2b9SYuval Mintz 101637bff2b9SYuval Mintz static void qed_iov_send_response(struct qed_hwfn *p_hwfn, 101737bff2b9SYuval Mintz struct qed_ptt *p_ptt, 101837bff2b9SYuval Mintz struct qed_vf_info *p_vf, 101937bff2b9SYuval Mintz u16 length, u8 status) 102037bff2b9SYuval Mintz { 102137bff2b9SYuval Mintz struct qed_iov_vf_mbx *mbx = &p_vf->vf_mbx; 102237bff2b9SYuval Mintz struct qed_dmae_params params; 102337bff2b9SYuval Mintz u8 eng_vf_id; 102437bff2b9SYuval Mintz 102537bff2b9SYuval Mintz mbx->reply_virt->default_resp.hdr.status = status; 102637bff2b9SYuval Mintz 102737bff2b9SYuval Mintz qed_dp_tlv_list(p_hwfn, mbx->reply_virt); 102837bff2b9SYuval Mintz 102937bff2b9SYuval Mintz eng_vf_id = p_vf->abs_vf_id; 103037bff2b9SYuval Mintz 103137bff2b9SYuval Mintz memset(¶ms, 0, sizeof(struct qed_dmae_params)); 103237bff2b9SYuval Mintz params.flags = QED_DMAE_FLAG_VF_DST; 103337bff2b9SYuval Mintz params.dst_vfid = eng_vf_id; 103437bff2b9SYuval Mintz 103537bff2b9SYuval Mintz qed_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys + sizeof(u64), 103637bff2b9SYuval Mintz mbx->req_virt->first_tlv.reply_address + 103737bff2b9SYuval Mintz sizeof(u64), 103837bff2b9SYuval Mintz (sizeof(union pfvf_tlvs) - sizeof(u64)) / 4, 103937bff2b9SYuval Mintz ¶ms); 104037bff2b9SYuval Mintz 104137bff2b9SYuval Mintz qed_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys, 104237bff2b9SYuval Mintz mbx->req_virt->first_tlv.reply_address, 104337bff2b9SYuval Mintz sizeof(u64) / 4, ¶ms); 104437bff2b9SYuval Mintz 104537bff2b9SYuval Mintz REG_WR(p_hwfn, 104637bff2b9SYuval Mintz GTT_BAR0_MAP_REG_USDM_RAM + 104737bff2b9SYuval Mintz USTORM_VF_PF_CHANNEL_READY_OFFSET(eng_vf_id), 1); 104837bff2b9SYuval Mintz } 104937bff2b9SYuval Mintz 1050dacd88d6SYuval Mintz static u16 qed_iov_vport_to_tlv(struct qed_hwfn *p_hwfn, 1051dacd88d6SYuval Mintz enum qed_iov_vport_update_flag flag) 1052dacd88d6SYuval Mintz { 1053dacd88d6SYuval Mintz switch (flag) { 1054dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_ACTIVATE: 1055dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_ACTIVATE; 105617b235c1SYuval Mintz case QED_IOV_VP_UPDATE_VLAN_STRIP: 105717b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP; 105817b235c1SYuval Mintz case QED_IOV_VP_UPDATE_TX_SWITCH: 105917b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; 1060dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_MCAST: 1061dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_MCAST; 1062dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_ACCEPT_PARAM: 1063dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; 1064dacd88d6SYuval Mintz case QED_IOV_VP_UPDATE_RSS: 1065dacd88d6SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_RSS; 106617b235c1SYuval Mintz case QED_IOV_VP_UPDATE_ACCEPT_ANY_VLAN: 106717b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; 106817b235c1SYuval Mintz case QED_IOV_VP_UPDATE_SGE_TPA: 106917b235c1SYuval Mintz return CHANNEL_TLV_VPORT_UPDATE_SGE_TPA; 1070dacd88d6SYuval Mintz default: 1071dacd88d6SYuval Mintz return 0; 1072dacd88d6SYuval Mintz } 1073dacd88d6SYuval Mintz } 1074dacd88d6SYuval Mintz 1075dacd88d6SYuval Mintz static u16 qed_iov_prep_vp_update_resp_tlvs(struct qed_hwfn *p_hwfn, 1076dacd88d6SYuval Mintz struct qed_vf_info *p_vf, 1077dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, 1078dacd88d6SYuval Mintz u8 status, 1079dacd88d6SYuval Mintz u16 tlvs_mask, u16 tlvs_accepted) 1080dacd88d6SYuval Mintz { 1081dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 1082dacd88d6SYuval Mintz u16 size, total_len, i; 1083dacd88d6SYuval Mintz 1084dacd88d6SYuval Mintz memset(p_mbx->reply_virt, 0, sizeof(union pfvf_tlvs)); 1085dacd88d6SYuval Mintz p_mbx->offset = (u8 *)p_mbx->reply_virt; 1086dacd88d6SYuval Mintz size = sizeof(struct pfvf_def_resp_tlv); 1087dacd88d6SYuval Mintz total_len = size; 1088dacd88d6SYuval Mintz 1089dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_mbx->offset, CHANNEL_TLV_VPORT_UPDATE, size); 1090dacd88d6SYuval Mintz 1091dacd88d6SYuval Mintz /* Prepare response for all extended tlvs if they are found by PF */ 1092dacd88d6SYuval Mintz for (i = 0; i < QED_IOV_VP_UPDATE_MAX; i++) { 1093dacd88d6SYuval Mintz if (!(tlvs_mask & (1 << i))) 1094dacd88d6SYuval Mintz continue; 1095dacd88d6SYuval Mintz 1096dacd88d6SYuval Mintz resp = qed_add_tlv(p_hwfn, &p_mbx->offset, 1097dacd88d6SYuval Mintz qed_iov_vport_to_tlv(p_hwfn, i), size); 1098dacd88d6SYuval Mintz 1099dacd88d6SYuval Mintz if (tlvs_accepted & (1 << i)) 1100dacd88d6SYuval Mintz resp->hdr.status = status; 1101dacd88d6SYuval Mintz else 1102dacd88d6SYuval Mintz resp->hdr.status = PFVF_STATUS_NOT_SUPPORTED; 1103dacd88d6SYuval Mintz 1104dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, 1105dacd88d6SYuval Mintz QED_MSG_IOV, 1106dacd88d6SYuval Mintz "VF[%d] - vport_update response: TLV %d, status %02x\n", 1107dacd88d6SYuval Mintz p_vf->relative_vf_id, 1108dacd88d6SYuval Mintz qed_iov_vport_to_tlv(p_hwfn, i), resp->hdr.status); 1109dacd88d6SYuval Mintz 1110dacd88d6SYuval Mintz total_len += size; 1111dacd88d6SYuval Mintz } 1112dacd88d6SYuval Mintz 1113dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_mbx->offset, CHANNEL_TLV_LIST_END, 1114dacd88d6SYuval Mintz sizeof(struct channel_list_end_tlv)); 1115dacd88d6SYuval Mintz 1116dacd88d6SYuval Mintz return total_len; 1117dacd88d6SYuval Mintz } 1118dacd88d6SYuval Mintz 111937bff2b9SYuval Mintz static void qed_iov_prepare_resp(struct qed_hwfn *p_hwfn, 112037bff2b9SYuval Mintz struct qed_ptt *p_ptt, 112137bff2b9SYuval Mintz struct qed_vf_info *vf_info, 112237bff2b9SYuval Mintz u16 type, u16 length, u8 status) 112337bff2b9SYuval Mintz { 112437bff2b9SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf_info->vf_mbx; 112537bff2b9SYuval Mintz 112637bff2b9SYuval Mintz mbx->offset = (u8 *)mbx->reply_virt; 112737bff2b9SYuval Mintz 112837bff2b9SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, type, length); 112937bff2b9SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 113037bff2b9SYuval Mintz sizeof(struct channel_list_end_tlv)); 113137bff2b9SYuval Mintz 113237bff2b9SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, vf_info, length, status); 113337bff2b9SYuval Mintz } 113437bff2b9SYuval Mintz 11350b55e27dSYuval Mintz struct qed_public_vf_info *qed_iov_get_public_vf_info(struct qed_hwfn *p_hwfn, 11360b55e27dSYuval Mintz u16 relative_vf_id, 11370b55e27dSYuval Mintz bool b_enabled_only) 11380b55e27dSYuval Mintz { 11390b55e27dSYuval Mintz struct qed_vf_info *vf = NULL; 11400b55e27dSYuval Mintz 11410b55e27dSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, relative_vf_id, b_enabled_only); 11420b55e27dSYuval Mintz if (!vf) 11430b55e27dSYuval Mintz return NULL; 11440b55e27dSYuval Mintz 11450b55e27dSYuval Mintz return &vf->p_vf_info; 11460b55e27dSYuval Mintz } 11470b55e27dSYuval Mintz 11480b55e27dSYuval Mintz void qed_iov_clean_vf(struct qed_hwfn *p_hwfn, u8 vfid) 11490b55e27dSYuval Mintz { 11500b55e27dSYuval Mintz struct qed_public_vf_info *vf_info; 11510b55e27dSYuval Mintz 11520b55e27dSYuval Mintz vf_info = qed_iov_get_public_vf_info(p_hwfn, vfid, false); 11530b55e27dSYuval Mintz 11540b55e27dSYuval Mintz if (!vf_info) 11550b55e27dSYuval Mintz return; 11560b55e27dSYuval Mintz 11570b55e27dSYuval Mintz /* Clear the VF mac */ 11580b55e27dSYuval Mintz memset(vf_info->mac, 0, ETH_ALEN); 11590b55e27dSYuval Mintz } 11600b55e27dSYuval Mintz 11610b55e27dSYuval Mintz static void qed_iov_vf_cleanup(struct qed_hwfn *p_hwfn, 11620b55e27dSYuval Mintz struct qed_vf_info *p_vf) 11630b55e27dSYuval Mintz { 11640b55e27dSYuval Mintz u32 i; 11650b55e27dSYuval Mintz 11660b55e27dSYuval Mintz p_vf->vf_bulletin = 0; 1167dacd88d6SYuval Mintz p_vf->vport_instance = 0; 116808feecd7SYuval Mintz p_vf->configured_features = 0; 11690b55e27dSYuval Mintz 11700b55e27dSYuval Mintz /* If VF previously requested less resources, go back to default */ 11710b55e27dSYuval Mintz p_vf->num_rxqs = p_vf->num_sbs; 11720b55e27dSYuval Mintz p_vf->num_txqs = p_vf->num_sbs; 11730b55e27dSYuval Mintz 1174dacd88d6SYuval Mintz p_vf->num_active_rxqs = 0; 1175dacd88d6SYuval Mintz 11760b55e27dSYuval Mintz for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++) 11770b55e27dSYuval Mintz p_vf->vf_queues[i].rxq_active = 0; 11780b55e27dSYuval Mintz 117908feecd7SYuval Mintz memset(&p_vf->shadow_config, 0, sizeof(p_vf->shadow_config)); 11801fe614d1SYuval Mintz memset(&p_vf->acquire, 0, sizeof(p_vf->acquire)); 11810b55e27dSYuval Mintz qed_iov_clean_vf(p_hwfn, p_vf->relative_vf_id); 11820b55e27dSYuval Mintz } 11830b55e27dSYuval Mintz 11841cf2b1a9SYuval Mintz static u8 qed_iov_vf_mbx_acquire_resc(struct qed_hwfn *p_hwfn, 11851cf2b1a9SYuval Mintz struct qed_ptt *p_ptt, 11861cf2b1a9SYuval Mintz struct qed_vf_info *p_vf, 11871cf2b1a9SYuval Mintz struct vf_pf_resc_request *p_req, 11881cf2b1a9SYuval Mintz struct pf_vf_resc *p_resp) 11891cf2b1a9SYuval Mintz { 11901cf2b1a9SYuval Mintz int i; 11911cf2b1a9SYuval Mintz 11921cf2b1a9SYuval Mintz /* Queue related information */ 11931cf2b1a9SYuval Mintz p_resp->num_rxqs = p_vf->num_rxqs; 11941cf2b1a9SYuval Mintz p_resp->num_txqs = p_vf->num_txqs; 11951cf2b1a9SYuval Mintz p_resp->num_sbs = p_vf->num_sbs; 11961cf2b1a9SYuval Mintz 11971cf2b1a9SYuval Mintz for (i = 0; i < p_resp->num_sbs; i++) { 11981cf2b1a9SYuval Mintz p_resp->hw_sbs[i].hw_sb_id = p_vf->igu_sbs[i]; 11991cf2b1a9SYuval Mintz p_resp->hw_sbs[i].sb_qid = 0; 12001cf2b1a9SYuval Mintz } 12011cf2b1a9SYuval Mintz 12021cf2b1a9SYuval Mintz /* These fields are filled for backward compatibility. 12031cf2b1a9SYuval Mintz * Unused by modern vfs. 12041cf2b1a9SYuval Mintz */ 12051cf2b1a9SYuval Mintz for (i = 0; i < p_resp->num_rxqs; i++) { 12061cf2b1a9SYuval Mintz qed_fw_l2_queue(p_hwfn, p_vf->vf_queues[i].fw_rx_qid, 12071cf2b1a9SYuval Mintz (u16 *)&p_resp->hw_qid[i]); 12081cf2b1a9SYuval Mintz p_resp->cid[i] = p_vf->vf_queues[i].fw_cid; 12091cf2b1a9SYuval Mintz } 12101cf2b1a9SYuval Mintz 12111cf2b1a9SYuval Mintz /* Filter related information */ 12121cf2b1a9SYuval Mintz p_resp->num_mac_filters = min_t(u8, p_vf->num_mac_filters, 12131cf2b1a9SYuval Mintz p_req->num_mac_filters); 12141cf2b1a9SYuval Mintz p_resp->num_vlan_filters = min_t(u8, p_vf->num_vlan_filters, 12151cf2b1a9SYuval Mintz p_req->num_vlan_filters); 12161cf2b1a9SYuval Mintz 12171cf2b1a9SYuval Mintz /* This isn't really needed/enforced, but some legacy VFs might depend 12181cf2b1a9SYuval Mintz * on the correct filling of this field. 12191cf2b1a9SYuval Mintz */ 12201cf2b1a9SYuval Mintz p_resp->num_mc_filters = QED_MAX_MC_ADDRS; 12211cf2b1a9SYuval Mintz 12221cf2b1a9SYuval Mintz /* Validate sufficient resources for VF */ 12231cf2b1a9SYuval Mintz if (p_resp->num_rxqs < p_req->num_rxqs || 12241cf2b1a9SYuval Mintz p_resp->num_txqs < p_req->num_txqs || 12251cf2b1a9SYuval Mintz p_resp->num_sbs < p_req->num_sbs || 12261cf2b1a9SYuval Mintz p_resp->num_mac_filters < p_req->num_mac_filters || 12271cf2b1a9SYuval Mintz p_resp->num_vlan_filters < p_req->num_vlan_filters || 12281cf2b1a9SYuval Mintz p_resp->num_mc_filters < p_req->num_mc_filters) { 12291cf2b1a9SYuval Mintz DP_VERBOSE(p_hwfn, 12301cf2b1a9SYuval Mintz QED_MSG_IOV, 12311cf2b1a9SYuval Mintz "VF[%d] - Insufficient resources: rxq [%02x/%02x] txq [%02x/%02x] sbs [%02x/%02x] mac [%02x/%02x] vlan [%02x/%02x] mc [%02x/%02x]\n", 12321cf2b1a9SYuval Mintz p_vf->abs_vf_id, 12331cf2b1a9SYuval Mintz p_req->num_rxqs, 12341cf2b1a9SYuval Mintz p_resp->num_rxqs, 12351cf2b1a9SYuval Mintz p_req->num_rxqs, 12361cf2b1a9SYuval Mintz p_resp->num_txqs, 12371cf2b1a9SYuval Mintz p_req->num_sbs, 12381cf2b1a9SYuval Mintz p_resp->num_sbs, 12391cf2b1a9SYuval Mintz p_req->num_mac_filters, 12401cf2b1a9SYuval Mintz p_resp->num_mac_filters, 12411cf2b1a9SYuval Mintz p_req->num_vlan_filters, 12421cf2b1a9SYuval Mintz p_resp->num_vlan_filters, 12431cf2b1a9SYuval Mintz p_req->num_mc_filters, p_resp->num_mc_filters); 12441cf2b1a9SYuval Mintz return PFVF_STATUS_NO_RESOURCE; 12451cf2b1a9SYuval Mintz } 12461cf2b1a9SYuval Mintz 12471cf2b1a9SYuval Mintz return PFVF_STATUS_SUCCESS; 12481cf2b1a9SYuval Mintz } 12491cf2b1a9SYuval Mintz 12501cf2b1a9SYuval Mintz static void qed_iov_vf_mbx_acquire_stats(struct qed_hwfn *p_hwfn, 12511cf2b1a9SYuval Mintz struct pfvf_stats_info *p_stats) 12521cf2b1a9SYuval Mintz { 12531cf2b1a9SYuval Mintz p_stats->mstats.address = PXP_VF_BAR0_START_MSDM_ZONE_B + 12541cf2b1a9SYuval Mintz offsetof(struct mstorm_vf_zone, 12551cf2b1a9SYuval Mintz non_trigger.eth_queue_stat); 12561cf2b1a9SYuval Mintz p_stats->mstats.len = sizeof(struct eth_mstorm_per_queue_stat); 12571cf2b1a9SYuval Mintz p_stats->ustats.address = PXP_VF_BAR0_START_USDM_ZONE_B + 12581cf2b1a9SYuval Mintz offsetof(struct ustorm_vf_zone, 12591cf2b1a9SYuval Mintz non_trigger.eth_queue_stat); 12601cf2b1a9SYuval Mintz p_stats->ustats.len = sizeof(struct eth_ustorm_per_queue_stat); 12611cf2b1a9SYuval Mintz p_stats->pstats.address = PXP_VF_BAR0_START_PSDM_ZONE_B + 12621cf2b1a9SYuval Mintz offsetof(struct pstorm_vf_zone, 12631cf2b1a9SYuval Mintz non_trigger.eth_queue_stat); 12641cf2b1a9SYuval Mintz p_stats->pstats.len = sizeof(struct eth_pstorm_per_queue_stat); 12651cf2b1a9SYuval Mintz p_stats->tstats.address = 0; 12661cf2b1a9SYuval Mintz p_stats->tstats.len = 0; 12671cf2b1a9SYuval Mintz } 12681cf2b1a9SYuval Mintz 12691408cc1fSYuval Mintz static void qed_iov_vf_mbx_acquire(struct qed_hwfn *p_hwfn, 127037bff2b9SYuval Mintz struct qed_ptt *p_ptt, 12711408cc1fSYuval Mintz struct qed_vf_info *vf) 127237bff2b9SYuval Mintz { 12731408cc1fSYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 12741408cc1fSYuval Mintz struct pfvf_acquire_resp_tlv *resp = &mbx->reply_virt->acquire_resp; 12751408cc1fSYuval Mintz struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info; 12761408cc1fSYuval Mintz struct vfpf_acquire_tlv *req = &mbx->req_virt->acquire; 12771cf2b1a9SYuval Mintz u8 vfpf_status = PFVF_STATUS_NOT_SUPPORTED; 12781408cc1fSYuval Mintz struct pf_vf_resc *resc = &resp->resc; 12791fe614d1SYuval Mintz int rc; 12801fe614d1SYuval Mintz 12811fe614d1SYuval Mintz memset(resp, 0, sizeof(*resp)); 12821408cc1fSYuval Mintz 12831408cc1fSYuval Mintz /* Validate FW compatibility */ 12841fe614d1SYuval Mintz if (req->vfdev_info.eth_fp_hsi_major != ETH_HSI_VER_MAJOR) { 12851408cc1fSYuval Mintz DP_INFO(p_hwfn, 12861fe614d1SYuval Mintz "VF[%d] needs fastpath HSI %02x.%02x, which is incompatible with loaded FW's faspath HSI %02x.%02x\n", 12871408cc1fSYuval Mintz vf->abs_vf_id, 12881fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_major, 12891fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_minor, 12901fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR); 12911fe614d1SYuval Mintz 12921fe614d1SYuval Mintz /* Write the PF version so that VF would know which version 12931fe614d1SYuval Mintz * is supported. 12941fe614d1SYuval Mintz */ 12951fe614d1SYuval Mintz pfdev_info->major_fp_hsi = ETH_HSI_VER_MAJOR; 12961fe614d1SYuval Mintz pfdev_info->minor_fp_hsi = ETH_HSI_VER_MINOR; 12971fe614d1SYuval Mintz 12981408cc1fSYuval Mintz goto out; 12991408cc1fSYuval Mintz } 13001408cc1fSYuval Mintz 13011408cc1fSYuval Mintz /* On 100g PFs, prevent old VFs from loading */ 13021408cc1fSYuval Mintz if ((p_hwfn->cdev->num_hwfns > 1) && 13031408cc1fSYuval Mintz !(req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_100G)) { 13041408cc1fSYuval Mintz DP_INFO(p_hwfn, 13051408cc1fSYuval Mintz "VF[%d] is running an old driver that doesn't support 100g\n", 13061408cc1fSYuval Mintz vf->abs_vf_id); 13071408cc1fSYuval Mintz goto out; 13081408cc1fSYuval Mintz } 13091408cc1fSYuval Mintz 13101fe614d1SYuval Mintz /* Store the acquire message */ 13111fe614d1SYuval Mintz memcpy(&vf->acquire, req, sizeof(vf->acquire)); 13121408cc1fSYuval Mintz 13131408cc1fSYuval Mintz vf->opaque_fid = req->vfdev_info.opaque_fid; 13141408cc1fSYuval Mintz 13151408cc1fSYuval Mintz vf->vf_bulletin = req->bulletin_addr; 13161408cc1fSYuval Mintz vf->bulletin.size = (vf->bulletin.size < req->bulletin_size) ? 13171408cc1fSYuval Mintz vf->bulletin.size : req->bulletin_size; 13181408cc1fSYuval Mintz 13191408cc1fSYuval Mintz /* fill in pfdev info */ 13201408cc1fSYuval Mintz pfdev_info->chip_num = p_hwfn->cdev->chip_num; 13211408cc1fSYuval Mintz pfdev_info->db_size = 0; 13221408cc1fSYuval Mintz pfdev_info->indices_per_sb = PIS_PER_SB; 13231408cc1fSYuval Mintz 13241408cc1fSYuval Mintz pfdev_info->capabilities = PFVF_ACQUIRE_CAP_DEFAULT_UNTAGGED | 13251408cc1fSYuval Mintz PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE; 13261408cc1fSYuval Mintz if (p_hwfn->cdev->num_hwfns > 1) 13271408cc1fSYuval Mintz pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_100G; 13281408cc1fSYuval Mintz 13291cf2b1a9SYuval Mintz qed_iov_vf_mbx_acquire_stats(p_hwfn, &pfdev_info->stats_info); 13301408cc1fSYuval Mintz 13311408cc1fSYuval Mintz memcpy(pfdev_info->port_mac, p_hwfn->hw_info.hw_mac_addr, ETH_ALEN); 13321408cc1fSYuval Mintz 13331408cc1fSYuval Mintz pfdev_info->fw_major = FW_MAJOR_VERSION; 13341408cc1fSYuval Mintz pfdev_info->fw_minor = FW_MINOR_VERSION; 13351408cc1fSYuval Mintz pfdev_info->fw_rev = FW_REVISION_VERSION; 13361408cc1fSYuval Mintz pfdev_info->fw_eng = FW_ENGINEERING_VERSION; 13371fe614d1SYuval Mintz pfdev_info->minor_fp_hsi = min_t(u8, 13381fe614d1SYuval Mintz ETH_HSI_VER_MINOR, 13391fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_minor); 13401408cc1fSYuval Mintz pfdev_info->os_type = VFPF_ACQUIRE_OS_LINUX; 13411408cc1fSYuval Mintz qed_mcp_get_mfw_ver(p_hwfn, p_ptt, &pfdev_info->mfw_ver, NULL); 13421408cc1fSYuval Mintz 13431408cc1fSYuval Mintz pfdev_info->dev_type = p_hwfn->cdev->type; 13441408cc1fSYuval Mintz pfdev_info->chip_rev = p_hwfn->cdev->chip_rev; 13451408cc1fSYuval Mintz 13461cf2b1a9SYuval Mintz /* Fill resources available to VF; Make sure there are enough to 13471cf2b1a9SYuval Mintz * satisfy the VF's request. 13481408cc1fSYuval Mintz */ 13491cf2b1a9SYuval Mintz vfpf_status = qed_iov_vf_mbx_acquire_resc(p_hwfn, p_ptt, vf, 13501cf2b1a9SYuval Mintz &req->resc_request, resc); 13511cf2b1a9SYuval Mintz if (vfpf_status != PFVF_STATUS_SUCCESS) 13521cf2b1a9SYuval Mintz goto out; 13531408cc1fSYuval Mintz 13541fe614d1SYuval Mintz /* Start the VF in FW */ 13551fe614d1SYuval Mintz rc = qed_sp_vf_start(p_hwfn, vf); 13561fe614d1SYuval Mintz if (rc) { 13571fe614d1SYuval Mintz DP_NOTICE(p_hwfn, "Failed to start VF[%02x]\n", vf->abs_vf_id); 13581fe614d1SYuval Mintz vfpf_status = PFVF_STATUS_FAILURE; 13591fe614d1SYuval Mintz goto out; 13601fe614d1SYuval Mintz } 13611fe614d1SYuval Mintz 13621408cc1fSYuval Mintz /* Fill agreed size of bulletin board in response */ 13631408cc1fSYuval Mintz resp->bulletin_size = vf->bulletin.size; 136436558c3dSYuval Mintz qed_iov_post_vf_bulletin(p_hwfn, vf->relative_vf_id, p_ptt); 13651408cc1fSYuval Mintz 13661408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 13671408cc1fSYuval Mintz QED_MSG_IOV, 13681408cc1fSYuval Mintz "VF[%d] ACQUIRE_RESPONSE: pfdev_info- chip_num=0x%x, db_size=%d, idx_per_sb=%d, pf_cap=0x%llx\n" 13691408cc1fSYuval Mintz "resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d\n", 13701408cc1fSYuval Mintz vf->abs_vf_id, 13711408cc1fSYuval Mintz resp->pfdev_info.chip_num, 13721408cc1fSYuval Mintz resp->pfdev_info.db_size, 13731408cc1fSYuval Mintz resp->pfdev_info.indices_per_sb, 13741408cc1fSYuval Mintz resp->pfdev_info.capabilities, 13751408cc1fSYuval Mintz resc->num_rxqs, 13761408cc1fSYuval Mintz resc->num_txqs, 13771408cc1fSYuval Mintz resc->num_sbs, 13781408cc1fSYuval Mintz resc->num_mac_filters, 13791408cc1fSYuval Mintz resc->num_vlan_filters); 13801408cc1fSYuval Mintz vf->state = VF_ACQUIRED; 13811408cc1fSYuval Mintz 13821408cc1fSYuval Mintz /* Prepare Response */ 13831408cc1fSYuval Mintz out: 13841408cc1fSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_ACQUIRE, 13851408cc1fSYuval Mintz sizeof(struct pfvf_acquire_resp_tlv), vfpf_status); 138637bff2b9SYuval Mintz } 138737bff2b9SYuval Mintz 13886ddc7608SYuval Mintz static int __qed_iov_spoofchk_set(struct qed_hwfn *p_hwfn, 13896ddc7608SYuval Mintz struct qed_vf_info *p_vf, bool val) 13906ddc7608SYuval Mintz { 13916ddc7608SYuval Mintz struct qed_sp_vport_update_params params; 13926ddc7608SYuval Mintz int rc; 13936ddc7608SYuval Mintz 13946ddc7608SYuval Mintz if (val == p_vf->spoof_chk) { 13956ddc7608SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 13966ddc7608SYuval Mintz "Spoofchk value[%d] is already configured\n", val); 13976ddc7608SYuval Mintz return 0; 13986ddc7608SYuval Mintz } 13996ddc7608SYuval Mintz 14006ddc7608SYuval Mintz memset(¶ms, 0, sizeof(struct qed_sp_vport_update_params)); 14016ddc7608SYuval Mintz params.opaque_fid = p_vf->opaque_fid; 14026ddc7608SYuval Mintz params.vport_id = p_vf->vport_id; 14036ddc7608SYuval Mintz params.update_anti_spoofing_en_flg = 1; 14046ddc7608SYuval Mintz params.anti_spoofing_en = val; 14056ddc7608SYuval Mintz 14066ddc7608SYuval Mintz rc = qed_sp_vport_update(p_hwfn, ¶ms, QED_SPQ_MODE_EBLOCK, NULL); 1407cb1fa088SYuval Mintz if (!rc) { 14086ddc7608SYuval Mintz p_vf->spoof_chk = val; 14096ddc7608SYuval Mintz p_vf->req_spoofchk_val = p_vf->spoof_chk; 14106ddc7608SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 14116ddc7608SYuval Mintz "Spoofchk val[%d] configured\n", val); 14126ddc7608SYuval Mintz } else { 14136ddc7608SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 14146ddc7608SYuval Mintz "Spoofchk configuration[val:%d] failed for VF[%d]\n", 14156ddc7608SYuval Mintz val, p_vf->relative_vf_id); 14166ddc7608SYuval Mintz } 14176ddc7608SYuval Mintz 14186ddc7608SYuval Mintz return rc; 14196ddc7608SYuval Mintz } 14206ddc7608SYuval Mintz 142108feecd7SYuval Mintz static int qed_iov_reconfigure_unicast_vlan(struct qed_hwfn *p_hwfn, 142208feecd7SYuval Mintz struct qed_vf_info *p_vf) 142308feecd7SYuval Mintz { 142408feecd7SYuval Mintz struct qed_filter_ucast filter; 142508feecd7SYuval Mintz int rc = 0; 142608feecd7SYuval Mintz int i; 142708feecd7SYuval Mintz 142808feecd7SYuval Mintz memset(&filter, 0, sizeof(filter)); 142908feecd7SYuval Mintz filter.is_rx_filter = 1; 143008feecd7SYuval Mintz filter.is_tx_filter = 1; 143108feecd7SYuval Mintz filter.vport_to_add_to = p_vf->vport_id; 143208feecd7SYuval Mintz filter.opcode = QED_FILTER_ADD; 143308feecd7SYuval Mintz 143408feecd7SYuval Mintz /* Reconfigure vlans */ 143508feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) { 143608feecd7SYuval Mintz if (!p_vf->shadow_config.vlans[i].used) 143708feecd7SYuval Mintz continue; 143808feecd7SYuval Mintz 143908feecd7SYuval Mintz filter.type = QED_FILTER_VLAN; 144008feecd7SYuval Mintz filter.vlan = p_vf->shadow_config.vlans[i].vid; 144108feecd7SYuval Mintz DP_VERBOSE(p_hwfn, 144208feecd7SYuval Mintz QED_MSG_IOV, 144308feecd7SYuval Mintz "Reconfiguring VLAN [0x%04x] for VF [%04x]\n", 144408feecd7SYuval Mintz filter.vlan, p_vf->relative_vf_id); 144508feecd7SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, 144608feecd7SYuval Mintz p_vf->opaque_fid, 144708feecd7SYuval Mintz &filter, 144808feecd7SYuval Mintz QED_SPQ_MODE_CB, NULL); 144908feecd7SYuval Mintz if (rc) { 145008feecd7SYuval Mintz DP_NOTICE(p_hwfn, 145108feecd7SYuval Mintz "Failed to configure VLAN [%04x] to VF [%04x]\n", 145208feecd7SYuval Mintz filter.vlan, p_vf->relative_vf_id); 145308feecd7SYuval Mintz break; 145408feecd7SYuval Mintz } 145508feecd7SYuval Mintz } 145608feecd7SYuval Mintz 145708feecd7SYuval Mintz return rc; 145808feecd7SYuval Mintz } 145908feecd7SYuval Mintz 146008feecd7SYuval Mintz static int 146108feecd7SYuval Mintz qed_iov_reconfigure_unicast_shadow(struct qed_hwfn *p_hwfn, 146208feecd7SYuval Mintz struct qed_vf_info *p_vf, u64 events) 146308feecd7SYuval Mintz { 146408feecd7SYuval Mintz int rc = 0; 146508feecd7SYuval Mintz 146608feecd7SYuval Mintz if ((events & (1 << VLAN_ADDR_FORCED)) && 146708feecd7SYuval Mintz !(p_vf->configured_features & (1 << VLAN_ADDR_FORCED))) 146808feecd7SYuval Mintz rc = qed_iov_reconfigure_unicast_vlan(p_hwfn, p_vf); 146908feecd7SYuval Mintz 147008feecd7SYuval Mintz return rc; 147108feecd7SYuval Mintz } 147208feecd7SYuval Mintz 147308feecd7SYuval Mintz static int qed_iov_configure_vport_forced(struct qed_hwfn *p_hwfn, 147408feecd7SYuval Mintz struct qed_vf_info *p_vf, u64 events) 147508feecd7SYuval Mintz { 147608feecd7SYuval Mintz int rc = 0; 147708feecd7SYuval Mintz struct qed_filter_ucast filter; 147808feecd7SYuval Mintz 147908feecd7SYuval Mintz if (!p_vf->vport_instance) 148008feecd7SYuval Mintz return -EINVAL; 148108feecd7SYuval Mintz 1482eff16960SYuval Mintz if (events & (1 << MAC_ADDR_FORCED)) { 1483eff16960SYuval Mintz /* Since there's no way [currently] of removing the MAC, 1484eff16960SYuval Mintz * we can always assume this means we need to force it. 1485eff16960SYuval Mintz */ 1486eff16960SYuval Mintz memset(&filter, 0, sizeof(filter)); 1487eff16960SYuval Mintz filter.type = QED_FILTER_MAC; 1488eff16960SYuval Mintz filter.opcode = QED_FILTER_REPLACE; 1489eff16960SYuval Mintz filter.is_rx_filter = 1; 1490eff16960SYuval Mintz filter.is_tx_filter = 1; 1491eff16960SYuval Mintz filter.vport_to_add_to = p_vf->vport_id; 1492eff16960SYuval Mintz ether_addr_copy(filter.mac, p_vf->bulletin.p_virt->mac); 1493eff16960SYuval Mintz 1494eff16960SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid, 1495eff16960SYuval Mintz &filter, QED_SPQ_MODE_CB, NULL); 1496eff16960SYuval Mintz if (rc) { 1497eff16960SYuval Mintz DP_NOTICE(p_hwfn, 1498eff16960SYuval Mintz "PF failed to configure MAC for VF\n"); 1499eff16960SYuval Mintz return rc; 1500eff16960SYuval Mintz } 1501eff16960SYuval Mintz 1502eff16960SYuval Mintz p_vf->configured_features |= 1 << MAC_ADDR_FORCED; 1503eff16960SYuval Mintz } 1504eff16960SYuval Mintz 150508feecd7SYuval Mintz if (events & (1 << VLAN_ADDR_FORCED)) { 150608feecd7SYuval Mintz struct qed_sp_vport_update_params vport_update; 150708feecd7SYuval Mintz u8 removal; 150808feecd7SYuval Mintz int i; 150908feecd7SYuval Mintz 151008feecd7SYuval Mintz memset(&filter, 0, sizeof(filter)); 151108feecd7SYuval Mintz filter.type = QED_FILTER_VLAN; 151208feecd7SYuval Mintz filter.is_rx_filter = 1; 151308feecd7SYuval Mintz filter.is_tx_filter = 1; 151408feecd7SYuval Mintz filter.vport_to_add_to = p_vf->vport_id; 151508feecd7SYuval Mintz filter.vlan = p_vf->bulletin.p_virt->pvid; 151608feecd7SYuval Mintz filter.opcode = filter.vlan ? QED_FILTER_REPLACE : 151708feecd7SYuval Mintz QED_FILTER_FLUSH; 151808feecd7SYuval Mintz 151908feecd7SYuval Mintz /* Send the ramrod */ 152008feecd7SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid, 152108feecd7SYuval Mintz &filter, QED_SPQ_MODE_CB, NULL); 152208feecd7SYuval Mintz if (rc) { 152308feecd7SYuval Mintz DP_NOTICE(p_hwfn, 152408feecd7SYuval Mintz "PF failed to configure VLAN for VF\n"); 152508feecd7SYuval Mintz return rc; 152608feecd7SYuval Mintz } 152708feecd7SYuval Mintz 152808feecd7SYuval Mintz /* Update the default-vlan & silent vlan stripping */ 152908feecd7SYuval Mintz memset(&vport_update, 0, sizeof(vport_update)); 153008feecd7SYuval Mintz vport_update.opaque_fid = p_vf->opaque_fid; 153108feecd7SYuval Mintz vport_update.vport_id = p_vf->vport_id; 153208feecd7SYuval Mintz vport_update.update_default_vlan_enable_flg = 1; 153308feecd7SYuval Mintz vport_update.default_vlan_enable_flg = filter.vlan ? 1 : 0; 153408feecd7SYuval Mintz vport_update.update_default_vlan_flg = 1; 153508feecd7SYuval Mintz vport_update.default_vlan = filter.vlan; 153608feecd7SYuval Mintz 153708feecd7SYuval Mintz vport_update.update_inner_vlan_removal_flg = 1; 153808feecd7SYuval Mintz removal = filter.vlan ? 1 153908feecd7SYuval Mintz : p_vf->shadow_config.inner_vlan_removal; 154008feecd7SYuval Mintz vport_update.inner_vlan_removal_flg = removal; 154108feecd7SYuval Mintz vport_update.silent_vlan_removal_flg = filter.vlan ? 1 : 0; 154208feecd7SYuval Mintz rc = qed_sp_vport_update(p_hwfn, 154308feecd7SYuval Mintz &vport_update, 154408feecd7SYuval Mintz QED_SPQ_MODE_EBLOCK, NULL); 154508feecd7SYuval Mintz if (rc) { 154608feecd7SYuval Mintz DP_NOTICE(p_hwfn, 154708feecd7SYuval Mintz "PF failed to configure VF vport for vlan\n"); 154808feecd7SYuval Mintz return rc; 154908feecd7SYuval Mintz } 155008feecd7SYuval Mintz 155108feecd7SYuval Mintz /* Update all the Rx queues */ 155208feecd7SYuval Mintz for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++) { 155308feecd7SYuval Mintz u16 qid; 155408feecd7SYuval Mintz 155508feecd7SYuval Mintz if (!p_vf->vf_queues[i].rxq_active) 155608feecd7SYuval Mintz continue; 155708feecd7SYuval Mintz 155808feecd7SYuval Mintz qid = p_vf->vf_queues[i].fw_rx_qid; 155908feecd7SYuval Mintz 156008feecd7SYuval Mintz rc = qed_sp_eth_rx_queues_update(p_hwfn, qid, 156108feecd7SYuval Mintz 1, 0, 1, 156208feecd7SYuval Mintz QED_SPQ_MODE_EBLOCK, 156308feecd7SYuval Mintz NULL); 156408feecd7SYuval Mintz if (rc) { 156508feecd7SYuval Mintz DP_NOTICE(p_hwfn, 156608feecd7SYuval Mintz "Failed to send Rx update fo queue[0x%04x]\n", 156708feecd7SYuval Mintz qid); 156808feecd7SYuval Mintz return rc; 156908feecd7SYuval Mintz } 157008feecd7SYuval Mintz } 157108feecd7SYuval Mintz 157208feecd7SYuval Mintz if (filter.vlan) 157308feecd7SYuval Mintz p_vf->configured_features |= 1 << VLAN_ADDR_FORCED; 157408feecd7SYuval Mintz else 157508feecd7SYuval Mintz p_vf->configured_features &= ~(1 << VLAN_ADDR_FORCED); 157608feecd7SYuval Mintz } 157708feecd7SYuval Mintz 157808feecd7SYuval Mintz /* If forced features are terminated, we need to configure the shadow 157908feecd7SYuval Mintz * configuration back again. 158008feecd7SYuval Mintz */ 158108feecd7SYuval Mintz if (events) 158208feecd7SYuval Mintz qed_iov_reconfigure_unicast_shadow(p_hwfn, p_vf, events); 158308feecd7SYuval Mintz 158408feecd7SYuval Mintz return rc; 158508feecd7SYuval Mintz } 158608feecd7SYuval Mintz 1587dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn, 1588dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1589dacd88d6SYuval Mintz struct qed_vf_info *vf) 1590dacd88d6SYuval Mintz { 1591dacd88d6SYuval Mintz struct qed_sp_vport_start_params params = { 0 }; 1592dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 1593dacd88d6SYuval Mintz struct vfpf_vport_start_tlv *start; 1594dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 1595dacd88d6SYuval Mintz struct qed_vf_info *vf_info; 159608feecd7SYuval Mintz u64 *p_bitmap; 1597dacd88d6SYuval Mintz int sb_id; 1598dacd88d6SYuval Mintz int rc; 1599dacd88d6SYuval Mintz 1600dacd88d6SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vf->relative_vf_id, true); 1601dacd88d6SYuval Mintz if (!vf_info) { 1602dacd88d6SYuval Mintz DP_NOTICE(p_hwfn->cdev, 1603dacd88d6SYuval Mintz "Failed to get VF info, invalid vfid [%d]\n", 1604dacd88d6SYuval Mintz vf->relative_vf_id); 1605dacd88d6SYuval Mintz return; 1606dacd88d6SYuval Mintz } 1607dacd88d6SYuval Mintz 1608dacd88d6SYuval Mintz vf->state = VF_ENABLED; 1609dacd88d6SYuval Mintz start = &mbx->req_virt->start_vport; 1610dacd88d6SYuval Mintz 1611dacd88d6SYuval Mintz /* Initialize Status block in CAU */ 1612dacd88d6SYuval Mintz for (sb_id = 0; sb_id < vf->num_sbs; sb_id++) { 1613dacd88d6SYuval Mintz if (!start->sb_addr[sb_id]) { 1614dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1615dacd88d6SYuval Mintz "VF[%d] did not fill the address of SB %d\n", 1616dacd88d6SYuval Mintz vf->relative_vf_id, sb_id); 1617dacd88d6SYuval Mintz break; 1618dacd88d6SYuval Mintz } 1619dacd88d6SYuval Mintz 1620dacd88d6SYuval Mintz qed_int_cau_conf_sb(p_hwfn, p_ptt, 1621dacd88d6SYuval Mintz start->sb_addr[sb_id], 1622dacd88d6SYuval Mintz vf->igu_sbs[sb_id], 1623dacd88d6SYuval Mintz vf->abs_vf_id, 1); 1624dacd88d6SYuval Mintz } 1625dacd88d6SYuval Mintz qed_iov_enable_vf_traffic(p_hwfn, p_ptt, vf); 1626dacd88d6SYuval Mintz 1627dacd88d6SYuval Mintz vf->mtu = start->mtu; 162808feecd7SYuval Mintz vf->shadow_config.inner_vlan_removal = start->inner_vlan_removal; 162908feecd7SYuval Mintz 163008feecd7SYuval Mintz /* Take into consideration configuration forced by hypervisor; 163108feecd7SYuval Mintz * If none is configured, use the supplied VF values [for old 163208feecd7SYuval Mintz * vfs that would still be fine, since they passed '0' as padding]. 163308feecd7SYuval Mintz */ 163408feecd7SYuval Mintz p_bitmap = &vf_info->bulletin.p_virt->valid_bitmap; 163508feecd7SYuval Mintz if (!(*p_bitmap & (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED))) { 163608feecd7SYuval Mintz u8 vf_req = start->only_untagged; 163708feecd7SYuval Mintz 163808feecd7SYuval Mintz vf_info->bulletin.p_virt->default_only_untagged = vf_req; 163908feecd7SYuval Mintz *p_bitmap |= 1 << VFPF_BULLETIN_UNTAGGED_DEFAULT; 164008feecd7SYuval Mintz } 1641dacd88d6SYuval Mintz 1642dacd88d6SYuval Mintz params.tpa_mode = start->tpa_mode; 1643dacd88d6SYuval Mintz params.remove_inner_vlan = start->inner_vlan_removal; 1644831bfb0eSYuval Mintz params.tx_switching = true; 1645dacd88d6SYuval Mintz 164608feecd7SYuval Mintz params.only_untagged = vf_info->bulletin.p_virt->default_only_untagged; 1647dacd88d6SYuval Mintz params.drop_ttl0 = false; 1648dacd88d6SYuval Mintz params.concrete_fid = vf->concrete_fid; 1649dacd88d6SYuval Mintz params.opaque_fid = vf->opaque_fid; 1650dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 1651dacd88d6SYuval Mintz params.max_buffers_per_cqe = start->max_buffers_per_cqe; 1652dacd88d6SYuval Mintz params.mtu = vf->mtu; 1653dacd88d6SYuval Mintz 1654dacd88d6SYuval Mintz rc = qed_sp_eth_vport_start(p_hwfn, ¶ms); 1655dacd88d6SYuval Mintz if (rc != 0) { 1656dacd88d6SYuval Mintz DP_ERR(p_hwfn, 1657dacd88d6SYuval Mintz "qed_iov_vf_mbx_start_vport returned error %d\n", rc); 1658dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1659dacd88d6SYuval Mintz } else { 1660dacd88d6SYuval Mintz vf->vport_instance++; 166108feecd7SYuval Mintz 166208feecd7SYuval Mintz /* Force configuration if needed on the newly opened vport */ 166308feecd7SYuval Mintz qed_iov_configure_vport_forced(p_hwfn, vf, *p_bitmap); 16646ddc7608SYuval Mintz 16656ddc7608SYuval Mintz __qed_iov_spoofchk_set(p_hwfn, vf, vf->req_spoofchk_val); 1666dacd88d6SYuval Mintz } 1667dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_START, 1668dacd88d6SYuval Mintz sizeof(struct pfvf_def_resp_tlv), status); 1669dacd88d6SYuval Mintz } 1670dacd88d6SYuval Mintz 1671dacd88d6SYuval Mintz static void qed_iov_vf_mbx_stop_vport(struct qed_hwfn *p_hwfn, 1672dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1673dacd88d6SYuval Mintz struct qed_vf_info *vf) 1674dacd88d6SYuval Mintz { 1675dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 1676dacd88d6SYuval Mintz int rc; 1677dacd88d6SYuval Mintz 1678dacd88d6SYuval Mintz vf->vport_instance--; 16796ddc7608SYuval Mintz vf->spoof_chk = false; 1680dacd88d6SYuval Mintz 1681dacd88d6SYuval Mintz rc = qed_sp_vport_stop(p_hwfn, vf->opaque_fid, vf->vport_id); 1682dacd88d6SYuval Mintz if (rc != 0) { 1683dacd88d6SYuval Mintz DP_ERR(p_hwfn, "qed_iov_vf_mbx_stop_vport returned error %d\n", 1684dacd88d6SYuval Mintz rc); 1685dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1686dacd88d6SYuval Mintz } 1687dacd88d6SYuval Mintz 168808feecd7SYuval Mintz /* Forget the configuration on the vport */ 168908feecd7SYuval Mintz vf->configured_features = 0; 169008feecd7SYuval Mintz memset(&vf->shadow_config, 0, sizeof(vf->shadow_config)); 169108feecd7SYuval Mintz 1692dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_TEARDOWN, 1693dacd88d6SYuval Mintz sizeof(struct pfvf_def_resp_tlv), status); 1694dacd88d6SYuval Mintz } 1695dacd88d6SYuval Mintz 1696dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_rxq_resp(struct qed_hwfn *p_hwfn, 1697dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1698dacd88d6SYuval Mintz struct qed_vf_info *vf, u8 status) 1699dacd88d6SYuval Mintz { 1700dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 1701dacd88d6SYuval Mintz struct pfvf_start_queue_resp_tlv *p_tlv; 1702dacd88d6SYuval Mintz struct vfpf_start_rxq_tlv *req; 1703dacd88d6SYuval Mintz 1704dacd88d6SYuval Mintz mbx->offset = (u8 *)mbx->reply_virt; 1705dacd88d6SYuval Mintz 1706dacd88d6SYuval Mintz p_tlv = qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_START_RXQ, 1707dacd88d6SYuval Mintz sizeof(*p_tlv)); 1708dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 1709dacd88d6SYuval Mintz sizeof(struct channel_list_end_tlv)); 1710dacd88d6SYuval Mintz 1711dacd88d6SYuval Mintz /* Update the TLV with the response */ 1712dacd88d6SYuval Mintz if (status == PFVF_STATUS_SUCCESS) { 1713dacd88d6SYuval Mintz req = &mbx->req_virt->start_rxq; 1714351a4dedSYuval Mintz p_tlv->offset = PXP_VF_BAR0_START_MSDM_ZONE_B + 1715351a4dedSYuval Mintz offsetof(struct mstorm_vf_zone, 1716351a4dedSYuval Mintz non_trigger.eth_rx_queue_producers) + 1717351a4dedSYuval Mintz sizeof(struct eth_rx_prod_data) * req->rx_qid; 1718dacd88d6SYuval Mintz } 1719dacd88d6SYuval Mintz 1720dacd88d6SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, vf, sizeof(*p_tlv), status); 1721dacd88d6SYuval Mintz } 1722dacd88d6SYuval Mintz 1723dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn, 1724dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1725dacd88d6SYuval Mintz struct qed_vf_info *vf) 1726dacd88d6SYuval Mintz { 1727dacd88d6SYuval Mintz struct qed_queue_start_common_params params; 1728dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 172941086467SYuval Mintz u8 status = PFVF_STATUS_NO_RESOURCE; 1730dacd88d6SYuval Mintz struct vfpf_start_rxq_tlv *req; 1731dacd88d6SYuval Mintz int rc; 1732dacd88d6SYuval Mintz 1733dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(params)); 1734dacd88d6SYuval Mintz req = &mbx->req_virt->start_rxq; 173541086467SYuval Mintz 173641086467SYuval Mintz if (!qed_iov_validate_rxq(p_hwfn, vf, req->rx_qid) || 173741086467SYuval Mintz !qed_iov_validate_sb(p_hwfn, vf, req->hw_sb)) 173841086467SYuval Mintz goto out; 173941086467SYuval Mintz 1740dacd88d6SYuval Mintz params.queue_id = vf->vf_queues[req->rx_qid].fw_rx_qid; 1741351a4dedSYuval Mintz params.vf_qid = req->rx_qid; 1742dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 1743dacd88d6SYuval Mintz params.sb = req->hw_sb; 1744dacd88d6SYuval Mintz params.sb_idx = req->sb_index; 1745dacd88d6SYuval Mintz 1746dacd88d6SYuval Mintz rc = qed_sp_eth_rxq_start_ramrod(p_hwfn, vf->opaque_fid, 1747dacd88d6SYuval Mintz vf->vf_queues[req->rx_qid].fw_cid, 1748dacd88d6SYuval Mintz ¶ms, 1749dacd88d6SYuval Mintz vf->abs_vf_id + 0x10, 1750dacd88d6SYuval Mintz req->bd_max_bytes, 1751dacd88d6SYuval Mintz req->rxq_addr, 1752dacd88d6SYuval Mintz req->cqe_pbl_addr, req->cqe_pbl_size); 1753dacd88d6SYuval Mintz 1754dacd88d6SYuval Mintz if (rc) { 1755dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1756dacd88d6SYuval Mintz } else { 175741086467SYuval Mintz status = PFVF_STATUS_SUCCESS; 1758dacd88d6SYuval Mintz vf->vf_queues[req->rx_qid].rxq_active = true; 1759dacd88d6SYuval Mintz vf->num_active_rxqs++; 1760dacd88d6SYuval Mintz } 1761dacd88d6SYuval Mintz 176241086467SYuval Mintz out: 1763dacd88d6SYuval Mintz qed_iov_vf_mbx_start_rxq_resp(p_hwfn, p_ptt, vf, status); 1764dacd88d6SYuval Mintz } 1765dacd88d6SYuval Mintz 17665040acf5SYuval Mintz static void qed_iov_vf_mbx_start_txq_resp(struct qed_hwfn *p_hwfn, 17675040acf5SYuval Mintz struct qed_ptt *p_ptt, 17685040acf5SYuval Mintz struct qed_vf_info *p_vf, u8 status) 17695040acf5SYuval Mintz { 17705040acf5SYuval Mintz struct qed_iov_vf_mbx *mbx = &p_vf->vf_mbx; 17715040acf5SYuval Mintz struct pfvf_start_queue_resp_tlv *p_tlv; 17725040acf5SYuval Mintz 17735040acf5SYuval Mintz mbx->offset = (u8 *)mbx->reply_virt; 17745040acf5SYuval Mintz 17755040acf5SYuval Mintz p_tlv = qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_START_TXQ, 17765040acf5SYuval Mintz sizeof(*p_tlv)); 17775040acf5SYuval Mintz qed_add_tlv(p_hwfn, &mbx->offset, CHANNEL_TLV_LIST_END, 17785040acf5SYuval Mintz sizeof(struct channel_list_end_tlv)); 17795040acf5SYuval Mintz 17805040acf5SYuval Mintz /* Update the TLV with the response */ 17815040acf5SYuval Mintz if (status == PFVF_STATUS_SUCCESS) { 17825040acf5SYuval Mintz u16 qid = mbx->req_virt->start_txq.tx_qid; 17835040acf5SYuval Mintz 17845040acf5SYuval Mintz p_tlv->offset = qed_db_addr(p_vf->vf_queues[qid].fw_cid, 17855040acf5SYuval Mintz DQ_DEMS_LEGACY); 17865040acf5SYuval Mintz } 17875040acf5SYuval Mintz 17885040acf5SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_tlv), status); 17895040acf5SYuval Mintz } 17905040acf5SYuval Mintz 1791dacd88d6SYuval Mintz static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn, 1792dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1793dacd88d6SYuval Mintz struct qed_vf_info *vf) 1794dacd88d6SYuval Mintz { 1795dacd88d6SYuval Mintz struct qed_queue_start_common_params params; 1796dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 179741086467SYuval Mintz u8 status = PFVF_STATUS_NO_RESOURCE; 1798dacd88d6SYuval Mintz union qed_qm_pq_params pq_params; 1799dacd88d6SYuval Mintz struct vfpf_start_txq_tlv *req; 1800dacd88d6SYuval Mintz int rc; 1801dacd88d6SYuval Mintz 1802dacd88d6SYuval Mintz /* Prepare the parameters which would choose the right PQ */ 1803dacd88d6SYuval Mintz memset(&pq_params, 0, sizeof(pq_params)); 1804dacd88d6SYuval Mintz pq_params.eth.is_vf = 1; 1805dacd88d6SYuval Mintz pq_params.eth.vf_id = vf->relative_vf_id; 1806dacd88d6SYuval Mintz 1807dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(params)); 1808dacd88d6SYuval Mintz req = &mbx->req_virt->start_txq; 180941086467SYuval Mintz 181041086467SYuval Mintz if (!qed_iov_validate_txq(p_hwfn, vf, req->tx_qid) || 181141086467SYuval Mintz !qed_iov_validate_sb(p_hwfn, vf, req->hw_sb)) 181241086467SYuval Mintz goto out; 181341086467SYuval Mintz 1814dacd88d6SYuval Mintz params.queue_id = vf->vf_queues[req->tx_qid].fw_tx_qid; 1815dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 1816dacd88d6SYuval Mintz params.sb = req->hw_sb; 1817dacd88d6SYuval Mintz params.sb_idx = req->sb_index; 1818dacd88d6SYuval Mintz 1819dacd88d6SYuval Mintz rc = qed_sp_eth_txq_start_ramrod(p_hwfn, 1820dacd88d6SYuval Mintz vf->opaque_fid, 1821dacd88d6SYuval Mintz vf->vf_queues[req->tx_qid].fw_cid, 1822dacd88d6SYuval Mintz ¶ms, 1823dacd88d6SYuval Mintz vf->abs_vf_id + 0x10, 1824dacd88d6SYuval Mintz req->pbl_addr, 1825dacd88d6SYuval Mintz req->pbl_size, &pq_params); 1826dacd88d6SYuval Mintz 182741086467SYuval Mintz if (rc) { 1828dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 182941086467SYuval Mintz } else { 183041086467SYuval Mintz status = PFVF_STATUS_SUCCESS; 1831dacd88d6SYuval Mintz vf->vf_queues[req->tx_qid].txq_active = true; 183241086467SYuval Mintz } 1833dacd88d6SYuval Mintz 183441086467SYuval Mintz out: 18355040acf5SYuval Mintz qed_iov_vf_mbx_start_txq_resp(p_hwfn, p_ptt, vf, status); 1836dacd88d6SYuval Mintz } 1837dacd88d6SYuval Mintz 1838dacd88d6SYuval Mintz static int qed_iov_vf_stop_rxqs(struct qed_hwfn *p_hwfn, 1839dacd88d6SYuval Mintz struct qed_vf_info *vf, 1840dacd88d6SYuval Mintz u16 rxq_id, u8 num_rxqs, bool cqe_completion) 1841dacd88d6SYuval Mintz { 1842dacd88d6SYuval Mintz int rc = 0; 1843dacd88d6SYuval Mintz int qid; 1844dacd88d6SYuval Mintz 1845dacd88d6SYuval Mintz if (rxq_id + num_rxqs > ARRAY_SIZE(vf->vf_queues)) 1846dacd88d6SYuval Mintz return -EINVAL; 1847dacd88d6SYuval Mintz 1848dacd88d6SYuval Mintz for (qid = rxq_id; qid < rxq_id + num_rxqs; qid++) { 1849dacd88d6SYuval Mintz if (vf->vf_queues[qid].rxq_active) { 1850dacd88d6SYuval Mintz rc = qed_sp_eth_rx_queue_stop(p_hwfn, 1851dacd88d6SYuval Mintz vf->vf_queues[qid]. 1852dacd88d6SYuval Mintz fw_rx_qid, false, 1853dacd88d6SYuval Mintz cqe_completion); 1854dacd88d6SYuval Mintz 1855dacd88d6SYuval Mintz if (rc) 1856dacd88d6SYuval Mintz return rc; 1857dacd88d6SYuval Mintz } 1858dacd88d6SYuval Mintz vf->vf_queues[qid].rxq_active = false; 1859dacd88d6SYuval Mintz vf->num_active_rxqs--; 1860dacd88d6SYuval Mintz } 1861dacd88d6SYuval Mintz 1862dacd88d6SYuval Mintz return rc; 1863dacd88d6SYuval Mintz } 1864dacd88d6SYuval Mintz 1865dacd88d6SYuval Mintz static int qed_iov_vf_stop_txqs(struct qed_hwfn *p_hwfn, 1866dacd88d6SYuval Mintz struct qed_vf_info *vf, u16 txq_id, u8 num_txqs) 1867dacd88d6SYuval Mintz { 1868dacd88d6SYuval Mintz int rc = 0; 1869dacd88d6SYuval Mintz int qid; 1870dacd88d6SYuval Mintz 1871dacd88d6SYuval Mintz if (txq_id + num_txqs > ARRAY_SIZE(vf->vf_queues)) 1872dacd88d6SYuval Mintz return -EINVAL; 1873dacd88d6SYuval Mintz 1874dacd88d6SYuval Mintz for (qid = txq_id; qid < txq_id + num_txqs; qid++) { 1875dacd88d6SYuval Mintz if (vf->vf_queues[qid].txq_active) { 1876dacd88d6SYuval Mintz rc = qed_sp_eth_tx_queue_stop(p_hwfn, 1877dacd88d6SYuval Mintz vf->vf_queues[qid]. 1878dacd88d6SYuval Mintz fw_tx_qid); 1879dacd88d6SYuval Mintz 1880dacd88d6SYuval Mintz if (rc) 1881dacd88d6SYuval Mintz return rc; 1882dacd88d6SYuval Mintz } 1883dacd88d6SYuval Mintz vf->vf_queues[qid].txq_active = false; 1884dacd88d6SYuval Mintz } 1885dacd88d6SYuval Mintz return rc; 1886dacd88d6SYuval Mintz } 1887dacd88d6SYuval Mintz 1888dacd88d6SYuval Mintz static void qed_iov_vf_mbx_stop_rxqs(struct qed_hwfn *p_hwfn, 1889dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1890dacd88d6SYuval Mintz struct qed_vf_info *vf) 1891dacd88d6SYuval Mintz { 1892dacd88d6SYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 1893dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 1894dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 1895dacd88d6SYuval Mintz struct vfpf_stop_rxqs_tlv *req; 1896dacd88d6SYuval Mintz int rc; 1897dacd88d6SYuval Mintz 1898dacd88d6SYuval Mintz /* We give the option of starting from qid != 0, in this case we 1899dacd88d6SYuval Mintz * need to make sure that qid + num_qs doesn't exceed the actual 1900dacd88d6SYuval Mintz * amount of queues that exist. 1901dacd88d6SYuval Mintz */ 1902dacd88d6SYuval Mintz req = &mbx->req_virt->stop_rxqs; 1903dacd88d6SYuval Mintz rc = qed_iov_vf_stop_rxqs(p_hwfn, vf, req->rx_qid, 1904dacd88d6SYuval Mintz req->num_rxqs, req->cqe_completion); 1905dacd88d6SYuval Mintz if (rc) 1906dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1907dacd88d6SYuval Mintz 1908dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_RXQS, 1909dacd88d6SYuval Mintz length, status); 1910dacd88d6SYuval Mintz } 1911dacd88d6SYuval Mintz 1912dacd88d6SYuval Mintz static void qed_iov_vf_mbx_stop_txqs(struct qed_hwfn *p_hwfn, 1913dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 1914dacd88d6SYuval Mintz struct qed_vf_info *vf) 1915dacd88d6SYuval Mintz { 1916dacd88d6SYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 1917dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 1918dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 1919dacd88d6SYuval Mintz struct vfpf_stop_txqs_tlv *req; 1920dacd88d6SYuval Mintz int rc; 1921dacd88d6SYuval Mintz 1922dacd88d6SYuval Mintz /* We give the option of starting from qid != 0, in this case we 1923dacd88d6SYuval Mintz * need to make sure that qid + num_qs doesn't exceed the actual 1924dacd88d6SYuval Mintz * amount of queues that exist. 1925dacd88d6SYuval Mintz */ 1926dacd88d6SYuval Mintz req = &mbx->req_virt->stop_txqs; 1927dacd88d6SYuval Mintz rc = qed_iov_vf_stop_txqs(p_hwfn, vf, req->tx_qid, req->num_txqs); 1928dacd88d6SYuval Mintz if (rc) 1929dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 1930dacd88d6SYuval Mintz 1931dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_TXQS, 1932dacd88d6SYuval Mintz length, status); 1933dacd88d6SYuval Mintz } 1934dacd88d6SYuval Mintz 193517b235c1SYuval Mintz static void qed_iov_vf_mbx_update_rxqs(struct qed_hwfn *p_hwfn, 193617b235c1SYuval Mintz struct qed_ptt *p_ptt, 193717b235c1SYuval Mintz struct qed_vf_info *vf) 193817b235c1SYuval Mintz { 193917b235c1SYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 194017b235c1SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 194117b235c1SYuval Mintz struct vfpf_update_rxq_tlv *req; 194217b235c1SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 194317b235c1SYuval Mintz u8 complete_event_flg; 194417b235c1SYuval Mintz u8 complete_cqe_flg; 194517b235c1SYuval Mintz u16 qid; 194617b235c1SYuval Mintz int rc; 194717b235c1SYuval Mintz u8 i; 194817b235c1SYuval Mintz 194917b235c1SYuval Mintz req = &mbx->req_virt->update_rxq; 195017b235c1SYuval Mintz complete_cqe_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_CQE_FLAG); 195117b235c1SYuval Mintz complete_event_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_EVENT_FLAG); 195217b235c1SYuval Mintz 195317b235c1SYuval Mintz for (i = 0; i < req->num_rxqs; i++) { 195417b235c1SYuval Mintz qid = req->rx_qid + i; 195517b235c1SYuval Mintz 195617b235c1SYuval Mintz if (!vf->vf_queues[qid].rxq_active) { 195717b235c1SYuval Mintz DP_NOTICE(p_hwfn, "VF rx_qid = %d isn`t active!\n", 195817b235c1SYuval Mintz qid); 195917b235c1SYuval Mintz status = PFVF_STATUS_FAILURE; 196017b235c1SYuval Mintz break; 196117b235c1SYuval Mintz } 196217b235c1SYuval Mintz 196317b235c1SYuval Mintz rc = qed_sp_eth_rx_queues_update(p_hwfn, 196417b235c1SYuval Mintz vf->vf_queues[qid].fw_rx_qid, 196517b235c1SYuval Mintz 1, 196617b235c1SYuval Mintz complete_cqe_flg, 196717b235c1SYuval Mintz complete_event_flg, 196817b235c1SYuval Mintz QED_SPQ_MODE_EBLOCK, NULL); 196917b235c1SYuval Mintz 197017b235c1SYuval Mintz if (rc) { 197117b235c1SYuval Mintz status = PFVF_STATUS_FAILURE; 197217b235c1SYuval Mintz break; 197317b235c1SYuval Mintz } 197417b235c1SYuval Mintz } 197517b235c1SYuval Mintz 197617b235c1SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UPDATE_RXQ, 197717b235c1SYuval Mintz length, status); 197817b235c1SYuval Mintz } 197917b235c1SYuval Mintz 1980dacd88d6SYuval Mintz void *qed_iov_search_list_tlvs(struct qed_hwfn *p_hwfn, 1981dacd88d6SYuval Mintz void *p_tlvs_list, u16 req_type) 1982dacd88d6SYuval Mintz { 1983dacd88d6SYuval Mintz struct channel_tlv *p_tlv = (struct channel_tlv *)p_tlvs_list; 1984dacd88d6SYuval Mintz int len = 0; 1985dacd88d6SYuval Mintz 1986dacd88d6SYuval Mintz do { 1987dacd88d6SYuval Mintz if (!p_tlv->length) { 1988dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, "Zero length TLV found\n"); 1989dacd88d6SYuval Mintz return NULL; 1990dacd88d6SYuval Mintz } 1991dacd88d6SYuval Mintz 1992dacd88d6SYuval Mintz if (p_tlv->type == req_type) { 1993dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1994dacd88d6SYuval Mintz "Extended tlv type %d, length %d found\n", 1995dacd88d6SYuval Mintz p_tlv->type, p_tlv->length); 1996dacd88d6SYuval Mintz return p_tlv; 1997dacd88d6SYuval Mintz } 1998dacd88d6SYuval Mintz 1999dacd88d6SYuval Mintz len += p_tlv->length; 2000dacd88d6SYuval Mintz p_tlv = (struct channel_tlv *)((u8 *)p_tlv + p_tlv->length); 2001dacd88d6SYuval Mintz 2002dacd88d6SYuval Mintz if ((len + p_tlv->length) > TLV_BUFFER_SIZE) { 2003dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, "TLVs has overrun the buffer size\n"); 2004dacd88d6SYuval Mintz return NULL; 2005dacd88d6SYuval Mintz } 2006dacd88d6SYuval Mintz } while (p_tlv->type != CHANNEL_TLV_LIST_END); 2007dacd88d6SYuval Mintz 2008dacd88d6SYuval Mintz return NULL; 2009dacd88d6SYuval Mintz } 2010dacd88d6SYuval Mintz 2011dacd88d6SYuval Mintz static void 2012dacd88d6SYuval Mintz qed_iov_vp_update_act_param(struct qed_hwfn *p_hwfn, 2013dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2014dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2015dacd88d6SYuval Mintz { 2016dacd88d6SYuval Mintz struct vfpf_vport_update_activate_tlv *p_act_tlv; 2017dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE; 2018dacd88d6SYuval Mintz 2019dacd88d6SYuval Mintz p_act_tlv = (struct vfpf_vport_update_activate_tlv *) 2020dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2021dacd88d6SYuval Mintz if (!p_act_tlv) 2022dacd88d6SYuval Mintz return; 2023dacd88d6SYuval Mintz 2024dacd88d6SYuval Mintz p_data->update_vport_active_rx_flg = p_act_tlv->update_rx; 2025dacd88d6SYuval Mintz p_data->vport_active_rx_flg = p_act_tlv->active_rx; 2026dacd88d6SYuval Mintz p_data->update_vport_active_tx_flg = p_act_tlv->update_tx; 2027dacd88d6SYuval Mintz p_data->vport_active_tx_flg = p_act_tlv->active_tx; 2028dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_ACTIVATE; 2029dacd88d6SYuval Mintz } 2030dacd88d6SYuval Mintz 2031dacd88d6SYuval Mintz static void 203217b235c1SYuval Mintz qed_iov_vp_update_vlan_param(struct qed_hwfn *p_hwfn, 203317b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 203417b235c1SYuval Mintz struct qed_vf_info *p_vf, 203517b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 203617b235c1SYuval Mintz { 203717b235c1SYuval Mintz struct vfpf_vport_update_vlan_strip_tlv *p_vlan_tlv; 203817b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP; 203917b235c1SYuval Mintz 204017b235c1SYuval Mintz p_vlan_tlv = (struct vfpf_vport_update_vlan_strip_tlv *) 204117b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 204217b235c1SYuval Mintz if (!p_vlan_tlv) 204317b235c1SYuval Mintz return; 204417b235c1SYuval Mintz 204508feecd7SYuval Mintz p_vf->shadow_config.inner_vlan_removal = p_vlan_tlv->remove_vlan; 204608feecd7SYuval Mintz 204708feecd7SYuval Mintz /* Ignore the VF request if we're forcing a vlan */ 204808feecd7SYuval Mintz if (!(p_vf->configured_features & (1 << VLAN_ADDR_FORCED))) { 204917b235c1SYuval Mintz p_data->update_inner_vlan_removal_flg = 1; 205017b235c1SYuval Mintz p_data->inner_vlan_removal_flg = p_vlan_tlv->remove_vlan; 205108feecd7SYuval Mintz } 205217b235c1SYuval Mintz 205317b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_VLAN_STRIP; 205417b235c1SYuval Mintz } 205517b235c1SYuval Mintz 205617b235c1SYuval Mintz static void 205717b235c1SYuval Mintz qed_iov_vp_update_tx_switch(struct qed_hwfn *p_hwfn, 205817b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 205917b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 206017b235c1SYuval Mintz { 206117b235c1SYuval Mintz struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv; 206217b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; 206317b235c1SYuval Mintz 206417b235c1SYuval Mintz p_tx_switch_tlv = (struct vfpf_vport_update_tx_switch_tlv *) 206517b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, 206617b235c1SYuval Mintz tlv); 206717b235c1SYuval Mintz if (!p_tx_switch_tlv) 206817b235c1SYuval Mintz return; 206917b235c1SYuval Mintz 207017b235c1SYuval Mintz p_data->update_tx_switching_flg = 1; 207117b235c1SYuval Mintz p_data->tx_switching_flg = p_tx_switch_tlv->tx_switching; 207217b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_TX_SWITCH; 207317b235c1SYuval Mintz } 207417b235c1SYuval Mintz 207517b235c1SYuval Mintz static void 2076dacd88d6SYuval Mintz qed_iov_vp_update_mcast_bin_param(struct qed_hwfn *p_hwfn, 2077dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2078dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2079dacd88d6SYuval Mintz { 2080dacd88d6SYuval Mintz struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv; 2081dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_MCAST; 2082dacd88d6SYuval Mintz 2083dacd88d6SYuval Mintz p_mcast_tlv = (struct vfpf_vport_update_mcast_bin_tlv *) 2084dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2085dacd88d6SYuval Mintz if (!p_mcast_tlv) 2086dacd88d6SYuval Mintz return; 2087dacd88d6SYuval Mintz 2088dacd88d6SYuval Mintz p_data->update_approx_mcast_flg = 1; 2089dacd88d6SYuval Mintz memcpy(p_data->bins, p_mcast_tlv->bins, 2090dacd88d6SYuval Mintz sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS); 2091dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_MCAST; 2092dacd88d6SYuval Mintz } 2093dacd88d6SYuval Mintz 2094dacd88d6SYuval Mintz static void 2095dacd88d6SYuval Mintz qed_iov_vp_update_accept_flag(struct qed_hwfn *p_hwfn, 2096dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2097dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2098dacd88d6SYuval Mintz { 2099dacd88d6SYuval Mintz struct qed_filter_accept_flags *p_flags = &p_data->accept_flags; 2100dacd88d6SYuval Mintz struct vfpf_vport_update_accept_param_tlv *p_accept_tlv; 2101dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; 2102dacd88d6SYuval Mintz 2103dacd88d6SYuval Mintz p_accept_tlv = (struct vfpf_vport_update_accept_param_tlv *) 2104dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2105dacd88d6SYuval Mintz if (!p_accept_tlv) 2106dacd88d6SYuval Mintz return; 2107dacd88d6SYuval Mintz 2108dacd88d6SYuval Mintz p_flags->update_rx_mode_config = p_accept_tlv->update_rx_mode; 2109dacd88d6SYuval Mintz p_flags->rx_accept_filter = p_accept_tlv->rx_accept_filter; 2110dacd88d6SYuval Mintz p_flags->update_tx_mode_config = p_accept_tlv->update_tx_mode; 2111dacd88d6SYuval Mintz p_flags->tx_accept_filter = p_accept_tlv->tx_accept_filter; 2112dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_ACCEPT_PARAM; 2113dacd88d6SYuval Mintz } 2114dacd88d6SYuval Mintz 2115dacd88d6SYuval Mintz static void 211617b235c1SYuval Mintz qed_iov_vp_update_accept_any_vlan(struct qed_hwfn *p_hwfn, 211717b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 211817b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 211917b235c1SYuval Mintz { 212017b235c1SYuval Mintz struct vfpf_vport_update_accept_any_vlan_tlv *p_accept_any_vlan; 212117b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; 212217b235c1SYuval Mintz 212317b235c1SYuval Mintz p_accept_any_vlan = (struct vfpf_vport_update_accept_any_vlan_tlv *) 212417b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, 212517b235c1SYuval Mintz tlv); 212617b235c1SYuval Mintz if (!p_accept_any_vlan) 212717b235c1SYuval Mintz return; 212817b235c1SYuval Mintz 212917b235c1SYuval Mintz p_data->accept_any_vlan = p_accept_any_vlan->accept_any_vlan; 213017b235c1SYuval Mintz p_data->update_accept_any_vlan_flg = 213117b235c1SYuval Mintz p_accept_any_vlan->update_accept_any_vlan_flg; 213217b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_ACCEPT_ANY_VLAN; 213317b235c1SYuval Mintz } 213417b235c1SYuval Mintz 213517b235c1SYuval Mintz static void 2136dacd88d6SYuval Mintz qed_iov_vp_update_rss_param(struct qed_hwfn *p_hwfn, 2137dacd88d6SYuval Mintz struct qed_vf_info *vf, 2138dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 2139dacd88d6SYuval Mintz struct qed_rss_params *p_rss, 2140dacd88d6SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 2141dacd88d6SYuval Mintz { 2142dacd88d6SYuval Mintz struct vfpf_vport_update_rss_tlv *p_rss_tlv; 2143dacd88d6SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_RSS; 2144dacd88d6SYuval Mintz u16 i, q_idx, max_q_idx; 2145dacd88d6SYuval Mintz u16 table_size; 2146dacd88d6SYuval Mintz 2147dacd88d6SYuval Mintz p_rss_tlv = (struct vfpf_vport_update_rss_tlv *) 2148dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 2149dacd88d6SYuval Mintz if (!p_rss_tlv) { 2150dacd88d6SYuval Mintz p_data->rss_params = NULL; 2151dacd88d6SYuval Mintz return; 2152dacd88d6SYuval Mintz } 2153dacd88d6SYuval Mintz 2154dacd88d6SYuval Mintz memset(p_rss, 0, sizeof(struct qed_rss_params)); 2155dacd88d6SYuval Mintz 2156dacd88d6SYuval Mintz p_rss->update_rss_config = !!(p_rss_tlv->update_rss_flags & 2157dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CONFIG_FLAG); 2158dacd88d6SYuval Mintz p_rss->update_rss_capabilities = !!(p_rss_tlv->update_rss_flags & 2159dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CAPS_FLAG); 2160dacd88d6SYuval Mintz p_rss->update_rss_ind_table = !!(p_rss_tlv->update_rss_flags & 2161dacd88d6SYuval Mintz VFPF_UPDATE_RSS_IND_TABLE_FLAG); 2162dacd88d6SYuval Mintz p_rss->update_rss_key = !!(p_rss_tlv->update_rss_flags & 2163dacd88d6SYuval Mintz VFPF_UPDATE_RSS_KEY_FLAG); 2164dacd88d6SYuval Mintz 2165dacd88d6SYuval Mintz p_rss->rss_enable = p_rss_tlv->rss_enable; 2166dacd88d6SYuval Mintz p_rss->rss_eng_id = vf->relative_vf_id + 1; 2167dacd88d6SYuval Mintz p_rss->rss_caps = p_rss_tlv->rss_caps; 2168dacd88d6SYuval Mintz p_rss->rss_table_size_log = p_rss_tlv->rss_table_size_log; 2169dacd88d6SYuval Mintz memcpy(p_rss->rss_ind_table, p_rss_tlv->rss_ind_table, 2170dacd88d6SYuval Mintz sizeof(p_rss->rss_ind_table)); 2171dacd88d6SYuval Mintz memcpy(p_rss->rss_key, p_rss_tlv->rss_key, sizeof(p_rss->rss_key)); 2172dacd88d6SYuval Mintz 2173dacd88d6SYuval Mintz table_size = min_t(u16, ARRAY_SIZE(p_rss->rss_ind_table), 2174dacd88d6SYuval Mintz (1 << p_rss_tlv->rss_table_size_log)); 2175dacd88d6SYuval Mintz 2176dacd88d6SYuval Mintz max_q_idx = ARRAY_SIZE(vf->vf_queues); 2177dacd88d6SYuval Mintz 2178dacd88d6SYuval Mintz for (i = 0; i < table_size; i++) { 2179dacd88d6SYuval Mintz u16 index = vf->vf_queues[0].fw_rx_qid; 2180dacd88d6SYuval Mintz 2181dacd88d6SYuval Mintz q_idx = p_rss->rss_ind_table[i]; 2182dacd88d6SYuval Mintz if (q_idx >= max_q_idx) 2183dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, 2184dacd88d6SYuval Mintz "rss_ind_table[%d] = %d, rxq is out of range\n", 2185dacd88d6SYuval Mintz i, q_idx); 2186dacd88d6SYuval Mintz else if (!vf->vf_queues[q_idx].rxq_active) 2187dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, 2188dacd88d6SYuval Mintz "rss_ind_table[%d] = %d, rxq is not active\n", 2189dacd88d6SYuval Mintz i, q_idx); 2190dacd88d6SYuval Mintz else 2191dacd88d6SYuval Mintz index = vf->vf_queues[q_idx].fw_rx_qid; 2192dacd88d6SYuval Mintz p_rss->rss_ind_table[i] = index; 2193dacd88d6SYuval Mintz } 2194dacd88d6SYuval Mintz 2195dacd88d6SYuval Mintz p_data->rss_params = p_rss; 2196dacd88d6SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_RSS; 2197dacd88d6SYuval Mintz } 2198dacd88d6SYuval Mintz 219917b235c1SYuval Mintz static void 220017b235c1SYuval Mintz qed_iov_vp_update_sge_tpa_param(struct qed_hwfn *p_hwfn, 220117b235c1SYuval Mintz struct qed_vf_info *vf, 220217b235c1SYuval Mintz struct qed_sp_vport_update_params *p_data, 220317b235c1SYuval Mintz struct qed_sge_tpa_params *p_sge_tpa, 220417b235c1SYuval Mintz struct qed_iov_vf_mbx *p_mbx, u16 *tlvs_mask) 220517b235c1SYuval Mintz { 220617b235c1SYuval Mintz struct vfpf_vport_update_sge_tpa_tlv *p_sge_tpa_tlv; 220717b235c1SYuval Mintz u16 tlv = CHANNEL_TLV_VPORT_UPDATE_SGE_TPA; 220817b235c1SYuval Mintz 220917b235c1SYuval Mintz p_sge_tpa_tlv = (struct vfpf_vport_update_sge_tpa_tlv *) 221017b235c1SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv); 221117b235c1SYuval Mintz 221217b235c1SYuval Mintz if (!p_sge_tpa_tlv) { 221317b235c1SYuval Mintz p_data->sge_tpa_params = NULL; 221417b235c1SYuval Mintz return; 221517b235c1SYuval Mintz } 221617b235c1SYuval Mintz 221717b235c1SYuval Mintz memset(p_sge_tpa, 0, sizeof(struct qed_sge_tpa_params)); 221817b235c1SYuval Mintz 221917b235c1SYuval Mintz p_sge_tpa->update_tpa_en_flg = 222017b235c1SYuval Mintz !!(p_sge_tpa_tlv->update_sge_tpa_flags & VFPF_UPDATE_TPA_EN_FLAG); 222117b235c1SYuval Mintz p_sge_tpa->update_tpa_param_flg = 222217b235c1SYuval Mintz !!(p_sge_tpa_tlv->update_sge_tpa_flags & 222317b235c1SYuval Mintz VFPF_UPDATE_TPA_PARAM_FLAG); 222417b235c1SYuval Mintz 222517b235c1SYuval Mintz p_sge_tpa->tpa_ipv4_en_flg = 222617b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_IPV4_EN_FLAG); 222717b235c1SYuval Mintz p_sge_tpa->tpa_ipv6_en_flg = 222817b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_IPV6_EN_FLAG); 222917b235c1SYuval Mintz p_sge_tpa->tpa_pkt_split_flg = 223017b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_PKT_SPLIT_FLAG); 223117b235c1SYuval Mintz p_sge_tpa->tpa_hdr_data_split_flg = 223217b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_HDR_DATA_SPLIT_FLAG); 223317b235c1SYuval Mintz p_sge_tpa->tpa_gro_consistent_flg = 223417b235c1SYuval Mintz !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_GRO_CONSIST_FLAG); 223517b235c1SYuval Mintz 223617b235c1SYuval Mintz p_sge_tpa->tpa_max_aggs_num = p_sge_tpa_tlv->tpa_max_aggs_num; 223717b235c1SYuval Mintz p_sge_tpa->tpa_max_size = p_sge_tpa_tlv->tpa_max_size; 223817b235c1SYuval Mintz p_sge_tpa->tpa_min_size_to_start = p_sge_tpa_tlv->tpa_min_size_to_start; 223917b235c1SYuval Mintz p_sge_tpa->tpa_min_size_to_cont = p_sge_tpa_tlv->tpa_min_size_to_cont; 224017b235c1SYuval Mintz p_sge_tpa->max_buffers_per_cqe = p_sge_tpa_tlv->max_buffers_per_cqe; 224117b235c1SYuval Mintz 224217b235c1SYuval Mintz p_data->sge_tpa_params = p_sge_tpa; 224317b235c1SYuval Mintz 224417b235c1SYuval Mintz *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_SGE_TPA; 224517b235c1SYuval Mintz } 224617b235c1SYuval Mintz 2247dacd88d6SYuval Mintz static void qed_iov_vf_mbx_vport_update(struct qed_hwfn *p_hwfn, 2248dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 2249dacd88d6SYuval Mintz struct qed_vf_info *vf) 2250dacd88d6SYuval Mintz { 2251dacd88d6SYuval Mintz struct qed_sp_vport_update_params params; 2252dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 225317b235c1SYuval Mintz struct qed_sge_tpa_params sge_tpa_params; 2254dacd88d6SYuval Mintz struct qed_rss_params rss_params; 2255dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 2256dacd88d6SYuval Mintz u16 tlvs_mask = 0; 2257dacd88d6SYuval Mintz u16 length; 2258dacd88d6SYuval Mintz int rc; 2259dacd88d6SYuval Mintz 226041086467SYuval Mintz /* Valiate PF can send such a request */ 226141086467SYuval Mintz if (!vf->vport_instance) { 226241086467SYuval Mintz DP_VERBOSE(p_hwfn, 226341086467SYuval Mintz QED_MSG_IOV, 226441086467SYuval Mintz "No VPORT instance available for VF[%d], failing vport update\n", 226541086467SYuval Mintz vf->abs_vf_id); 226641086467SYuval Mintz status = PFVF_STATUS_FAILURE; 226741086467SYuval Mintz goto out; 226841086467SYuval Mintz } 226941086467SYuval Mintz 2270dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(params)); 2271dacd88d6SYuval Mintz params.opaque_fid = vf->opaque_fid; 2272dacd88d6SYuval Mintz params.vport_id = vf->vport_id; 2273dacd88d6SYuval Mintz params.rss_params = NULL; 2274dacd88d6SYuval Mintz 2275dacd88d6SYuval Mintz /* Search for extended tlvs list and update values 2276dacd88d6SYuval Mintz * from VF in struct qed_sp_vport_update_params. 2277dacd88d6SYuval Mintz */ 2278dacd88d6SYuval Mintz qed_iov_vp_update_act_param(p_hwfn, ¶ms, mbx, &tlvs_mask); 227917b235c1SYuval Mintz qed_iov_vp_update_vlan_param(p_hwfn, ¶ms, vf, mbx, &tlvs_mask); 228017b235c1SYuval Mintz qed_iov_vp_update_tx_switch(p_hwfn, ¶ms, mbx, &tlvs_mask); 2281dacd88d6SYuval Mintz qed_iov_vp_update_mcast_bin_param(p_hwfn, ¶ms, mbx, &tlvs_mask); 2282dacd88d6SYuval Mintz qed_iov_vp_update_accept_flag(p_hwfn, ¶ms, mbx, &tlvs_mask); 2283dacd88d6SYuval Mintz qed_iov_vp_update_rss_param(p_hwfn, vf, ¶ms, &rss_params, 2284dacd88d6SYuval Mintz mbx, &tlvs_mask); 228517b235c1SYuval Mintz qed_iov_vp_update_accept_any_vlan(p_hwfn, ¶ms, mbx, &tlvs_mask); 228617b235c1SYuval Mintz qed_iov_vp_update_sge_tpa_param(p_hwfn, vf, ¶ms, 228717b235c1SYuval Mintz &sge_tpa_params, mbx, &tlvs_mask); 2288dacd88d6SYuval Mintz 2289dacd88d6SYuval Mintz /* Just log a message if there is no single extended tlv in buffer. 2290dacd88d6SYuval Mintz * When all features of vport update ramrod would be requested by VF 2291dacd88d6SYuval Mintz * as extended TLVs in buffer then an error can be returned in response 2292dacd88d6SYuval Mintz * if there is no extended TLV present in buffer. 2293dacd88d6SYuval Mintz */ 2294dacd88d6SYuval Mintz if (!tlvs_mask) { 2295dacd88d6SYuval Mintz DP_NOTICE(p_hwfn, 2296dacd88d6SYuval Mintz "No feature tlvs found for vport update\n"); 2297dacd88d6SYuval Mintz status = PFVF_STATUS_NOT_SUPPORTED; 2298dacd88d6SYuval Mintz goto out; 2299dacd88d6SYuval Mintz } 2300dacd88d6SYuval Mintz 2301dacd88d6SYuval Mintz rc = qed_sp_vport_update(p_hwfn, ¶ms, QED_SPQ_MODE_EBLOCK, NULL); 2302dacd88d6SYuval Mintz 2303dacd88d6SYuval Mintz if (rc) 2304dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 2305dacd88d6SYuval Mintz 2306dacd88d6SYuval Mintz out: 2307dacd88d6SYuval Mintz length = qed_iov_prep_vp_update_resp_tlvs(p_hwfn, vf, mbx, status, 2308dacd88d6SYuval Mintz tlvs_mask, tlvs_mask); 2309dacd88d6SYuval Mintz qed_iov_send_response(p_hwfn, p_ptt, vf, length, status); 2310dacd88d6SYuval Mintz } 2311dacd88d6SYuval Mintz 23128246d0b4SYuval Mintz static int qed_iov_vf_update_vlan_shadow(struct qed_hwfn *p_hwfn, 231308feecd7SYuval Mintz struct qed_vf_info *p_vf, 231408feecd7SYuval Mintz struct qed_filter_ucast *p_params) 231508feecd7SYuval Mintz { 231608feecd7SYuval Mintz int i; 231708feecd7SYuval Mintz 231808feecd7SYuval Mintz /* First remove entries and then add new ones */ 231908feecd7SYuval Mintz if (p_params->opcode == QED_FILTER_REMOVE) { 232008feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) 232108feecd7SYuval Mintz if (p_vf->shadow_config.vlans[i].used && 232208feecd7SYuval Mintz p_vf->shadow_config.vlans[i].vid == 232308feecd7SYuval Mintz p_params->vlan) { 232408feecd7SYuval Mintz p_vf->shadow_config.vlans[i].used = false; 232508feecd7SYuval Mintz break; 232608feecd7SYuval Mintz } 232708feecd7SYuval Mintz if (i == QED_ETH_VF_NUM_VLAN_FILTERS + 1) { 232808feecd7SYuval Mintz DP_VERBOSE(p_hwfn, 232908feecd7SYuval Mintz QED_MSG_IOV, 233008feecd7SYuval Mintz "VF [%d] - Tries to remove a non-existing vlan\n", 233108feecd7SYuval Mintz p_vf->relative_vf_id); 233208feecd7SYuval Mintz return -EINVAL; 233308feecd7SYuval Mintz } 233408feecd7SYuval Mintz } else if (p_params->opcode == QED_FILTER_REPLACE || 233508feecd7SYuval Mintz p_params->opcode == QED_FILTER_FLUSH) { 233608feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) 233708feecd7SYuval Mintz p_vf->shadow_config.vlans[i].used = false; 233808feecd7SYuval Mintz } 233908feecd7SYuval Mintz 234008feecd7SYuval Mintz /* In forced mode, we're willing to remove entries - but we don't add 234108feecd7SYuval Mintz * new ones. 234208feecd7SYuval Mintz */ 234308feecd7SYuval Mintz if (p_vf->bulletin.p_virt->valid_bitmap & (1 << VLAN_ADDR_FORCED)) 234408feecd7SYuval Mintz return 0; 234508feecd7SYuval Mintz 234608feecd7SYuval Mintz if (p_params->opcode == QED_FILTER_ADD || 234708feecd7SYuval Mintz p_params->opcode == QED_FILTER_REPLACE) { 234808feecd7SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_VLAN_FILTERS + 1; i++) { 234908feecd7SYuval Mintz if (p_vf->shadow_config.vlans[i].used) 235008feecd7SYuval Mintz continue; 235108feecd7SYuval Mintz 235208feecd7SYuval Mintz p_vf->shadow_config.vlans[i].used = true; 235308feecd7SYuval Mintz p_vf->shadow_config.vlans[i].vid = p_params->vlan; 235408feecd7SYuval Mintz break; 235508feecd7SYuval Mintz } 235608feecd7SYuval Mintz 235708feecd7SYuval Mintz if (i == QED_ETH_VF_NUM_VLAN_FILTERS + 1) { 235808feecd7SYuval Mintz DP_VERBOSE(p_hwfn, 235908feecd7SYuval Mintz QED_MSG_IOV, 236008feecd7SYuval Mintz "VF [%d] - Tries to configure more than %d vlan filters\n", 236108feecd7SYuval Mintz p_vf->relative_vf_id, 236208feecd7SYuval Mintz QED_ETH_VF_NUM_VLAN_FILTERS + 1); 236308feecd7SYuval Mintz return -EINVAL; 236408feecd7SYuval Mintz } 236508feecd7SYuval Mintz } 236608feecd7SYuval Mintz 236708feecd7SYuval Mintz return 0; 236808feecd7SYuval Mintz } 236908feecd7SYuval Mintz 23708246d0b4SYuval Mintz static int qed_iov_vf_update_mac_shadow(struct qed_hwfn *p_hwfn, 23718246d0b4SYuval Mintz struct qed_vf_info *p_vf, 23728246d0b4SYuval Mintz struct qed_filter_ucast *p_params) 23738246d0b4SYuval Mintz { 23748246d0b4SYuval Mintz int i; 23758246d0b4SYuval Mintz 23768246d0b4SYuval Mintz /* If we're in forced-mode, we don't allow any change */ 23778246d0b4SYuval Mintz if (p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)) 23788246d0b4SYuval Mintz return 0; 23798246d0b4SYuval Mintz 23808246d0b4SYuval Mintz /* First remove entries and then add new ones */ 23818246d0b4SYuval Mintz if (p_params->opcode == QED_FILTER_REMOVE) { 23828246d0b4SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) { 23838246d0b4SYuval Mintz if (ether_addr_equal(p_vf->shadow_config.macs[i], 23848246d0b4SYuval Mintz p_params->mac)) { 23858246d0b4SYuval Mintz memset(p_vf->shadow_config.macs[i], 0, 23868246d0b4SYuval Mintz ETH_ALEN); 23878246d0b4SYuval Mintz break; 23888246d0b4SYuval Mintz } 23898246d0b4SYuval Mintz } 23908246d0b4SYuval Mintz 23918246d0b4SYuval Mintz if (i == QED_ETH_VF_NUM_MAC_FILTERS) { 23928246d0b4SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 23938246d0b4SYuval Mintz "MAC isn't configured\n"); 23948246d0b4SYuval Mintz return -EINVAL; 23958246d0b4SYuval Mintz } 23968246d0b4SYuval Mintz } else if (p_params->opcode == QED_FILTER_REPLACE || 23978246d0b4SYuval Mintz p_params->opcode == QED_FILTER_FLUSH) { 23988246d0b4SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) 23998246d0b4SYuval Mintz memset(p_vf->shadow_config.macs[i], 0, ETH_ALEN); 24008246d0b4SYuval Mintz } 24018246d0b4SYuval Mintz 24028246d0b4SYuval Mintz /* List the new MAC address */ 24038246d0b4SYuval Mintz if (p_params->opcode != QED_FILTER_ADD && 24048246d0b4SYuval Mintz p_params->opcode != QED_FILTER_REPLACE) 24058246d0b4SYuval Mintz return 0; 24068246d0b4SYuval Mintz 24078246d0b4SYuval Mintz for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) { 24088246d0b4SYuval Mintz if (is_zero_ether_addr(p_vf->shadow_config.macs[i])) { 24098246d0b4SYuval Mintz ether_addr_copy(p_vf->shadow_config.macs[i], 24108246d0b4SYuval Mintz p_params->mac); 24118246d0b4SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 24128246d0b4SYuval Mintz "Added MAC at %d entry in shadow\n", i); 24138246d0b4SYuval Mintz break; 24148246d0b4SYuval Mintz } 24158246d0b4SYuval Mintz } 24168246d0b4SYuval Mintz 24178246d0b4SYuval Mintz if (i == QED_ETH_VF_NUM_MAC_FILTERS) { 24188246d0b4SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "No available place for MAC\n"); 24198246d0b4SYuval Mintz return -EINVAL; 24208246d0b4SYuval Mintz } 24218246d0b4SYuval Mintz 24228246d0b4SYuval Mintz return 0; 24238246d0b4SYuval Mintz } 24248246d0b4SYuval Mintz 24258246d0b4SYuval Mintz static int 24268246d0b4SYuval Mintz qed_iov_vf_update_unicast_shadow(struct qed_hwfn *p_hwfn, 24278246d0b4SYuval Mintz struct qed_vf_info *p_vf, 24288246d0b4SYuval Mintz struct qed_filter_ucast *p_params) 24298246d0b4SYuval Mintz { 24308246d0b4SYuval Mintz int rc = 0; 24318246d0b4SYuval Mintz 24328246d0b4SYuval Mintz if (p_params->type == QED_FILTER_MAC) { 24338246d0b4SYuval Mintz rc = qed_iov_vf_update_mac_shadow(p_hwfn, p_vf, p_params); 24348246d0b4SYuval Mintz if (rc) 24358246d0b4SYuval Mintz return rc; 24368246d0b4SYuval Mintz } 24378246d0b4SYuval Mintz 24388246d0b4SYuval Mintz if (p_params->type == QED_FILTER_VLAN) 24398246d0b4SYuval Mintz rc = qed_iov_vf_update_vlan_shadow(p_hwfn, p_vf, p_params); 24408246d0b4SYuval Mintz 24418246d0b4SYuval Mintz return rc; 24428246d0b4SYuval Mintz } 24438246d0b4SYuval Mintz 2444dacd88d6SYuval Mintz int qed_iov_chk_ucast(struct qed_hwfn *hwfn, 2445dacd88d6SYuval Mintz int vfid, struct qed_filter_ucast *params) 2446dacd88d6SYuval Mintz { 2447dacd88d6SYuval Mintz struct qed_public_vf_info *vf; 2448dacd88d6SYuval Mintz 2449dacd88d6SYuval Mintz vf = qed_iov_get_public_vf_info(hwfn, vfid, true); 2450dacd88d6SYuval Mintz if (!vf) 2451dacd88d6SYuval Mintz return -EINVAL; 2452dacd88d6SYuval Mintz 2453dacd88d6SYuval Mintz /* No real decision to make; Store the configured MAC */ 2454dacd88d6SYuval Mintz if (params->type == QED_FILTER_MAC || 2455dacd88d6SYuval Mintz params->type == QED_FILTER_MAC_VLAN) 2456dacd88d6SYuval Mintz ether_addr_copy(vf->mac, params->mac); 2457dacd88d6SYuval Mintz 2458dacd88d6SYuval Mintz return 0; 2459dacd88d6SYuval Mintz } 2460dacd88d6SYuval Mintz 2461dacd88d6SYuval Mintz static void qed_iov_vf_mbx_ucast_filter(struct qed_hwfn *p_hwfn, 2462dacd88d6SYuval Mintz struct qed_ptt *p_ptt, 2463dacd88d6SYuval Mintz struct qed_vf_info *vf) 2464dacd88d6SYuval Mintz { 246508feecd7SYuval Mintz struct qed_bulletin_content *p_bulletin = vf->bulletin.p_virt; 2466dacd88d6SYuval Mintz struct qed_iov_vf_mbx *mbx = &vf->vf_mbx; 2467dacd88d6SYuval Mintz struct vfpf_ucast_filter_tlv *req; 2468dacd88d6SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 2469dacd88d6SYuval Mintz struct qed_filter_ucast params; 2470dacd88d6SYuval Mintz int rc; 2471dacd88d6SYuval Mintz 2472dacd88d6SYuval Mintz /* Prepare the unicast filter params */ 2473dacd88d6SYuval Mintz memset(¶ms, 0, sizeof(struct qed_filter_ucast)); 2474dacd88d6SYuval Mintz req = &mbx->req_virt->ucast_filter; 2475dacd88d6SYuval Mintz params.opcode = (enum qed_filter_opcode)req->opcode; 2476dacd88d6SYuval Mintz params.type = (enum qed_filter_ucast_type)req->type; 2477dacd88d6SYuval Mintz 2478dacd88d6SYuval Mintz params.is_rx_filter = 1; 2479dacd88d6SYuval Mintz params.is_tx_filter = 1; 2480dacd88d6SYuval Mintz params.vport_to_remove_from = vf->vport_id; 2481dacd88d6SYuval Mintz params.vport_to_add_to = vf->vport_id; 2482dacd88d6SYuval Mintz memcpy(params.mac, req->mac, ETH_ALEN); 2483dacd88d6SYuval Mintz params.vlan = req->vlan; 2484dacd88d6SYuval Mintz 2485dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, 2486dacd88d6SYuval Mintz QED_MSG_IOV, 2487dacd88d6SYuval 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", 2488dacd88d6SYuval Mintz vf->abs_vf_id, params.opcode, params.type, 2489dacd88d6SYuval Mintz params.is_rx_filter ? "RX" : "", 2490dacd88d6SYuval Mintz params.is_tx_filter ? "TX" : "", 2491dacd88d6SYuval Mintz params.vport_to_add_to, 2492dacd88d6SYuval Mintz params.mac[0], params.mac[1], 2493dacd88d6SYuval Mintz params.mac[2], params.mac[3], 2494dacd88d6SYuval Mintz params.mac[4], params.mac[5], params.vlan); 2495dacd88d6SYuval Mintz 2496dacd88d6SYuval Mintz if (!vf->vport_instance) { 2497dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, 2498dacd88d6SYuval Mintz QED_MSG_IOV, 2499dacd88d6SYuval Mintz "No VPORT instance available for VF[%d], failing ucast MAC configuration\n", 2500dacd88d6SYuval Mintz vf->abs_vf_id); 2501dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 2502dacd88d6SYuval Mintz goto out; 2503dacd88d6SYuval Mintz } 2504dacd88d6SYuval Mintz 250508feecd7SYuval Mintz /* Update shadow copy of the VF configuration */ 250608feecd7SYuval Mintz if (qed_iov_vf_update_unicast_shadow(p_hwfn, vf, ¶ms)) { 250708feecd7SYuval Mintz status = PFVF_STATUS_FAILURE; 250808feecd7SYuval Mintz goto out; 250908feecd7SYuval Mintz } 251008feecd7SYuval Mintz 251108feecd7SYuval Mintz /* Determine if the unicast filtering is acceptible by PF */ 251208feecd7SYuval Mintz if ((p_bulletin->valid_bitmap & (1 << VLAN_ADDR_FORCED)) && 251308feecd7SYuval Mintz (params.type == QED_FILTER_VLAN || 251408feecd7SYuval Mintz params.type == QED_FILTER_MAC_VLAN)) { 251508feecd7SYuval Mintz /* Once VLAN is forced or PVID is set, do not allow 251608feecd7SYuval Mintz * to add/replace any further VLANs. 251708feecd7SYuval Mintz */ 251808feecd7SYuval Mintz if (params.opcode == QED_FILTER_ADD || 251908feecd7SYuval Mintz params.opcode == QED_FILTER_REPLACE) 252008feecd7SYuval Mintz status = PFVF_STATUS_FORCED; 252108feecd7SYuval Mintz goto out; 252208feecd7SYuval Mintz } 252308feecd7SYuval Mintz 2524eff16960SYuval Mintz if ((p_bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) && 2525eff16960SYuval Mintz (params.type == QED_FILTER_MAC || 2526eff16960SYuval Mintz params.type == QED_FILTER_MAC_VLAN)) { 2527eff16960SYuval Mintz if (!ether_addr_equal(p_bulletin->mac, params.mac) || 2528eff16960SYuval Mintz (params.opcode != QED_FILTER_ADD && 2529eff16960SYuval Mintz params.opcode != QED_FILTER_REPLACE)) 2530eff16960SYuval Mintz status = PFVF_STATUS_FORCED; 2531eff16960SYuval Mintz goto out; 2532eff16960SYuval Mintz } 2533eff16960SYuval Mintz 2534dacd88d6SYuval Mintz rc = qed_iov_chk_ucast(p_hwfn, vf->relative_vf_id, ¶ms); 2535dacd88d6SYuval Mintz if (rc) { 2536dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 2537dacd88d6SYuval Mintz goto out; 2538dacd88d6SYuval Mintz } 2539dacd88d6SYuval Mintz 2540dacd88d6SYuval Mintz rc = qed_sp_eth_filter_ucast(p_hwfn, vf->opaque_fid, ¶ms, 2541dacd88d6SYuval Mintz QED_SPQ_MODE_CB, NULL); 2542dacd88d6SYuval Mintz if (rc) 2543dacd88d6SYuval Mintz status = PFVF_STATUS_FAILURE; 2544dacd88d6SYuval Mintz 2545dacd88d6SYuval Mintz out: 2546dacd88d6SYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UCAST_FILTER, 2547dacd88d6SYuval Mintz sizeof(struct pfvf_def_resp_tlv), status); 2548dacd88d6SYuval Mintz } 2549dacd88d6SYuval Mintz 25500b55e27dSYuval Mintz static void qed_iov_vf_mbx_int_cleanup(struct qed_hwfn *p_hwfn, 25510b55e27dSYuval Mintz struct qed_ptt *p_ptt, 25520b55e27dSYuval Mintz struct qed_vf_info *vf) 25530b55e27dSYuval Mintz { 25540b55e27dSYuval Mintz int i; 25550b55e27dSYuval Mintz 25560b55e27dSYuval Mintz /* Reset the SBs */ 25570b55e27dSYuval Mintz for (i = 0; i < vf->num_sbs; i++) 25580b55e27dSYuval Mintz qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, 25590b55e27dSYuval Mintz vf->igu_sbs[i], 25600b55e27dSYuval Mintz vf->opaque_fid, false); 25610b55e27dSYuval Mintz 25620b55e27dSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_INT_CLEANUP, 25630b55e27dSYuval Mintz sizeof(struct pfvf_def_resp_tlv), 25640b55e27dSYuval Mintz PFVF_STATUS_SUCCESS); 25650b55e27dSYuval Mintz } 25660b55e27dSYuval Mintz 25670b55e27dSYuval Mintz static void qed_iov_vf_mbx_close(struct qed_hwfn *p_hwfn, 25680b55e27dSYuval Mintz struct qed_ptt *p_ptt, struct qed_vf_info *vf) 25690b55e27dSYuval Mintz { 25700b55e27dSYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 25710b55e27dSYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 25720b55e27dSYuval Mintz 25730b55e27dSYuval Mintz /* Disable Interrupts for VF */ 25740b55e27dSYuval Mintz qed_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0); 25750b55e27dSYuval Mintz 25760b55e27dSYuval Mintz /* Reset Permission table */ 25770b55e27dSYuval Mintz qed_iov_config_perm_table(p_hwfn, p_ptt, vf, 0); 25780b55e27dSYuval Mintz 25790b55e27dSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_CLOSE, 25800b55e27dSYuval Mintz length, status); 25810b55e27dSYuval Mintz } 25820b55e27dSYuval Mintz 25830b55e27dSYuval Mintz static void qed_iov_vf_mbx_release(struct qed_hwfn *p_hwfn, 25840b55e27dSYuval Mintz struct qed_ptt *p_ptt, 25850b55e27dSYuval Mintz struct qed_vf_info *p_vf) 25860b55e27dSYuval Mintz { 25870b55e27dSYuval Mintz u16 length = sizeof(struct pfvf_def_resp_tlv); 25881fe614d1SYuval Mintz u8 status = PFVF_STATUS_SUCCESS; 25891fe614d1SYuval Mintz int rc = 0; 25900b55e27dSYuval Mintz 25910b55e27dSYuval Mintz qed_iov_vf_cleanup(p_hwfn, p_vf); 25920b55e27dSYuval Mintz 25931fe614d1SYuval Mintz if (p_vf->state != VF_STOPPED && p_vf->state != VF_FREE) { 25941fe614d1SYuval Mintz /* Stopping the VF */ 25951fe614d1SYuval Mintz rc = qed_sp_vf_stop(p_hwfn, p_vf->concrete_fid, 25961fe614d1SYuval Mintz p_vf->opaque_fid); 25971fe614d1SYuval Mintz 25981fe614d1SYuval Mintz if (rc) { 25991fe614d1SYuval Mintz DP_ERR(p_hwfn, "qed_sp_vf_stop returned error %d\n", 26001fe614d1SYuval Mintz rc); 26011fe614d1SYuval Mintz status = PFVF_STATUS_FAILURE; 26021fe614d1SYuval Mintz } 26031fe614d1SYuval Mintz 26041fe614d1SYuval Mintz p_vf->state = VF_STOPPED; 26051fe614d1SYuval Mintz } 26061fe614d1SYuval Mintz 26070b55e27dSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, CHANNEL_TLV_RELEASE, 26081fe614d1SYuval Mintz length, status); 26090b55e27dSYuval Mintz } 26100b55e27dSYuval Mintz 26110b55e27dSYuval Mintz static int 26120b55e27dSYuval Mintz qed_iov_vf_flr_poll_dorq(struct qed_hwfn *p_hwfn, 26130b55e27dSYuval Mintz struct qed_vf_info *p_vf, struct qed_ptt *p_ptt) 26140b55e27dSYuval Mintz { 26150b55e27dSYuval Mintz int cnt; 26160b55e27dSYuval Mintz u32 val; 26170b55e27dSYuval Mintz 26180b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_vf->concrete_fid); 26190b55e27dSYuval Mintz 26200b55e27dSYuval Mintz for (cnt = 0; cnt < 50; cnt++) { 26210b55e27dSYuval Mintz val = qed_rd(p_hwfn, p_ptt, DORQ_REG_VF_USAGE_CNT); 26220b55e27dSYuval Mintz if (!val) 26230b55e27dSYuval Mintz break; 26240b55e27dSYuval Mintz msleep(20); 26250b55e27dSYuval Mintz } 26260b55e27dSYuval Mintz qed_fid_pretend(p_hwfn, p_ptt, (u16) p_hwfn->hw_info.concrete_fid); 26270b55e27dSYuval Mintz 26280b55e27dSYuval Mintz if (cnt == 50) { 26290b55e27dSYuval Mintz DP_ERR(p_hwfn, 26300b55e27dSYuval Mintz "VF[%d] - dorq failed to cleanup [usage 0x%08x]\n", 26310b55e27dSYuval Mintz p_vf->abs_vf_id, val); 26320b55e27dSYuval Mintz return -EBUSY; 26330b55e27dSYuval Mintz } 26340b55e27dSYuval Mintz 26350b55e27dSYuval Mintz return 0; 26360b55e27dSYuval Mintz } 26370b55e27dSYuval Mintz 26380b55e27dSYuval Mintz static int 26390b55e27dSYuval Mintz qed_iov_vf_flr_poll_pbf(struct qed_hwfn *p_hwfn, 26400b55e27dSYuval Mintz struct qed_vf_info *p_vf, struct qed_ptt *p_ptt) 26410b55e27dSYuval Mintz { 26420b55e27dSYuval Mintz u32 cons[MAX_NUM_VOQS], distance[MAX_NUM_VOQS]; 26430b55e27dSYuval Mintz int i, cnt; 26440b55e27dSYuval Mintz 26450b55e27dSYuval Mintz /* Read initial consumers & producers */ 26460b55e27dSYuval Mintz for (i = 0; i < MAX_NUM_VOQS; i++) { 26470b55e27dSYuval Mintz u32 prod; 26480b55e27dSYuval Mintz 26490b55e27dSYuval Mintz cons[i] = qed_rd(p_hwfn, p_ptt, 26500b55e27dSYuval Mintz PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0 + 26510b55e27dSYuval Mintz i * 0x40); 26520b55e27dSYuval Mintz prod = qed_rd(p_hwfn, p_ptt, 26530b55e27dSYuval Mintz PBF_REG_NUM_BLOCKS_ALLOCATED_PROD_VOQ0 + 26540b55e27dSYuval Mintz i * 0x40); 26550b55e27dSYuval Mintz distance[i] = prod - cons[i]; 26560b55e27dSYuval Mintz } 26570b55e27dSYuval Mintz 26580b55e27dSYuval Mintz /* Wait for consumers to pass the producers */ 26590b55e27dSYuval Mintz i = 0; 26600b55e27dSYuval Mintz for (cnt = 0; cnt < 50; cnt++) { 26610b55e27dSYuval Mintz for (; i < MAX_NUM_VOQS; i++) { 26620b55e27dSYuval Mintz u32 tmp; 26630b55e27dSYuval Mintz 26640b55e27dSYuval Mintz tmp = qed_rd(p_hwfn, p_ptt, 26650b55e27dSYuval Mintz PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0 + 26660b55e27dSYuval Mintz i * 0x40); 26670b55e27dSYuval Mintz if (distance[i] > tmp - cons[i]) 26680b55e27dSYuval Mintz break; 26690b55e27dSYuval Mintz } 26700b55e27dSYuval Mintz 26710b55e27dSYuval Mintz if (i == MAX_NUM_VOQS) 26720b55e27dSYuval Mintz break; 26730b55e27dSYuval Mintz 26740b55e27dSYuval Mintz msleep(20); 26750b55e27dSYuval Mintz } 26760b55e27dSYuval Mintz 26770b55e27dSYuval Mintz if (cnt == 50) { 26780b55e27dSYuval Mintz DP_ERR(p_hwfn, "VF[%d] - pbf polling failed on VOQ %d\n", 26790b55e27dSYuval Mintz p_vf->abs_vf_id, i); 26800b55e27dSYuval Mintz return -EBUSY; 26810b55e27dSYuval Mintz } 26820b55e27dSYuval Mintz 26830b55e27dSYuval Mintz return 0; 26840b55e27dSYuval Mintz } 26850b55e27dSYuval Mintz 26860b55e27dSYuval Mintz static int qed_iov_vf_flr_poll(struct qed_hwfn *p_hwfn, 26870b55e27dSYuval Mintz struct qed_vf_info *p_vf, struct qed_ptt *p_ptt) 26880b55e27dSYuval Mintz { 26890b55e27dSYuval Mintz int rc; 26900b55e27dSYuval Mintz 26910b55e27dSYuval Mintz rc = qed_iov_vf_flr_poll_dorq(p_hwfn, p_vf, p_ptt); 26920b55e27dSYuval Mintz if (rc) 26930b55e27dSYuval Mintz return rc; 26940b55e27dSYuval Mintz 26950b55e27dSYuval Mintz rc = qed_iov_vf_flr_poll_pbf(p_hwfn, p_vf, p_ptt); 26960b55e27dSYuval Mintz if (rc) 26970b55e27dSYuval Mintz return rc; 26980b55e27dSYuval Mintz 26990b55e27dSYuval Mintz return 0; 27000b55e27dSYuval Mintz } 27010b55e27dSYuval Mintz 27020b55e27dSYuval Mintz static int 27030b55e27dSYuval Mintz qed_iov_execute_vf_flr_cleanup(struct qed_hwfn *p_hwfn, 27040b55e27dSYuval Mintz struct qed_ptt *p_ptt, 27050b55e27dSYuval Mintz u16 rel_vf_id, u32 *ack_vfs) 27060b55e27dSYuval Mintz { 27070b55e27dSYuval Mintz struct qed_vf_info *p_vf; 27080b55e27dSYuval Mintz int rc = 0; 27090b55e27dSYuval Mintz 27100b55e27dSYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, false); 27110b55e27dSYuval Mintz if (!p_vf) 27120b55e27dSYuval Mintz return 0; 27130b55e27dSYuval Mintz 27140b55e27dSYuval Mintz if (p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] & 27150b55e27dSYuval Mintz (1ULL << (rel_vf_id % 64))) { 27160b55e27dSYuval Mintz u16 vfid = p_vf->abs_vf_id; 27170b55e27dSYuval Mintz 27180b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 27190b55e27dSYuval Mintz "VF[%d] - Handling FLR\n", vfid); 27200b55e27dSYuval Mintz 27210b55e27dSYuval Mintz qed_iov_vf_cleanup(p_hwfn, p_vf); 27220b55e27dSYuval Mintz 27230b55e27dSYuval Mintz /* If VF isn't active, no need for anything but SW */ 27240b55e27dSYuval Mintz if (!p_vf->b_init) 27250b55e27dSYuval Mintz goto cleanup; 27260b55e27dSYuval Mintz 27270b55e27dSYuval Mintz rc = qed_iov_vf_flr_poll(p_hwfn, p_vf, p_ptt); 27280b55e27dSYuval Mintz if (rc) 27290b55e27dSYuval Mintz goto cleanup; 27300b55e27dSYuval Mintz 27310b55e27dSYuval Mintz rc = qed_final_cleanup(p_hwfn, p_ptt, vfid, true); 27320b55e27dSYuval Mintz if (rc) { 27330b55e27dSYuval Mintz DP_ERR(p_hwfn, "Failed handle FLR of VF[%d]\n", vfid); 27340b55e27dSYuval Mintz return rc; 27350b55e27dSYuval Mintz } 27360b55e27dSYuval Mintz 27370b55e27dSYuval Mintz /* VF_STOPPED has to be set only after final cleanup 27380b55e27dSYuval Mintz * but prior to re-enabling the VF. 27390b55e27dSYuval Mintz */ 27400b55e27dSYuval Mintz p_vf->state = VF_STOPPED; 27410b55e27dSYuval Mintz 27420b55e27dSYuval Mintz rc = qed_iov_enable_vf_access(p_hwfn, p_ptt, p_vf); 27430b55e27dSYuval Mintz if (rc) { 27440b55e27dSYuval Mintz DP_ERR(p_hwfn, "Failed to re-enable VF[%d] acces\n", 27450b55e27dSYuval Mintz vfid); 27460b55e27dSYuval Mintz return rc; 27470b55e27dSYuval Mintz } 27480b55e27dSYuval Mintz cleanup: 27490b55e27dSYuval Mintz /* Mark VF for ack and clean pending state */ 27500b55e27dSYuval Mintz if (p_vf->state == VF_RESET) 27510b55e27dSYuval Mintz p_vf->state = VF_STOPPED; 27520b55e27dSYuval Mintz ack_vfs[vfid / 32] |= (1 << (vfid % 32)); 27530b55e27dSYuval Mintz p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &= 27540b55e27dSYuval Mintz ~(1ULL << (rel_vf_id % 64)); 27550b55e27dSYuval Mintz p_hwfn->pf_iov_info->pending_events[rel_vf_id / 64] &= 27560b55e27dSYuval Mintz ~(1ULL << (rel_vf_id % 64)); 27570b55e27dSYuval Mintz } 27580b55e27dSYuval Mintz 27590b55e27dSYuval Mintz return rc; 27600b55e27dSYuval Mintz } 27610b55e27dSYuval Mintz 27620b55e27dSYuval Mintz int qed_iov_vf_flr_cleanup(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 27630b55e27dSYuval Mintz { 27640b55e27dSYuval Mintz u32 ack_vfs[VF_MAX_STATIC / 32]; 27650b55e27dSYuval Mintz int rc = 0; 27660b55e27dSYuval Mintz u16 i; 27670b55e27dSYuval Mintz 27680b55e27dSYuval Mintz memset(ack_vfs, 0, sizeof(u32) * (VF_MAX_STATIC / 32)); 27690b55e27dSYuval Mintz 27700b55e27dSYuval Mintz /* Since BRB <-> PRS interface can't be tested as part of the flr 27710b55e27dSYuval Mintz * polling due to HW limitations, simply sleep a bit. And since 27720b55e27dSYuval Mintz * there's no need to wait per-vf, do it before looping. 27730b55e27dSYuval Mintz */ 27740b55e27dSYuval Mintz msleep(100); 27750b55e27dSYuval Mintz 27760b55e27dSYuval Mintz for (i = 0; i < p_hwfn->cdev->p_iov_info->total_vfs; i++) 27770b55e27dSYuval Mintz qed_iov_execute_vf_flr_cleanup(p_hwfn, p_ptt, i, ack_vfs); 27780b55e27dSYuval Mintz 27790b55e27dSYuval Mintz rc = qed_mcp_ack_vf_flr(p_hwfn, p_ptt, ack_vfs); 27800b55e27dSYuval Mintz return rc; 27810b55e27dSYuval Mintz } 27820b55e27dSYuval Mintz 27830b55e27dSYuval Mintz int qed_iov_mark_vf_flr(struct qed_hwfn *p_hwfn, u32 *p_disabled_vfs) 27840b55e27dSYuval Mintz { 27850b55e27dSYuval Mintz u16 i, found = 0; 27860b55e27dSYuval Mintz 27870b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "Marking FLR-ed VFs\n"); 27880b55e27dSYuval Mintz for (i = 0; i < (VF_MAX_STATIC / 32); i++) 27890b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 27900b55e27dSYuval Mintz "[%08x,...,%08x]: %08x\n", 27910b55e27dSYuval Mintz i * 32, (i + 1) * 32 - 1, p_disabled_vfs[i]); 27920b55e27dSYuval Mintz 27930b55e27dSYuval Mintz if (!p_hwfn->cdev->p_iov_info) { 27940b55e27dSYuval Mintz DP_NOTICE(p_hwfn, "VF flr but no IOV\n"); 27950b55e27dSYuval Mintz return 0; 27960b55e27dSYuval Mintz } 27970b55e27dSYuval Mintz 27980b55e27dSYuval Mintz /* Mark VFs */ 27990b55e27dSYuval Mintz for (i = 0; i < p_hwfn->cdev->p_iov_info->total_vfs; i++) { 28000b55e27dSYuval Mintz struct qed_vf_info *p_vf; 28010b55e27dSYuval Mintz u8 vfid; 28020b55e27dSYuval Mintz 28030b55e27dSYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, i, false); 28040b55e27dSYuval Mintz if (!p_vf) 28050b55e27dSYuval Mintz continue; 28060b55e27dSYuval Mintz 28070b55e27dSYuval Mintz vfid = p_vf->abs_vf_id; 28080b55e27dSYuval Mintz if ((1 << (vfid % 32)) & p_disabled_vfs[vfid / 32]) { 28090b55e27dSYuval Mintz u64 *p_flr = p_hwfn->pf_iov_info->pending_flr; 28100b55e27dSYuval Mintz u16 rel_vf_id = p_vf->relative_vf_id; 28110b55e27dSYuval Mintz 28120b55e27dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 28130b55e27dSYuval Mintz "VF[%d] [rel %d] got FLR-ed\n", 28140b55e27dSYuval Mintz vfid, rel_vf_id); 28150b55e27dSYuval Mintz 28160b55e27dSYuval Mintz p_vf->state = VF_RESET; 28170b55e27dSYuval Mintz 28180b55e27dSYuval Mintz /* No need to lock here, since pending_flr should 28190b55e27dSYuval Mintz * only change here and before ACKing MFw. Since 28200b55e27dSYuval Mintz * MFW will not trigger an additional attention for 28210b55e27dSYuval Mintz * VF flr until ACKs, we're safe. 28220b55e27dSYuval Mintz */ 28230b55e27dSYuval Mintz p_flr[rel_vf_id / 64] |= 1ULL << (rel_vf_id % 64); 28240b55e27dSYuval Mintz found = 1; 28250b55e27dSYuval Mintz } 28260b55e27dSYuval Mintz } 28270b55e27dSYuval Mintz 28280b55e27dSYuval Mintz return found; 28290b55e27dSYuval Mintz } 28300b55e27dSYuval Mintz 283173390ac9SYuval Mintz static void qed_iov_get_link(struct qed_hwfn *p_hwfn, 283273390ac9SYuval Mintz u16 vfid, 283373390ac9SYuval Mintz struct qed_mcp_link_params *p_params, 283473390ac9SYuval Mintz struct qed_mcp_link_state *p_link, 283573390ac9SYuval Mintz struct qed_mcp_link_capabilities *p_caps) 283673390ac9SYuval Mintz { 283773390ac9SYuval Mintz struct qed_vf_info *p_vf = qed_iov_get_vf_info(p_hwfn, 283873390ac9SYuval Mintz vfid, 283973390ac9SYuval Mintz false); 284073390ac9SYuval Mintz struct qed_bulletin_content *p_bulletin; 284173390ac9SYuval Mintz 284273390ac9SYuval Mintz if (!p_vf) 284373390ac9SYuval Mintz return; 284473390ac9SYuval Mintz 284573390ac9SYuval Mintz p_bulletin = p_vf->bulletin.p_virt; 284673390ac9SYuval Mintz 284773390ac9SYuval Mintz if (p_params) 284873390ac9SYuval Mintz __qed_vf_get_link_params(p_hwfn, p_params, p_bulletin); 284973390ac9SYuval Mintz if (p_link) 285073390ac9SYuval Mintz __qed_vf_get_link_state(p_hwfn, p_link, p_bulletin); 285173390ac9SYuval Mintz if (p_caps) 285273390ac9SYuval Mintz __qed_vf_get_link_caps(p_hwfn, p_caps, p_bulletin); 285373390ac9SYuval Mintz } 285473390ac9SYuval Mintz 285537bff2b9SYuval Mintz static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn, 285637bff2b9SYuval Mintz struct qed_ptt *p_ptt, int vfid) 285737bff2b9SYuval Mintz { 285837bff2b9SYuval Mintz struct qed_iov_vf_mbx *mbx; 285937bff2b9SYuval Mintz struct qed_vf_info *p_vf; 286037bff2b9SYuval Mintz 286137bff2b9SYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 286237bff2b9SYuval Mintz if (!p_vf) 286337bff2b9SYuval Mintz return; 286437bff2b9SYuval Mintz 286537bff2b9SYuval Mintz mbx = &p_vf->vf_mbx; 286637bff2b9SYuval Mintz 286737bff2b9SYuval Mintz /* qed_iov_process_mbx_request */ 286854fdd80fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 286954fdd80fSYuval Mintz "VF[%02x]: Processing mailbox message\n", p_vf->abs_vf_id); 287037bff2b9SYuval Mintz 287137bff2b9SYuval Mintz mbx->first_tlv = mbx->req_virt->first_tlv; 287237bff2b9SYuval Mintz 287337bff2b9SYuval Mintz /* check if tlv type is known */ 287437bff2b9SYuval Mintz if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) { 28751408cc1fSYuval Mintz switch (mbx->first_tlv.tl.type) { 28761408cc1fSYuval Mintz case CHANNEL_TLV_ACQUIRE: 28771408cc1fSYuval Mintz qed_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf); 28781408cc1fSYuval Mintz break; 2879dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_START: 2880dacd88d6SYuval Mintz qed_iov_vf_mbx_start_vport(p_hwfn, p_ptt, p_vf); 2881dacd88d6SYuval Mintz break; 2882dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_TEARDOWN: 2883dacd88d6SYuval Mintz qed_iov_vf_mbx_stop_vport(p_hwfn, p_ptt, p_vf); 2884dacd88d6SYuval Mintz break; 2885dacd88d6SYuval Mintz case CHANNEL_TLV_START_RXQ: 2886dacd88d6SYuval Mintz qed_iov_vf_mbx_start_rxq(p_hwfn, p_ptt, p_vf); 2887dacd88d6SYuval Mintz break; 2888dacd88d6SYuval Mintz case CHANNEL_TLV_START_TXQ: 2889dacd88d6SYuval Mintz qed_iov_vf_mbx_start_txq(p_hwfn, p_ptt, p_vf); 2890dacd88d6SYuval Mintz break; 2891dacd88d6SYuval Mintz case CHANNEL_TLV_STOP_RXQS: 2892dacd88d6SYuval Mintz qed_iov_vf_mbx_stop_rxqs(p_hwfn, p_ptt, p_vf); 2893dacd88d6SYuval Mintz break; 2894dacd88d6SYuval Mintz case CHANNEL_TLV_STOP_TXQS: 2895dacd88d6SYuval Mintz qed_iov_vf_mbx_stop_txqs(p_hwfn, p_ptt, p_vf); 2896dacd88d6SYuval Mintz break; 289717b235c1SYuval Mintz case CHANNEL_TLV_UPDATE_RXQ: 289817b235c1SYuval Mintz qed_iov_vf_mbx_update_rxqs(p_hwfn, p_ptt, p_vf); 289917b235c1SYuval Mintz break; 2900dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE: 2901dacd88d6SYuval Mintz qed_iov_vf_mbx_vport_update(p_hwfn, p_ptt, p_vf); 2902dacd88d6SYuval Mintz break; 2903dacd88d6SYuval Mintz case CHANNEL_TLV_UCAST_FILTER: 2904dacd88d6SYuval Mintz qed_iov_vf_mbx_ucast_filter(p_hwfn, p_ptt, p_vf); 2905dacd88d6SYuval Mintz break; 29060b55e27dSYuval Mintz case CHANNEL_TLV_CLOSE: 29070b55e27dSYuval Mintz qed_iov_vf_mbx_close(p_hwfn, p_ptt, p_vf); 29080b55e27dSYuval Mintz break; 29090b55e27dSYuval Mintz case CHANNEL_TLV_INT_CLEANUP: 29100b55e27dSYuval Mintz qed_iov_vf_mbx_int_cleanup(p_hwfn, p_ptt, p_vf); 29110b55e27dSYuval Mintz break; 29120b55e27dSYuval Mintz case CHANNEL_TLV_RELEASE: 29130b55e27dSYuval Mintz qed_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf); 29140b55e27dSYuval Mintz break; 29151408cc1fSYuval Mintz } 291637bff2b9SYuval Mintz } else { 291737bff2b9SYuval Mintz /* unknown TLV - this may belong to a VF driver from the future 291837bff2b9SYuval Mintz * - a version written after this PF driver was written, which 291937bff2b9SYuval Mintz * supports features unknown as of yet. Too bad since we don't 292037bff2b9SYuval Mintz * support them. Or this may be because someone wrote a crappy 292137bff2b9SYuval Mintz * VF driver and is sending garbage over the channel. 292237bff2b9SYuval Mintz */ 292354fdd80fSYuval Mintz DP_NOTICE(p_hwfn, 292454fdd80fSYuval Mintz "VF[%02x]: unknown TLV. type %04x length %04x padding %08x reply address %llu\n", 292554fdd80fSYuval Mintz p_vf->abs_vf_id, 292654fdd80fSYuval Mintz mbx->first_tlv.tl.type, 292754fdd80fSYuval Mintz mbx->first_tlv.tl.length, 292854fdd80fSYuval Mintz mbx->first_tlv.padding, mbx->first_tlv.reply_address); 292937bff2b9SYuval Mintz 293054fdd80fSYuval Mintz /* Try replying in case reply address matches the acquisition's 293154fdd80fSYuval Mintz * posted address. 293254fdd80fSYuval Mintz */ 293354fdd80fSYuval Mintz if (p_vf->acquire.first_tlv.reply_address && 293454fdd80fSYuval Mintz (mbx->first_tlv.reply_address == 293554fdd80fSYuval Mintz p_vf->acquire.first_tlv.reply_address)) { 293654fdd80fSYuval Mintz qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf, 293754fdd80fSYuval Mintz mbx->first_tlv.tl.type, 293854fdd80fSYuval Mintz sizeof(struct pfvf_def_resp_tlv), 293954fdd80fSYuval Mintz PFVF_STATUS_NOT_SUPPORTED); 294054fdd80fSYuval Mintz } else { 294137bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, 294237bff2b9SYuval Mintz QED_MSG_IOV, 294354fdd80fSYuval Mintz "VF[%02x]: Can't respond to TLV - no valid reply address\n", 294454fdd80fSYuval Mintz p_vf->abs_vf_id); 294537bff2b9SYuval Mintz } 294637bff2b9SYuval Mintz } 294737bff2b9SYuval Mintz } 294837bff2b9SYuval Mintz 294937bff2b9SYuval Mintz void qed_iov_pf_add_pending_events(struct qed_hwfn *p_hwfn, u8 vfid) 295037bff2b9SYuval Mintz { 295137bff2b9SYuval Mintz u64 add_bit = 1ULL << (vfid % 64); 295237bff2b9SYuval Mintz 295337bff2b9SYuval Mintz p_hwfn->pf_iov_info->pending_events[vfid / 64] |= add_bit; 295437bff2b9SYuval Mintz } 295537bff2b9SYuval Mintz 295637bff2b9SYuval Mintz static void qed_iov_pf_get_and_clear_pending_events(struct qed_hwfn *p_hwfn, 295737bff2b9SYuval Mintz u64 *events) 295837bff2b9SYuval Mintz { 295937bff2b9SYuval Mintz u64 *p_pending_events = p_hwfn->pf_iov_info->pending_events; 296037bff2b9SYuval Mintz 296137bff2b9SYuval Mintz memcpy(events, p_pending_events, sizeof(u64) * QED_VF_ARRAY_LENGTH); 296237bff2b9SYuval Mintz memset(p_pending_events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH); 296337bff2b9SYuval Mintz } 296437bff2b9SYuval Mintz 296537bff2b9SYuval Mintz static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn, 296637bff2b9SYuval Mintz u16 abs_vfid, struct regpair *vf_msg) 296737bff2b9SYuval Mintz { 296837bff2b9SYuval Mintz u8 min = (u8)p_hwfn->cdev->p_iov_info->first_vf_in_pf; 296937bff2b9SYuval Mintz struct qed_vf_info *p_vf; 297037bff2b9SYuval Mintz 297137bff2b9SYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) { 297237bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, 297337bff2b9SYuval Mintz QED_MSG_IOV, 297437bff2b9SYuval Mintz "Got a message from VF [abs 0x%08x] that cannot be handled by PF\n", 297537bff2b9SYuval Mintz abs_vfid); 297637bff2b9SYuval Mintz return 0; 297737bff2b9SYuval Mintz } 297837bff2b9SYuval Mintz p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min]; 297937bff2b9SYuval Mintz 298037bff2b9SYuval Mintz /* List the physical address of the request so that handler 298137bff2b9SYuval Mintz * could later on copy the message from it. 298237bff2b9SYuval Mintz */ 298337bff2b9SYuval Mintz p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) | vf_msg->lo; 298437bff2b9SYuval Mintz 298537bff2b9SYuval Mintz /* Mark the event and schedule the workqueue */ 298637bff2b9SYuval Mintz qed_iov_pf_add_pending_events(p_hwfn, p_vf->relative_vf_id); 298737bff2b9SYuval Mintz qed_schedule_iov(p_hwfn, QED_IOV_WQ_MSG_FLAG); 298837bff2b9SYuval Mintz 298937bff2b9SYuval Mintz return 0; 299037bff2b9SYuval Mintz } 299137bff2b9SYuval Mintz 299237bff2b9SYuval Mintz int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, 299337bff2b9SYuval Mintz u8 opcode, __le16 echo, union event_ring_data *data) 299437bff2b9SYuval Mintz { 299537bff2b9SYuval Mintz switch (opcode) { 299637bff2b9SYuval Mintz case COMMON_EVENT_VF_PF_CHANNEL: 299737bff2b9SYuval Mintz return qed_sriov_vfpf_msg(p_hwfn, le16_to_cpu(echo), 299837bff2b9SYuval Mintz &data->vf_pf_channel.msg_addr); 299937bff2b9SYuval Mintz default: 300037bff2b9SYuval Mintz DP_INFO(p_hwfn->cdev, "Unknown sriov eqe event 0x%02x\n", 300137bff2b9SYuval Mintz opcode); 300237bff2b9SYuval Mintz return -EINVAL; 300337bff2b9SYuval Mintz } 300437bff2b9SYuval Mintz } 300537bff2b9SYuval Mintz 300632a47e72SYuval Mintz u16 qed_iov_get_next_active_vf(struct qed_hwfn *p_hwfn, u16 rel_vf_id) 300732a47e72SYuval Mintz { 300832a47e72SYuval Mintz struct qed_hw_sriov_info *p_iov = p_hwfn->cdev->p_iov_info; 300932a47e72SYuval Mintz u16 i; 301032a47e72SYuval Mintz 301132a47e72SYuval Mintz if (!p_iov) 301232a47e72SYuval Mintz goto out; 301332a47e72SYuval Mintz 301432a47e72SYuval Mintz for (i = rel_vf_id; i < p_iov->total_vfs; i++) 301532a47e72SYuval Mintz if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true)) 301632a47e72SYuval Mintz return i; 301732a47e72SYuval Mintz 301832a47e72SYuval Mintz out: 301932a47e72SYuval Mintz return MAX_NUM_VFS; 302032a47e72SYuval Mintz } 302137bff2b9SYuval Mintz 302237bff2b9SYuval Mintz static int qed_iov_copy_vf_msg(struct qed_hwfn *p_hwfn, struct qed_ptt *ptt, 302337bff2b9SYuval Mintz int vfid) 302437bff2b9SYuval Mintz { 302537bff2b9SYuval Mintz struct qed_dmae_params params; 302637bff2b9SYuval Mintz struct qed_vf_info *vf_info; 302737bff2b9SYuval Mintz 302837bff2b9SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 302937bff2b9SYuval Mintz if (!vf_info) 303037bff2b9SYuval Mintz return -EINVAL; 303137bff2b9SYuval Mintz 303237bff2b9SYuval Mintz memset(¶ms, 0, sizeof(struct qed_dmae_params)); 303337bff2b9SYuval Mintz params.flags = QED_DMAE_FLAG_VF_SRC | QED_DMAE_FLAG_COMPLETION_DST; 303437bff2b9SYuval Mintz params.src_vfid = vf_info->abs_vf_id; 303537bff2b9SYuval Mintz 303637bff2b9SYuval Mintz if (qed_dmae_host2host(p_hwfn, ptt, 303737bff2b9SYuval Mintz vf_info->vf_mbx.pending_req, 303837bff2b9SYuval Mintz vf_info->vf_mbx.req_phys, 303937bff2b9SYuval Mintz sizeof(union vfpf_tlvs) / 4, ¶ms)) { 304037bff2b9SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 304137bff2b9SYuval Mintz "Failed to copy message from VF 0x%02x\n", vfid); 304237bff2b9SYuval Mintz 304337bff2b9SYuval Mintz return -EIO; 304437bff2b9SYuval Mintz } 304537bff2b9SYuval Mintz 304637bff2b9SYuval Mintz return 0; 304737bff2b9SYuval Mintz } 304837bff2b9SYuval Mintz 3049eff16960SYuval Mintz static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn, 3050eff16960SYuval Mintz u8 *mac, int vfid) 3051eff16960SYuval Mintz { 3052eff16960SYuval Mintz struct qed_vf_info *vf_info; 3053eff16960SYuval Mintz u64 feature; 3054eff16960SYuval Mintz 3055eff16960SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true); 3056eff16960SYuval Mintz if (!vf_info) { 3057eff16960SYuval Mintz DP_NOTICE(p_hwfn->cdev, 3058eff16960SYuval Mintz "Can not set forced MAC, invalid vfid [%d]\n", vfid); 3059eff16960SYuval Mintz return; 3060eff16960SYuval Mintz } 3061eff16960SYuval Mintz 3062eff16960SYuval Mintz feature = 1 << MAC_ADDR_FORCED; 3063eff16960SYuval Mintz memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN); 3064eff16960SYuval Mintz 3065eff16960SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap |= feature; 3066eff16960SYuval Mintz /* Forced MAC will disable MAC_ADDR */ 3067eff16960SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap &= 3068eff16960SYuval Mintz ~(1 << VFPF_BULLETIN_MAC_ADDR); 3069eff16960SYuval Mintz 3070eff16960SYuval Mintz qed_iov_configure_vport_forced(p_hwfn, vf_info, feature); 3071eff16960SYuval Mintz } 3072eff16960SYuval Mintz 307308feecd7SYuval Mintz void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn, 307408feecd7SYuval Mintz u16 pvid, int vfid) 307508feecd7SYuval Mintz { 307608feecd7SYuval Mintz struct qed_vf_info *vf_info; 307708feecd7SYuval Mintz u64 feature; 307808feecd7SYuval Mintz 307908feecd7SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 308008feecd7SYuval Mintz if (!vf_info) { 308108feecd7SYuval Mintz DP_NOTICE(p_hwfn->cdev, 308208feecd7SYuval Mintz "Can not set forced MAC, invalid vfid [%d]\n", vfid); 308308feecd7SYuval Mintz return; 308408feecd7SYuval Mintz } 308508feecd7SYuval Mintz 308608feecd7SYuval Mintz feature = 1 << VLAN_ADDR_FORCED; 308708feecd7SYuval Mintz vf_info->bulletin.p_virt->pvid = pvid; 308808feecd7SYuval Mintz if (pvid) 308908feecd7SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap |= feature; 309008feecd7SYuval Mintz else 309108feecd7SYuval Mintz vf_info->bulletin.p_virt->valid_bitmap &= ~feature; 309208feecd7SYuval Mintz 309308feecd7SYuval Mintz qed_iov_configure_vport_forced(p_hwfn, vf_info, feature); 309408feecd7SYuval Mintz } 309508feecd7SYuval Mintz 30966ddc7608SYuval Mintz static bool qed_iov_vf_has_vport_instance(struct qed_hwfn *p_hwfn, int vfid) 30976ddc7608SYuval Mintz { 30986ddc7608SYuval Mintz struct qed_vf_info *p_vf_info; 30996ddc7608SYuval Mintz 31006ddc7608SYuval Mintz p_vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 31016ddc7608SYuval Mintz if (!p_vf_info) 31026ddc7608SYuval Mintz return false; 31036ddc7608SYuval Mintz 31046ddc7608SYuval Mintz return !!p_vf_info->vport_instance; 31056ddc7608SYuval Mintz } 31066ddc7608SYuval Mintz 31070b55e27dSYuval Mintz bool qed_iov_is_vf_stopped(struct qed_hwfn *p_hwfn, int vfid) 31080b55e27dSYuval Mintz { 31090b55e27dSYuval Mintz struct qed_vf_info *p_vf_info; 31100b55e27dSYuval Mintz 31110b55e27dSYuval Mintz p_vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 31120b55e27dSYuval Mintz if (!p_vf_info) 31130b55e27dSYuval Mintz return true; 31140b55e27dSYuval Mintz 31150b55e27dSYuval Mintz return p_vf_info->state == VF_STOPPED; 31160b55e27dSYuval Mintz } 31170b55e27dSYuval Mintz 311873390ac9SYuval Mintz static bool qed_iov_spoofchk_get(struct qed_hwfn *p_hwfn, int vfid) 311973390ac9SYuval Mintz { 312073390ac9SYuval Mintz struct qed_vf_info *vf_info; 312173390ac9SYuval Mintz 312273390ac9SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 312373390ac9SYuval Mintz if (!vf_info) 312473390ac9SYuval Mintz return false; 312573390ac9SYuval Mintz 312673390ac9SYuval Mintz return vf_info->spoof_chk; 312773390ac9SYuval Mintz } 312873390ac9SYuval Mintz 31296ddc7608SYuval Mintz int qed_iov_spoofchk_set(struct qed_hwfn *p_hwfn, int vfid, bool val) 31306ddc7608SYuval Mintz { 31316ddc7608SYuval Mintz struct qed_vf_info *vf; 31326ddc7608SYuval Mintz int rc = -EINVAL; 31336ddc7608SYuval Mintz 31346ddc7608SYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, vfid)) { 31356ddc7608SYuval Mintz DP_NOTICE(p_hwfn, 31366ddc7608SYuval Mintz "SR-IOV sanity check failed, can't set spoofchk\n"); 31376ddc7608SYuval Mintz goto out; 31386ddc7608SYuval Mintz } 31396ddc7608SYuval Mintz 31406ddc7608SYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 31416ddc7608SYuval Mintz if (!vf) 31426ddc7608SYuval Mintz goto out; 31436ddc7608SYuval Mintz 31446ddc7608SYuval Mintz if (!qed_iov_vf_has_vport_instance(p_hwfn, vfid)) { 31456ddc7608SYuval Mintz /* After VF VPORT start PF will configure spoof check */ 31466ddc7608SYuval Mintz vf->req_spoofchk_val = val; 31476ddc7608SYuval Mintz rc = 0; 31486ddc7608SYuval Mintz goto out; 31496ddc7608SYuval Mintz } 31506ddc7608SYuval Mintz 31516ddc7608SYuval Mintz rc = __qed_iov_spoofchk_set(p_hwfn, vf, val); 31526ddc7608SYuval Mintz 31536ddc7608SYuval Mintz out: 31546ddc7608SYuval Mintz return rc; 31556ddc7608SYuval Mintz } 31566ddc7608SYuval Mintz 3157eff16960SYuval Mintz static u8 *qed_iov_bulletin_get_forced_mac(struct qed_hwfn *p_hwfn, 3158eff16960SYuval Mintz u16 rel_vf_id) 3159eff16960SYuval Mintz { 3160eff16960SYuval Mintz struct qed_vf_info *p_vf; 3161eff16960SYuval Mintz 3162eff16960SYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true); 3163eff16960SYuval Mintz if (!p_vf || !p_vf->bulletin.p_virt) 3164eff16960SYuval Mintz return NULL; 3165eff16960SYuval Mintz 3166eff16960SYuval Mintz if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED))) 3167eff16960SYuval Mintz return NULL; 3168eff16960SYuval Mintz 3169eff16960SYuval Mintz return p_vf->bulletin.p_virt->mac; 3170eff16960SYuval Mintz } 3171eff16960SYuval Mintz 317208feecd7SYuval Mintz u16 qed_iov_bulletin_get_forced_vlan(struct qed_hwfn *p_hwfn, u16 rel_vf_id) 317308feecd7SYuval Mintz { 317408feecd7SYuval Mintz struct qed_vf_info *p_vf; 317508feecd7SYuval Mintz 317608feecd7SYuval Mintz p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true); 317708feecd7SYuval Mintz if (!p_vf || !p_vf->bulletin.p_virt) 317808feecd7SYuval Mintz return 0; 317908feecd7SYuval Mintz 318008feecd7SYuval Mintz if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << VLAN_ADDR_FORCED))) 318108feecd7SYuval Mintz return 0; 318208feecd7SYuval Mintz 318308feecd7SYuval Mintz return p_vf->bulletin.p_virt->pvid; 318408feecd7SYuval Mintz } 318508feecd7SYuval Mintz 3186733def6aSYuval Mintz static int qed_iov_configure_tx_rate(struct qed_hwfn *p_hwfn, 3187733def6aSYuval Mintz struct qed_ptt *p_ptt, int vfid, int val) 3188733def6aSYuval Mintz { 3189733def6aSYuval Mintz struct qed_vf_info *vf; 3190733def6aSYuval Mintz u8 abs_vp_id = 0; 3191733def6aSYuval Mintz int rc; 3192733def6aSYuval Mintz 3193733def6aSYuval Mintz vf = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true); 3194733def6aSYuval Mintz if (!vf) 3195733def6aSYuval Mintz return -EINVAL; 3196733def6aSYuval Mintz 3197733def6aSYuval Mintz rc = qed_fw_vport(p_hwfn, vf->vport_id, &abs_vp_id); 3198733def6aSYuval Mintz if (rc) 3199733def6aSYuval Mintz return rc; 3200733def6aSYuval Mintz 3201733def6aSYuval Mintz return qed_init_vport_rl(p_hwfn, p_ptt, abs_vp_id, (u32)val); 3202733def6aSYuval Mintz } 3203733def6aSYuval Mintz 3204733def6aSYuval Mintz int qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate) 3205733def6aSYuval Mintz { 3206733def6aSYuval Mintz struct qed_vf_info *vf; 3207733def6aSYuval Mintz u8 vport_id; 3208733def6aSYuval Mintz int i; 3209733def6aSYuval Mintz 3210733def6aSYuval Mintz for_each_hwfn(cdev, i) { 3211733def6aSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 3212733def6aSYuval Mintz 3213733def6aSYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, vfid)) { 3214733def6aSYuval Mintz DP_NOTICE(p_hwfn, 3215733def6aSYuval Mintz "SR-IOV sanity check failed, can't set min rate\n"); 3216733def6aSYuval Mintz return -EINVAL; 3217733def6aSYuval Mintz } 3218733def6aSYuval Mintz } 3219733def6aSYuval Mintz 3220733def6aSYuval Mintz vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true); 3221733def6aSYuval Mintz vport_id = vf->vport_id; 3222733def6aSYuval Mintz 3223733def6aSYuval Mintz return qed_configure_vport_wfq(cdev, vport_id, rate); 3224733def6aSYuval Mintz } 3225733def6aSYuval Mintz 322673390ac9SYuval Mintz static int qed_iov_get_vf_min_rate(struct qed_hwfn *p_hwfn, int vfid) 322773390ac9SYuval Mintz { 322873390ac9SYuval Mintz struct qed_wfq_data *vf_vp_wfq; 322973390ac9SYuval Mintz struct qed_vf_info *vf_info; 323073390ac9SYuval Mintz 323173390ac9SYuval Mintz vf_info = qed_iov_get_vf_info(p_hwfn, (u16) vfid, true); 323273390ac9SYuval Mintz if (!vf_info) 323373390ac9SYuval Mintz return 0; 323473390ac9SYuval Mintz 323573390ac9SYuval Mintz vf_vp_wfq = &p_hwfn->qm_info.wfq_data[vf_info->vport_id]; 323673390ac9SYuval Mintz 323773390ac9SYuval Mintz if (vf_vp_wfq->configured) 323873390ac9SYuval Mintz return vf_vp_wfq->min_speed; 323973390ac9SYuval Mintz else 324073390ac9SYuval Mintz return 0; 324173390ac9SYuval Mintz } 324273390ac9SYuval Mintz 324337bff2b9SYuval Mintz /** 324437bff2b9SYuval Mintz * qed_schedule_iov - schedules IOV task for VF and PF 324537bff2b9SYuval Mintz * @hwfn: hardware function pointer 324637bff2b9SYuval Mintz * @flag: IOV flag for VF/PF 324737bff2b9SYuval Mintz */ 324837bff2b9SYuval Mintz void qed_schedule_iov(struct qed_hwfn *hwfn, enum qed_iov_wq_flag flag) 324937bff2b9SYuval Mintz { 325037bff2b9SYuval Mintz smp_mb__before_atomic(); 325137bff2b9SYuval Mintz set_bit(flag, &hwfn->iov_task_flags); 325237bff2b9SYuval Mintz smp_mb__after_atomic(); 325337bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, "Scheduling iov task [Flag: %d]\n", flag); 325437bff2b9SYuval Mintz queue_delayed_work(hwfn->iov_wq, &hwfn->iov_task, 0); 325537bff2b9SYuval Mintz } 325637bff2b9SYuval Mintz 32571408cc1fSYuval Mintz void qed_vf_start_iov_wq(struct qed_dev *cdev) 32581408cc1fSYuval Mintz { 32591408cc1fSYuval Mintz int i; 32601408cc1fSYuval Mintz 32611408cc1fSYuval Mintz for_each_hwfn(cdev, i) 32621408cc1fSYuval Mintz queue_delayed_work(cdev->hwfns[i].iov_wq, 32631408cc1fSYuval Mintz &cdev->hwfns[i].iov_task, 0); 32641408cc1fSYuval Mintz } 32651408cc1fSYuval Mintz 32660b55e27dSYuval Mintz int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) 32670b55e27dSYuval Mintz { 32680b55e27dSYuval Mintz int i, j; 32690b55e27dSYuval Mintz 32700b55e27dSYuval Mintz for_each_hwfn(cdev, i) 32710b55e27dSYuval Mintz if (cdev->hwfns[i].iov_wq) 32720b55e27dSYuval Mintz flush_workqueue(cdev->hwfns[i].iov_wq); 32730b55e27dSYuval Mintz 32740b55e27dSYuval Mintz /* Mark VFs for disablement */ 32750b55e27dSYuval Mintz qed_iov_set_vfs_to_disable(cdev, true); 32760b55e27dSYuval Mintz 32770b55e27dSYuval Mintz if (cdev->p_iov_info && cdev->p_iov_info->num_vfs && pci_enabled) 32780b55e27dSYuval Mintz pci_disable_sriov(cdev->pdev); 32790b55e27dSYuval Mintz 32800b55e27dSYuval Mintz for_each_hwfn(cdev, i) { 32810b55e27dSYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 32820b55e27dSYuval Mintz struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 32830b55e27dSYuval Mintz 32840b55e27dSYuval Mintz /* Failure to acquire the ptt in 100g creates an odd error 32850b55e27dSYuval Mintz * where the first engine has already relased IOV. 32860b55e27dSYuval Mintz */ 32870b55e27dSYuval Mintz if (!ptt) { 32880b55e27dSYuval Mintz DP_ERR(hwfn, "Failed to acquire ptt\n"); 32890b55e27dSYuval Mintz return -EBUSY; 32900b55e27dSYuval Mintz } 32910b55e27dSYuval Mintz 3292733def6aSYuval Mintz /* Clean WFQ db and configure equal weight for all vports */ 3293733def6aSYuval Mintz qed_clean_wfq_db(hwfn, ptt); 3294733def6aSYuval Mintz 32950b55e27dSYuval Mintz qed_for_each_vf(hwfn, j) { 32960b55e27dSYuval Mintz int k; 32970b55e27dSYuval Mintz 32980b55e27dSYuval Mintz if (!qed_iov_is_valid_vfid(hwfn, j, true)) 32990b55e27dSYuval Mintz continue; 33000b55e27dSYuval Mintz 33010b55e27dSYuval Mintz /* Wait until VF is disabled before releasing */ 33020b55e27dSYuval Mintz for (k = 0; k < 100; k++) { 33030b55e27dSYuval Mintz if (!qed_iov_is_vf_stopped(hwfn, j)) 33040b55e27dSYuval Mintz msleep(20); 33050b55e27dSYuval Mintz else 33060b55e27dSYuval Mintz break; 33070b55e27dSYuval Mintz } 33080b55e27dSYuval Mintz 33090b55e27dSYuval Mintz if (k < 100) 33100b55e27dSYuval Mintz qed_iov_release_hw_for_vf(&cdev->hwfns[i], 33110b55e27dSYuval Mintz ptt, j); 33120b55e27dSYuval Mintz else 33130b55e27dSYuval Mintz DP_ERR(hwfn, 33140b55e27dSYuval Mintz "Timeout waiting for VF's FLR to end\n"); 33150b55e27dSYuval Mintz } 33160b55e27dSYuval Mintz 33170b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 33180b55e27dSYuval Mintz } 33190b55e27dSYuval Mintz 33200b55e27dSYuval Mintz qed_iov_set_vfs_to_disable(cdev, false); 33210b55e27dSYuval Mintz 33220b55e27dSYuval Mintz return 0; 33230b55e27dSYuval Mintz } 33240b55e27dSYuval Mintz 33250b55e27dSYuval Mintz static int qed_sriov_enable(struct qed_dev *cdev, int num) 33260b55e27dSYuval Mintz { 33270b55e27dSYuval Mintz struct qed_sb_cnt_info sb_cnt_info; 33280b55e27dSYuval Mintz int i, j, rc; 33290b55e27dSYuval Mintz 33300b55e27dSYuval Mintz if (num >= RESC_NUM(&cdev->hwfns[0], QED_VPORT)) { 33310b55e27dSYuval Mintz DP_NOTICE(cdev, "Can start at most %d VFs\n", 33320b55e27dSYuval Mintz RESC_NUM(&cdev->hwfns[0], QED_VPORT) - 1); 33330b55e27dSYuval Mintz return -EINVAL; 33340b55e27dSYuval Mintz } 33350b55e27dSYuval Mintz 33360b55e27dSYuval Mintz /* Initialize HW for VF access */ 33370b55e27dSYuval Mintz for_each_hwfn(cdev, j) { 33380b55e27dSYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[j]; 33390b55e27dSYuval Mintz struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 33400b55e27dSYuval Mintz int num_sbs = 0, limit = 16; 33410b55e27dSYuval Mintz 33420b55e27dSYuval Mintz if (!ptt) { 33430b55e27dSYuval Mintz DP_ERR(hwfn, "Failed to acquire ptt\n"); 33440b55e27dSYuval Mintz rc = -EBUSY; 33450b55e27dSYuval Mintz goto err; 33460b55e27dSYuval Mintz } 33470b55e27dSYuval Mintz 334883f34bd4SYuval Mintz if (IS_MF_DEFAULT(hwfn)) 334983f34bd4SYuval Mintz limit = MAX_NUM_VFS_BB / hwfn->num_funcs_on_engine; 335083f34bd4SYuval Mintz 33510b55e27dSYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); 33520b55e27dSYuval Mintz qed_int_get_num_sbs(hwfn, &sb_cnt_info); 33530b55e27dSYuval Mintz num_sbs = min_t(int, sb_cnt_info.sb_free_blk, limit); 33540b55e27dSYuval Mintz 33550b55e27dSYuval Mintz for (i = 0; i < num; i++) { 33560b55e27dSYuval Mintz if (!qed_iov_is_valid_vfid(hwfn, i, false)) 33570b55e27dSYuval Mintz continue; 33580b55e27dSYuval Mintz 33590b55e27dSYuval Mintz rc = qed_iov_init_hw_for_vf(hwfn, 33600b55e27dSYuval Mintz ptt, i, num_sbs / num); 33610b55e27dSYuval Mintz if (rc) { 33620b55e27dSYuval Mintz DP_ERR(cdev, "Failed to enable VF[%d]\n", i); 33630b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 33640b55e27dSYuval Mintz goto err; 33650b55e27dSYuval Mintz } 33660b55e27dSYuval Mintz } 33670b55e27dSYuval Mintz 33680b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 33690b55e27dSYuval Mintz } 33700b55e27dSYuval Mintz 33710b55e27dSYuval Mintz /* Enable SRIOV PCIe functions */ 33720b55e27dSYuval Mintz rc = pci_enable_sriov(cdev->pdev, num); 33730b55e27dSYuval Mintz if (rc) { 33740b55e27dSYuval Mintz DP_ERR(cdev, "Failed to enable sriov [%d]\n", rc); 33750b55e27dSYuval Mintz goto err; 33760b55e27dSYuval Mintz } 33770b55e27dSYuval Mintz 33780b55e27dSYuval Mintz return num; 33790b55e27dSYuval Mintz 33800b55e27dSYuval Mintz err: 33810b55e27dSYuval Mintz qed_sriov_disable(cdev, false); 33820b55e27dSYuval Mintz return rc; 33830b55e27dSYuval Mintz } 33840b55e27dSYuval Mintz 33850b55e27dSYuval Mintz static int qed_sriov_configure(struct qed_dev *cdev, int num_vfs_param) 33860b55e27dSYuval Mintz { 33870b55e27dSYuval Mintz if (!IS_QED_SRIOV(cdev)) { 33880b55e27dSYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, "SR-IOV is not supported\n"); 33890b55e27dSYuval Mintz return -EOPNOTSUPP; 33900b55e27dSYuval Mintz } 33910b55e27dSYuval Mintz 33920b55e27dSYuval Mintz if (num_vfs_param) 33930b55e27dSYuval Mintz return qed_sriov_enable(cdev, num_vfs_param); 33940b55e27dSYuval Mintz else 33950b55e27dSYuval Mintz return qed_sriov_disable(cdev, true); 33960b55e27dSYuval Mintz } 33970b55e27dSYuval Mintz 3398eff16960SYuval Mintz static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid) 3399eff16960SYuval Mintz { 3400eff16960SYuval Mintz int i; 3401eff16960SYuval Mintz 3402eff16960SYuval Mintz if (!IS_QED_SRIOV(cdev) || !IS_PF_SRIOV_ALLOC(&cdev->hwfns[0])) { 3403eff16960SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 3404eff16960SYuval Mintz "Cannot set a VF MAC; Sriov is not enabled\n"); 3405eff16960SYuval Mintz return -EINVAL; 3406eff16960SYuval Mintz } 3407eff16960SYuval Mintz 3408eff16960SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) { 3409eff16960SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 3410eff16960SYuval Mintz "Cannot set VF[%d] MAC (VF is not active)\n", vfid); 3411eff16960SYuval Mintz return -EINVAL; 3412eff16960SYuval Mintz } 3413eff16960SYuval Mintz 3414eff16960SYuval Mintz for_each_hwfn(cdev, i) { 3415eff16960SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 3416eff16960SYuval Mintz struct qed_public_vf_info *vf_info; 3417eff16960SYuval Mintz 3418eff16960SYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true); 3419eff16960SYuval Mintz if (!vf_info) 3420eff16960SYuval Mintz continue; 3421eff16960SYuval Mintz 3422eff16960SYuval Mintz /* Set the forced MAC, and schedule the IOV task */ 3423eff16960SYuval Mintz ether_addr_copy(vf_info->forced_mac, mac); 3424eff16960SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_SET_UNICAST_FILTER_FLAG); 3425eff16960SYuval Mintz } 3426eff16960SYuval Mintz 3427eff16960SYuval Mintz return 0; 3428eff16960SYuval Mintz } 3429eff16960SYuval Mintz 343008feecd7SYuval Mintz static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid) 343108feecd7SYuval Mintz { 343208feecd7SYuval Mintz int i; 343308feecd7SYuval Mintz 343408feecd7SYuval Mintz if (!IS_QED_SRIOV(cdev) || !IS_PF_SRIOV_ALLOC(&cdev->hwfns[0])) { 343508feecd7SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 343608feecd7SYuval Mintz "Cannot set a VF MAC; Sriov is not enabled\n"); 343708feecd7SYuval Mintz return -EINVAL; 343808feecd7SYuval Mintz } 343908feecd7SYuval Mintz 344008feecd7SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) { 344108feecd7SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 344208feecd7SYuval Mintz "Cannot set VF[%d] MAC (VF is not active)\n", vfid); 344308feecd7SYuval Mintz return -EINVAL; 344408feecd7SYuval Mintz } 344508feecd7SYuval Mintz 344608feecd7SYuval Mintz for_each_hwfn(cdev, i) { 344708feecd7SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 344808feecd7SYuval Mintz struct qed_public_vf_info *vf_info; 344908feecd7SYuval Mintz 345008feecd7SYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true); 345108feecd7SYuval Mintz if (!vf_info) 345208feecd7SYuval Mintz continue; 345308feecd7SYuval Mintz 345408feecd7SYuval Mintz /* Set the forced vlan, and schedule the IOV task */ 345508feecd7SYuval Mintz vf_info->forced_vlan = vid; 345608feecd7SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_SET_UNICAST_FILTER_FLAG); 345708feecd7SYuval Mintz } 345808feecd7SYuval Mintz 345908feecd7SYuval Mintz return 0; 346008feecd7SYuval Mintz } 346108feecd7SYuval Mintz 346273390ac9SYuval Mintz static int qed_get_vf_config(struct qed_dev *cdev, 346373390ac9SYuval Mintz int vf_id, struct ifla_vf_info *ivi) 346473390ac9SYuval Mintz { 346573390ac9SYuval Mintz struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 346673390ac9SYuval Mintz struct qed_public_vf_info *vf_info; 346773390ac9SYuval Mintz struct qed_mcp_link_state link; 346873390ac9SYuval Mintz u32 tx_rate; 346973390ac9SYuval Mintz 347073390ac9SYuval Mintz /* Sanitize request */ 347173390ac9SYuval Mintz if (IS_VF(cdev)) 347273390ac9SYuval Mintz return -EINVAL; 347373390ac9SYuval Mintz 347473390ac9SYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) { 347573390ac9SYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 347673390ac9SYuval Mintz "VF index [%d] isn't active\n", vf_id); 347773390ac9SYuval Mintz return -EINVAL; 347873390ac9SYuval Mintz } 347973390ac9SYuval Mintz 348073390ac9SYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, vf_id, true); 348173390ac9SYuval Mintz 348273390ac9SYuval Mintz qed_iov_get_link(hwfn, vf_id, NULL, &link, NULL); 348373390ac9SYuval Mintz 348473390ac9SYuval Mintz /* Fill information about VF */ 348573390ac9SYuval Mintz ivi->vf = vf_id; 348673390ac9SYuval Mintz 348773390ac9SYuval Mintz if (is_valid_ether_addr(vf_info->forced_mac)) 348873390ac9SYuval Mintz ether_addr_copy(ivi->mac, vf_info->forced_mac); 348973390ac9SYuval Mintz else 349073390ac9SYuval Mintz ether_addr_copy(ivi->mac, vf_info->mac); 349173390ac9SYuval Mintz 349273390ac9SYuval Mintz ivi->vlan = vf_info->forced_vlan; 349373390ac9SYuval Mintz ivi->spoofchk = qed_iov_spoofchk_get(hwfn, vf_id); 349473390ac9SYuval Mintz ivi->linkstate = vf_info->link_state; 349573390ac9SYuval Mintz tx_rate = vf_info->tx_rate; 349673390ac9SYuval Mintz ivi->max_tx_rate = tx_rate ? tx_rate : link.speed; 349773390ac9SYuval Mintz ivi->min_tx_rate = qed_iov_get_vf_min_rate(hwfn, vf_id); 349873390ac9SYuval Mintz 349973390ac9SYuval Mintz return 0; 350073390ac9SYuval Mintz } 350173390ac9SYuval Mintz 350236558c3dSYuval Mintz void qed_inform_vf_link_state(struct qed_hwfn *hwfn) 350336558c3dSYuval Mintz { 350436558c3dSYuval Mintz struct qed_mcp_link_capabilities caps; 350536558c3dSYuval Mintz struct qed_mcp_link_params params; 350636558c3dSYuval Mintz struct qed_mcp_link_state link; 350736558c3dSYuval Mintz int i; 350836558c3dSYuval Mintz 350936558c3dSYuval Mintz if (!hwfn->pf_iov_info) 351036558c3dSYuval Mintz return; 351136558c3dSYuval Mintz 351236558c3dSYuval Mintz /* Update bulletin of all future possible VFs with link configuration */ 351336558c3dSYuval Mintz for (i = 0; i < hwfn->cdev->p_iov_info->total_vfs; i++) { 3514733def6aSYuval Mintz struct qed_public_vf_info *vf_info; 3515733def6aSYuval Mintz 3516733def6aSYuval Mintz vf_info = qed_iov_get_public_vf_info(hwfn, i, false); 3517733def6aSYuval Mintz if (!vf_info) 3518733def6aSYuval Mintz continue; 3519733def6aSYuval Mintz 352036558c3dSYuval Mintz memcpy(¶ms, qed_mcp_get_link_params(hwfn), sizeof(params)); 352136558c3dSYuval Mintz memcpy(&link, qed_mcp_get_link_state(hwfn), sizeof(link)); 352236558c3dSYuval Mintz memcpy(&caps, qed_mcp_get_link_capabilities(hwfn), 352336558c3dSYuval Mintz sizeof(caps)); 352436558c3dSYuval Mintz 3525733def6aSYuval Mintz /* Modify link according to the VF's configured link state */ 3526733def6aSYuval Mintz switch (vf_info->link_state) { 3527733def6aSYuval Mintz case IFLA_VF_LINK_STATE_DISABLE: 3528733def6aSYuval Mintz link.link_up = false; 3529733def6aSYuval Mintz break; 3530733def6aSYuval Mintz case IFLA_VF_LINK_STATE_ENABLE: 3531733def6aSYuval Mintz link.link_up = true; 3532733def6aSYuval Mintz /* Set speed according to maximum supported by HW. 3533733def6aSYuval Mintz * that is 40G for regular devices and 100G for CMT 3534733def6aSYuval Mintz * mode devices. 3535733def6aSYuval Mintz */ 3536733def6aSYuval Mintz link.speed = (hwfn->cdev->num_hwfns > 1) ? 3537733def6aSYuval Mintz 100000 : 40000; 3538733def6aSYuval Mintz default: 3539733def6aSYuval Mintz /* In auto mode pass PF link image to VF */ 3540733def6aSYuval Mintz break; 3541733def6aSYuval Mintz } 3542733def6aSYuval Mintz 3543733def6aSYuval Mintz if (link.link_up && vf_info->tx_rate) { 3544733def6aSYuval Mintz struct qed_ptt *ptt; 3545733def6aSYuval Mintz int rate; 3546733def6aSYuval Mintz 3547733def6aSYuval Mintz rate = min_t(int, vf_info->tx_rate, link.speed); 3548733def6aSYuval Mintz 3549733def6aSYuval Mintz ptt = qed_ptt_acquire(hwfn); 3550733def6aSYuval Mintz if (!ptt) { 3551733def6aSYuval Mintz DP_NOTICE(hwfn, "Failed to acquire PTT\n"); 3552733def6aSYuval Mintz return; 3553733def6aSYuval Mintz } 3554733def6aSYuval Mintz 3555733def6aSYuval Mintz if (!qed_iov_configure_tx_rate(hwfn, ptt, i, rate)) { 3556733def6aSYuval Mintz vf_info->tx_rate = rate; 3557733def6aSYuval Mintz link.speed = rate; 3558733def6aSYuval Mintz } 3559733def6aSYuval Mintz 3560733def6aSYuval Mintz qed_ptt_release(hwfn, ptt); 3561733def6aSYuval Mintz } 3562733def6aSYuval Mintz 356336558c3dSYuval Mintz qed_iov_set_link(hwfn, i, ¶ms, &link, &caps); 356436558c3dSYuval Mintz } 356536558c3dSYuval Mintz 356636558c3dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 356736558c3dSYuval Mintz } 356836558c3dSYuval Mintz 3569733def6aSYuval Mintz static int qed_set_vf_link_state(struct qed_dev *cdev, 3570733def6aSYuval Mintz int vf_id, int link_state) 3571733def6aSYuval Mintz { 3572733def6aSYuval Mintz int i; 3573733def6aSYuval Mintz 3574733def6aSYuval Mintz /* Sanitize request */ 3575733def6aSYuval Mintz if (IS_VF(cdev)) 3576733def6aSYuval Mintz return -EINVAL; 3577733def6aSYuval Mintz 3578733def6aSYuval Mintz if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) { 3579733def6aSYuval Mintz DP_VERBOSE(cdev, QED_MSG_IOV, 3580733def6aSYuval Mintz "VF index [%d] isn't active\n", vf_id); 3581733def6aSYuval Mintz return -EINVAL; 3582733def6aSYuval Mintz } 3583733def6aSYuval Mintz 3584733def6aSYuval Mintz /* Handle configuration of link state */ 3585733def6aSYuval Mintz for_each_hwfn(cdev, i) { 3586733def6aSYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[i]; 3587733def6aSYuval Mintz struct qed_public_vf_info *vf; 3588733def6aSYuval Mintz 3589733def6aSYuval Mintz vf = qed_iov_get_public_vf_info(hwfn, vf_id, true); 3590733def6aSYuval Mintz if (!vf) 3591733def6aSYuval Mintz continue; 3592733def6aSYuval Mintz 3593733def6aSYuval Mintz if (vf->link_state == link_state) 3594733def6aSYuval Mintz continue; 3595733def6aSYuval Mintz 3596733def6aSYuval Mintz vf->link_state = link_state; 3597733def6aSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 3598733def6aSYuval Mintz } 3599733def6aSYuval Mintz 3600733def6aSYuval Mintz return 0; 3601733def6aSYuval Mintz } 3602733def6aSYuval Mintz 36036ddc7608SYuval Mintz static int qed_spoof_configure(struct qed_dev *cdev, int vfid, bool val) 36046ddc7608SYuval Mintz { 36056ddc7608SYuval Mintz int i, rc = -EINVAL; 36066ddc7608SYuval Mintz 36076ddc7608SYuval Mintz for_each_hwfn(cdev, i) { 36086ddc7608SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 36096ddc7608SYuval Mintz 36106ddc7608SYuval Mintz rc = qed_iov_spoofchk_set(p_hwfn, vfid, val); 36116ddc7608SYuval Mintz if (rc) 36126ddc7608SYuval Mintz break; 36136ddc7608SYuval Mintz } 36146ddc7608SYuval Mintz 36156ddc7608SYuval Mintz return rc; 36166ddc7608SYuval Mintz } 36176ddc7608SYuval Mintz 3618733def6aSYuval Mintz static int qed_configure_max_vf_rate(struct qed_dev *cdev, int vfid, int rate) 3619733def6aSYuval Mintz { 3620733def6aSYuval Mintz int i; 3621733def6aSYuval Mintz 3622733def6aSYuval Mintz for_each_hwfn(cdev, i) { 3623733def6aSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 3624733def6aSYuval Mintz struct qed_public_vf_info *vf; 3625733def6aSYuval Mintz 3626733def6aSYuval Mintz if (!qed_iov_pf_sanity_check(p_hwfn, vfid)) { 3627733def6aSYuval Mintz DP_NOTICE(p_hwfn, 3628733def6aSYuval Mintz "SR-IOV sanity check failed, can't set tx rate\n"); 3629733def6aSYuval Mintz return -EINVAL; 3630733def6aSYuval Mintz } 3631733def6aSYuval Mintz 3632733def6aSYuval Mintz vf = qed_iov_get_public_vf_info(p_hwfn, vfid, true); 3633733def6aSYuval Mintz 3634733def6aSYuval Mintz vf->tx_rate = rate; 3635733def6aSYuval Mintz 3636733def6aSYuval Mintz qed_inform_vf_link_state(p_hwfn); 3637733def6aSYuval Mintz } 3638733def6aSYuval Mintz 3639733def6aSYuval Mintz return 0; 3640733def6aSYuval Mintz } 3641733def6aSYuval Mintz 3642733def6aSYuval Mintz static int qed_set_vf_rate(struct qed_dev *cdev, 3643733def6aSYuval Mintz int vfid, u32 min_rate, u32 max_rate) 3644733def6aSYuval Mintz { 3645733def6aSYuval Mintz int rc_min = 0, rc_max = 0; 3646733def6aSYuval Mintz 3647733def6aSYuval Mintz if (max_rate) 3648733def6aSYuval Mintz rc_max = qed_configure_max_vf_rate(cdev, vfid, max_rate); 3649733def6aSYuval Mintz 3650733def6aSYuval Mintz if (min_rate) 3651733def6aSYuval Mintz rc_min = qed_iov_configure_min_tx_rate(cdev, vfid, min_rate); 3652733def6aSYuval Mintz 3653733def6aSYuval Mintz if (rc_max | rc_min) 3654733def6aSYuval Mintz return -EINVAL; 3655733def6aSYuval Mintz 3656733def6aSYuval Mintz return 0; 3657733def6aSYuval Mintz } 3658733def6aSYuval Mintz 365937bff2b9SYuval Mintz static void qed_handle_vf_msg(struct qed_hwfn *hwfn) 366037bff2b9SYuval Mintz { 366137bff2b9SYuval Mintz u64 events[QED_VF_ARRAY_LENGTH]; 366237bff2b9SYuval Mintz struct qed_ptt *ptt; 366337bff2b9SYuval Mintz int i; 366437bff2b9SYuval Mintz 366537bff2b9SYuval Mintz ptt = qed_ptt_acquire(hwfn); 366637bff2b9SYuval Mintz if (!ptt) { 366737bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, 366837bff2b9SYuval Mintz "Can't acquire PTT; re-scheduling\n"); 366937bff2b9SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_MSG_FLAG); 367037bff2b9SYuval Mintz return; 367137bff2b9SYuval Mintz } 367237bff2b9SYuval Mintz 367337bff2b9SYuval Mintz qed_iov_pf_get_and_clear_pending_events(hwfn, events); 367437bff2b9SYuval Mintz 367537bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, 367637bff2b9SYuval Mintz "Event mask of VF events: 0x%llx 0x%llx 0x%llx\n", 367737bff2b9SYuval Mintz events[0], events[1], events[2]); 367837bff2b9SYuval Mintz 367937bff2b9SYuval Mintz qed_for_each_vf(hwfn, i) { 368037bff2b9SYuval Mintz /* Skip VFs with no pending messages */ 368137bff2b9SYuval Mintz if (!(events[i / 64] & (1ULL << (i % 64)))) 368237bff2b9SYuval Mintz continue; 368337bff2b9SYuval Mintz 368437bff2b9SYuval Mintz DP_VERBOSE(hwfn, QED_MSG_IOV, 368537bff2b9SYuval Mintz "Handling VF message from VF 0x%02x [Abs 0x%02x]\n", 368637bff2b9SYuval Mintz i, hwfn->cdev->p_iov_info->first_vf_in_pf + i); 368737bff2b9SYuval Mintz 368837bff2b9SYuval Mintz /* Copy VF's message to PF's request buffer for that VF */ 368937bff2b9SYuval Mintz if (qed_iov_copy_vf_msg(hwfn, ptt, i)) 369037bff2b9SYuval Mintz continue; 369137bff2b9SYuval Mintz 369237bff2b9SYuval Mintz qed_iov_process_mbx_req(hwfn, ptt, i); 369337bff2b9SYuval Mintz } 369437bff2b9SYuval Mintz 369537bff2b9SYuval Mintz qed_ptt_release(hwfn, ptt); 369637bff2b9SYuval Mintz } 369737bff2b9SYuval Mintz 369808feecd7SYuval Mintz static void qed_handle_pf_set_vf_unicast(struct qed_hwfn *hwfn) 369908feecd7SYuval Mintz { 370008feecd7SYuval Mintz int i; 370108feecd7SYuval Mintz 370208feecd7SYuval Mintz qed_for_each_vf(hwfn, i) { 370308feecd7SYuval Mintz struct qed_public_vf_info *info; 370408feecd7SYuval Mintz bool update = false; 3705eff16960SYuval Mintz u8 *mac; 370608feecd7SYuval Mintz 370708feecd7SYuval Mintz info = qed_iov_get_public_vf_info(hwfn, i, true); 370808feecd7SYuval Mintz if (!info) 370908feecd7SYuval Mintz continue; 371008feecd7SYuval Mintz 371108feecd7SYuval Mintz /* Update data on bulletin board */ 3712eff16960SYuval Mintz mac = qed_iov_bulletin_get_forced_mac(hwfn, i); 3713eff16960SYuval Mintz if (is_valid_ether_addr(info->forced_mac) && 3714eff16960SYuval Mintz (!mac || !ether_addr_equal(mac, info->forced_mac))) { 3715eff16960SYuval Mintz DP_VERBOSE(hwfn, 3716eff16960SYuval Mintz QED_MSG_IOV, 3717eff16960SYuval Mintz "Handling PF setting of VF MAC to VF 0x%02x [Abs 0x%02x]\n", 3718eff16960SYuval Mintz i, 3719eff16960SYuval Mintz hwfn->cdev->p_iov_info->first_vf_in_pf + i); 3720eff16960SYuval Mintz 3721eff16960SYuval Mintz /* Update bulletin board with forced MAC */ 3722eff16960SYuval Mintz qed_iov_bulletin_set_forced_mac(hwfn, 3723eff16960SYuval Mintz info->forced_mac, i); 3724eff16960SYuval Mintz update = true; 3725eff16960SYuval Mintz } 372608feecd7SYuval Mintz 372708feecd7SYuval Mintz if (qed_iov_bulletin_get_forced_vlan(hwfn, i) ^ 372808feecd7SYuval Mintz info->forced_vlan) { 372908feecd7SYuval Mintz DP_VERBOSE(hwfn, 373008feecd7SYuval Mintz QED_MSG_IOV, 373108feecd7SYuval Mintz "Handling PF setting of pvid [0x%04x] to VF 0x%02x [Abs 0x%02x]\n", 373208feecd7SYuval Mintz info->forced_vlan, 373308feecd7SYuval Mintz i, 373408feecd7SYuval Mintz hwfn->cdev->p_iov_info->first_vf_in_pf + i); 373508feecd7SYuval Mintz qed_iov_bulletin_set_forced_vlan(hwfn, 373608feecd7SYuval Mintz info->forced_vlan, i); 373708feecd7SYuval Mintz update = true; 373808feecd7SYuval Mintz } 373908feecd7SYuval Mintz 374008feecd7SYuval Mintz if (update) 374108feecd7SYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 374208feecd7SYuval Mintz } 374308feecd7SYuval Mintz } 374408feecd7SYuval Mintz 374536558c3dSYuval Mintz static void qed_handle_bulletin_post(struct qed_hwfn *hwfn) 374636558c3dSYuval Mintz { 374736558c3dSYuval Mintz struct qed_ptt *ptt; 374836558c3dSYuval Mintz int i; 374936558c3dSYuval Mintz 375036558c3dSYuval Mintz ptt = qed_ptt_acquire(hwfn); 375136558c3dSYuval Mintz if (!ptt) { 375236558c3dSYuval Mintz DP_NOTICE(hwfn, "Failed allocating a ptt entry\n"); 375336558c3dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 375436558c3dSYuval Mintz return; 375536558c3dSYuval Mintz } 375636558c3dSYuval Mintz 375736558c3dSYuval Mintz qed_for_each_vf(hwfn, i) 375836558c3dSYuval Mintz qed_iov_post_vf_bulletin(hwfn, i, ptt); 375936558c3dSYuval Mintz 376036558c3dSYuval Mintz qed_ptt_release(hwfn, ptt); 376136558c3dSYuval Mintz } 376236558c3dSYuval Mintz 376337bff2b9SYuval Mintz void qed_iov_pf_task(struct work_struct *work) 376437bff2b9SYuval Mintz { 376537bff2b9SYuval Mintz struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn, 376637bff2b9SYuval Mintz iov_task.work); 37670b55e27dSYuval Mintz int rc; 376837bff2b9SYuval Mintz 376937bff2b9SYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_STOP_WQ_FLAG, &hwfn->iov_task_flags)) 377037bff2b9SYuval Mintz return; 377137bff2b9SYuval Mintz 37720b55e27dSYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_FLR_FLAG, &hwfn->iov_task_flags)) { 37730b55e27dSYuval Mintz struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 37740b55e27dSYuval Mintz 37750b55e27dSYuval Mintz if (!ptt) { 37760b55e27dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_FLR_FLAG); 37770b55e27dSYuval Mintz return; 37780b55e27dSYuval Mintz } 37790b55e27dSYuval Mintz 37800b55e27dSYuval Mintz rc = qed_iov_vf_flr_cleanup(hwfn, ptt); 37810b55e27dSYuval Mintz if (rc) 37820b55e27dSYuval Mintz qed_schedule_iov(hwfn, QED_IOV_WQ_FLR_FLAG); 37830b55e27dSYuval Mintz 37840b55e27dSYuval Mintz qed_ptt_release(hwfn, ptt); 37850b55e27dSYuval Mintz } 37860b55e27dSYuval Mintz 378737bff2b9SYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_MSG_FLAG, &hwfn->iov_task_flags)) 378837bff2b9SYuval Mintz qed_handle_vf_msg(hwfn); 378908feecd7SYuval Mintz 379008feecd7SYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_SET_UNICAST_FILTER_FLAG, 379108feecd7SYuval Mintz &hwfn->iov_task_flags)) 379208feecd7SYuval Mintz qed_handle_pf_set_vf_unicast(hwfn); 379308feecd7SYuval Mintz 379436558c3dSYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_BULLETIN_UPDATE_FLAG, 379536558c3dSYuval Mintz &hwfn->iov_task_flags)) 379636558c3dSYuval Mintz qed_handle_bulletin_post(hwfn); 379737bff2b9SYuval Mintz } 379837bff2b9SYuval Mintz 379937bff2b9SYuval Mintz void qed_iov_wq_stop(struct qed_dev *cdev, bool schedule_first) 380037bff2b9SYuval Mintz { 380137bff2b9SYuval Mintz int i; 380237bff2b9SYuval Mintz 380337bff2b9SYuval Mintz for_each_hwfn(cdev, i) { 380437bff2b9SYuval Mintz if (!cdev->hwfns[i].iov_wq) 380537bff2b9SYuval Mintz continue; 380637bff2b9SYuval Mintz 380737bff2b9SYuval Mintz if (schedule_first) { 380837bff2b9SYuval Mintz qed_schedule_iov(&cdev->hwfns[i], 380937bff2b9SYuval Mintz QED_IOV_WQ_STOP_WQ_FLAG); 381037bff2b9SYuval Mintz cancel_delayed_work_sync(&cdev->hwfns[i].iov_task); 381137bff2b9SYuval Mintz } 381237bff2b9SYuval Mintz 381337bff2b9SYuval Mintz flush_workqueue(cdev->hwfns[i].iov_wq); 381437bff2b9SYuval Mintz destroy_workqueue(cdev->hwfns[i].iov_wq); 381537bff2b9SYuval Mintz } 381637bff2b9SYuval Mintz } 381737bff2b9SYuval Mintz 381837bff2b9SYuval Mintz int qed_iov_wq_start(struct qed_dev *cdev) 381937bff2b9SYuval Mintz { 382037bff2b9SYuval Mintz char name[NAME_SIZE]; 382137bff2b9SYuval Mintz int i; 382237bff2b9SYuval Mintz 382337bff2b9SYuval Mintz for_each_hwfn(cdev, i) { 382437bff2b9SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 382537bff2b9SYuval Mintz 382636558c3dSYuval Mintz /* PFs needs a dedicated workqueue only if they support IOV. 382736558c3dSYuval Mintz * VFs always require one. 382836558c3dSYuval Mintz */ 382936558c3dSYuval Mintz if (IS_PF(p_hwfn->cdev) && !IS_PF_SRIOV(p_hwfn)) 383037bff2b9SYuval Mintz continue; 383137bff2b9SYuval Mintz 383237bff2b9SYuval Mintz snprintf(name, NAME_SIZE, "iov-%02x:%02x.%02x", 383337bff2b9SYuval Mintz cdev->pdev->bus->number, 383437bff2b9SYuval Mintz PCI_SLOT(cdev->pdev->devfn), p_hwfn->abs_pf_id); 383537bff2b9SYuval Mintz 383637bff2b9SYuval Mintz p_hwfn->iov_wq = create_singlethread_workqueue(name); 383737bff2b9SYuval Mintz if (!p_hwfn->iov_wq) { 383837bff2b9SYuval Mintz DP_NOTICE(p_hwfn, "Cannot create iov workqueue\n"); 383937bff2b9SYuval Mintz return -ENOMEM; 384037bff2b9SYuval Mintz } 384137bff2b9SYuval Mintz 384236558c3dSYuval Mintz if (IS_PF(cdev)) 384337bff2b9SYuval Mintz INIT_DELAYED_WORK(&p_hwfn->iov_task, qed_iov_pf_task); 384436558c3dSYuval Mintz else 384536558c3dSYuval Mintz INIT_DELAYED_WORK(&p_hwfn->iov_task, qed_iov_vf_task); 384637bff2b9SYuval Mintz } 384737bff2b9SYuval Mintz 384837bff2b9SYuval Mintz return 0; 384937bff2b9SYuval Mintz } 38500b55e27dSYuval Mintz 38510b55e27dSYuval Mintz const struct qed_iov_hv_ops qed_iov_ops_pass = { 38520b55e27dSYuval Mintz .configure = &qed_sriov_configure, 3853eff16960SYuval Mintz .set_mac = &qed_sriov_pf_set_mac, 385408feecd7SYuval Mintz .set_vlan = &qed_sriov_pf_set_vlan, 385573390ac9SYuval Mintz .get_config = &qed_get_vf_config, 3856733def6aSYuval Mintz .set_link_state = &qed_set_vf_link_state, 38576ddc7608SYuval Mintz .set_spoof = &qed_spoof_configure, 3858733def6aSYuval Mintz .set_rate = &qed_set_vf_rate, 38590b55e27dSYuval Mintz }; 3860