11408cc1fSYuval Mintz /* QLogic qed NIC Driver 21408cc1fSYuval Mintz * Copyright (c) 2015 QLogic Corporation 31408cc1fSYuval Mintz * 41408cc1fSYuval Mintz * This software is available under the terms of the GNU General Public License 51408cc1fSYuval Mintz * (GPL) Version 2, available from the file COPYING in the main directory of 61408cc1fSYuval Mintz * this source tree. 71408cc1fSYuval Mintz */ 81408cc1fSYuval Mintz 936558c3dSYuval Mintz #include <linux/crc32.h> 10eff16960SYuval Mintz #include <linux/etherdevice.h> 111408cc1fSYuval Mintz #include "qed.h" 121408cc1fSYuval Mintz #include "qed_sriov.h" 131408cc1fSYuval Mintz #include "qed_vf.h" 141408cc1fSYuval Mintz 151408cc1fSYuval Mintz static void *qed_vf_pf_prep(struct qed_hwfn *p_hwfn, u16 type, u16 length) 161408cc1fSYuval Mintz { 171408cc1fSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 181408cc1fSYuval Mintz void *p_tlv; 191408cc1fSYuval Mintz 201408cc1fSYuval Mintz /* This lock is released when we receive PF's response 211408cc1fSYuval Mintz * in qed_send_msg2pf(). 221408cc1fSYuval Mintz * So, qed_vf_pf_prep() and qed_send_msg2pf() 231408cc1fSYuval Mintz * must come in sequence. 241408cc1fSYuval Mintz */ 251408cc1fSYuval Mintz mutex_lock(&(p_iov->mutex)); 261408cc1fSYuval Mintz 271408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 281408cc1fSYuval Mintz QED_MSG_IOV, 291408cc1fSYuval Mintz "preparing to send 0x%04x tlv over vf pf channel\n", 301408cc1fSYuval Mintz type); 311408cc1fSYuval Mintz 321408cc1fSYuval Mintz /* Reset Requst offset */ 331408cc1fSYuval Mintz p_iov->offset = (u8 *)p_iov->vf2pf_request; 341408cc1fSYuval Mintz 351408cc1fSYuval Mintz /* Clear mailbox - both request and reply */ 361408cc1fSYuval Mintz memset(p_iov->vf2pf_request, 0, sizeof(union vfpf_tlvs)); 371408cc1fSYuval Mintz memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs)); 381408cc1fSYuval Mintz 391408cc1fSYuval Mintz /* Init type and length */ 401408cc1fSYuval Mintz p_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, type, length); 411408cc1fSYuval Mintz 421408cc1fSYuval Mintz /* Init first tlv header */ 431408cc1fSYuval Mintz ((struct vfpf_first_tlv *)p_tlv)->reply_address = 441408cc1fSYuval Mintz (u64)p_iov->pf2vf_reply_phys; 451408cc1fSYuval Mintz 461408cc1fSYuval Mintz return p_tlv; 471408cc1fSYuval Mintz } 481408cc1fSYuval Mintz 49b0bccb69SYuval Mintz static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status) 50b0bccb69SYuval Mintz { 51b0bccb69SYuval Mintz union pfvf_tlvs *resp = p_hwfn->vf_iov_info->pf2vf_reply; 52b0bccb69SYuval Mintz 53b0bccb69SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 54b0bccb69SYuval Mintz "VF request status = 0x%x, PF reply status = 0x%x\n", 55b0bccb69SYuval Mintz req_status, resp->default_resp.hdr.status); 56b0bccb69SYuval Mintz 57b0bccb69SYuval Mintz mutex_unlock(&(p_hwfn->vf_iov_info->mutex)); 58b0bccb69SYuval Mintz } 59b0bccb69SYuval Mintz 601408cc1fSYuval Mintz static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size) 611408cc1fSYuval Mintz { 621408cc1fSYuval Mintz union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request; 631408cc1fSYuval Mintz struct ustorm_trigger_vf_zone trigger; 641408cc1fSYuval Mintz struct ustorm_vf_zone *zone_data; 651408cc1fSYuval Mintz int rc = 0, time = 100; 661408cc1fSYuval Mintz 671408cc1fSYuval Mintz zone_data = (struct ustorm_vf_zone *)PXP_VF_BAR0_START_USDM_ZONE_B; 681408cc1fSYuval Mintz 691408cc1fSYuval Mintz /* output tlvs list */ 701408cc1fSYuval Mintz qed_dp_tlv_list(p_hwfn, p_req); 711408cc1fSYuval Mintz 721408cc1fSYuval Mintz /* need to add the END TLV to the message size */ 731408cc1fSYuval Mintz resp_size += sizeof(struct channel_list_end_tlv); 741408cc1fSYuval Mintz 751408cc1fSYuval Mintz /* Send TLVs over HW channel */ 761408cc1fSYuval Mintz memset(&trigger, 0, sizeof(struct ustorm_trigger_vf_zone)); 771408cc1fSYuval Mintz trigger.vf_pf_msg_valid = 1; 781408cc1fSYuval Mintz 791408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 801408cc1fSYuval Mintz QED_MSG_IOV, 811408cc1fSYuval Mintz "VF -> PF [%02x] message: [%08x, %08x] --> %p, %08x --> %p\n", 821408cc1fSYuval Mintz GET_FIELD(p_hwfn->hw_info.concrete_fid, 831408cc1fSYuval Mintz PXP_CONCRETE_FID_PFID), 841408cc1fSYuval Mintz upper_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys), 851408cc1fSYuval Mintz lower_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys), 861408cc1fSYuval Mintz &zone_data->non_trigger.vf_pf_msg_addr, 871408cc1fSYuval Mintz *((u32 *)&trigger), &zone_data->trigger); 881408cc1fSYuval Mintz 891408cc1fSYuval Mintz REG_WR(p_hwfn, 901408cc1fSYuval Mintz (uintptr_t)&zone_data->non_trigger.vf_pf_msg_addr.lo, 911408cc1fSYuval Mintz lower_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys)); 921408cc1fSYuval Mintz 931408cc1fSYuval Mintz REG_WR(p_hwfn, 941408cc1fSYuval Mintz (uintptr_t)&zone_data->non_trigger.vf_pf_msg_addr.hi, 951408cc1fSYuval Mintz upper_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys)); 961408cc1fSYuval Mintz 971408cc1fSYuval Mintz /* The message data must be written first, to prevent trigger before 981408cc1fSYuval Mintz * data is written. 991408cc1fSYuval Mintz */ 1001408cc1fSYuval Mintz wmb(); 1011408cc1fSYuval Mintz 1021408cc1fSYuval Mintz REG_WR(p_hwfn, (uintptr_t)&zone_data->trigger, *((u32 *)&trigger)); 1031408cc1fSYuval Mintz 1041408cc1fSYuval Mintz /* When PF would be done with the response, it would write back to the 1051408cc1fSYuval Mintz * `done' address. Poll until then. 1061408cc1fSYuval Mintz */ 1071408cc1fSYuval Mintz while ((!*done) && time) { 1081408cc1fSYuval Mintz msleep(25); 1091408cc1fSYuval Mintz time--; 1101408cc1fSYuval Mintz } 1111408cc1fSYuval Mintz 1121408cc1fSYuval Mintz if (!*done) { 1131408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1141408cc1fSYuval Mintz "VF <-- PF Timeout [Type %d]\n", 1151408cc1fSYuval Mintz p_req->first_tlv.tl.type); 1161408cc1fSYuval Mintz rc = -EBUSY; 1171408cc1fSYuval Mintz } else { 1181408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1191408cc1fSYuval Mintz "PF response: %d [Type %d]\n", 1201408cc1fSYuval Mintz *done, p_req->first_tlv.tl.type); 1211408cc1fSYuval Mintz } 1221408cc1fSYuval Mintz 1231408cc1fSYuval Mintz return rc; 1241408cc1fSYuval Mintz } 1251408cc1fSYuval Mintz 1261408cc1fSYuval Mintz #define VF_ACQUIRE_THRESH 3 1271cf2b1a9SYuval Mintz static void qed_vf_pf_acquire_reduce_resc(struct qed_hwfn *p_hwfn, 1281cf2b1a9SYuval Mintz struct vf_pf_resc_request *p_req, 1291cf2b1a9SYuval Mintz struct pf_vf_resc *p_resp) 1301cf2b1a9SYuval Mintz { 1311cf2b1a9SYuval Mintz DP_VERBOSE(p_hwfn, 1321cf2b1a9SYuval Mintz QED_MSG_IOV, 1331cf2b1a9SYuval Mintz "PF unwilling to fullill resource request: rxq [%02x/%02x] txq [%02x/%02x] sbs [%02x/%02x] mac [%02x/%02x] vlan [%02x/%02x] mc [%02x/%02x]. Try PF recommended amount\n", 1341cf2b1a9SYuval Mintz p_req->num_rxqs, 1351cf2b1a9SYuval Mintz p_resp->num_rxqs, 1361cf2b1a9SYuval Mintz p_req->num_rxqs, 1371cf2b1a9SYuval Mintz p_resp->num_txqs, 1381cf2b1a9SYuval Mintz p_req->num_sbs, 1391cf2b1a9SYuval Mintz p_resp->num_sbs, 1401cf2b1a9SYuval Mintz p_req->num_mac_filters, 1411cf2b1a9SYuval Mintz p_resp->num_mac_filters, 1421cf2b1a9SYuval Mintz p_req->num_vlan_filters, 1431cf2b1a9SYuval Mintz p_resp->num_vlan_filters, 1441cf2b1a9SYuval Mintz p_req->num_mc_filters, p_resp->num_mc_filters); 1451cf2b1a9SYuval Mintz 1461cf2b1a9SYuval Mintz /* humble our request */ 1471cf2b1a9SYuval Mintz p_req->num_txqs = p_resp->num_txqs; 1481cf2b1a9SYuval Mintz p_req->num_rxqs = p_resp->num_rxqs; 1491cf2b1a9SYuval Mintz p_req->num_sbs = p_resp->num_sbs; 1501cf2b1a9SYuval Mintz p_req->num_mac_filters = p_resp->num_mac_filters; 1511cf2b1a9SYuval Mintz p_req->num_vlan_filters = p_resp->num_vlan_filters; 1521cf2b1a9SYuval Mintz p_req->num_mc_filters = p_resp->num_mc_filters; 1531cf2b1a9SYuval Mintz } 1541408cc1fSYuval Mintz 1551408cc1fSYuval Mintz static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn) 1561408cc1fSYuval Mintz { 1571408cc1fSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 1581408cc1fSYuval Mintz struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp; 1591408cc1fSYuval Mintz struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info; 1601cf2b1a9SYuval Mintz struct vf_pf_resc_request *p_resc; 1611408cc1fSYuval Mintz bool resources_acquired = false; 1621408cc1fSYuval Mintz struct vfpf_acquire_tlv *req; 1631408cc1fSYuval Mintz int rc = 0, attempts = 0; 1641408cc1fSYuval Mintz 1651408cc1fSYuval Mintz /* clear mailbox and prep first tlv */ 1661408cc1fSYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_ACQUIRE, sizeof(*req)); 1671cf2b1a9SYuval Mintz p_resc = &req->resc_request; 1681408cc1fSYuval Mintz 1691408cc1fSYuval Mintz /* starting filling the request */ 1701408cc1fSYuval Mintz req->vfdev_info.opaque_fid = p_hwfn->hw_info.opaque_fid; 1711408cc1fSYuval Mintz 1721cf2b1a9SYuval Mintz p_resc->num_rxqs = QED_MAX_VF_CHAINS_PER_PF; 1731cf2b1a9SYuval Mintz p_resc->num_txqs = QED_MAX_VF_CHAINS_PER_PF; 1741cf2b1a9SYuval Mintz p_resc->num_sbs = QED_MAX_VF_CHAINS_PER_PF; 1751cf2b1a9SYuval Mintz p_resc->num_mac_filters = QED_ETH_VF_NUM_MAC_FILTERS; 1761cf2b1a9SYuval Mintz p_resc->num_vlan_filters = QED_ETH_VF_NUM_VLAN_FILTERS; 1771408cc1fSYuval Mintz 1781408cc1fSYuval Mintz req->vfdev_info.os_type = VFPF_ACQUIRE_OS_LINUX; 1791408cc1fSYuval Mintz req->vfdev_info.fw_major = FW_MAJOR_VERSION; 1801408cc1fSYuval Mintz req->vfdev_info.fw_minor = FW_MINOR_VERSION; 1811408cc1fSYuval Mintz req->vfdev_info.fw_revision = FW_REVISION_VERSION; 1821408cc1fSYuval Mintz req->vfdev_info.fw_engineering = FW_ENGINEERING_VERSION; 1831fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_major = ETH_HSI_VER_MAJOR; 1841fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_minor = ETH_HSI_VER_MINOR; 1851408cc1fSYuval Mintz 1861408cc1fSYuval Mintz /* Fill capability field with any non-deprecated config we support */ 1871408cc1fSYuval Mintz req->vfdev_info.capabilities |= VFPF_ACQUIRE_CAP_100G; 1881408cc1fSYuval Mintz 1891408cc1fSYuval Mintz /* pf 2 vf bulletin board address */ 1901408cc1fSYuval Mintz req->bulletin_addr = p_iov->bulletin.phys; 1911408cc1fSYuval Mintz req->bulletin_size = p_iov->bulletin.size; 1921408cc1fSYuval Mintz 1931408cc1fSYuval Mintz /* add list termination tlv */ 1941408cc1fSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 1951408cc1fSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 1961408cc1fSYuval Mintz 1971408cc1fSYuval Mintz while (!resources_acquired) { 1981408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 1991408cc1fSYuval Mintz QED_MSG_IOV, "attempting to acquire resources\n"); 2001408cc1fSYuval Mintz 201d8c2c7e3SYuval Mintz /* Clear response buffer, as this might be a re-send */ 202d8c2c7e3SYuval Mintz memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs)); 203d8c2c7e3SYuval Mintz 2041408cc1fSYuval Mintz /* send acquire request */ 2051408cc1fSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 2061408cc1fSYuval Mintz if (rc) 2071408cc1fSYuval Mintz return rc; 2081408cc1fSYuval Mintz 2091408cc1fSYuval Mintz /* copy acquire response from buffer to p_hwfn */ 2101408cc1fSYuval Mintz memcpy(&p_iov->acquire_resp, resp, sizeof(p_iov->acquire_resp)); 2111408cc1fSYuval Mintz 2121408cc1fSYuval Mintz attempts++; 2131408cc1fSYuval Mintz 2141408cc1fSYuval Mintz if (resp->hdr.status == PFVF_STATUS_SUCCESS) { 2151408cc1fSYuval Mintz /* PF agrees to allocate our resources */ 2161408cc1fSYuval Mintz if (!(resp->pfdev_info.capabilities & 2171408cc1fSYuval Mintz PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) { 218d8c2c7e3SYuval Mintz /* It's possible legacy PF mistakenly accepted; 219d8c2c7e3SYuval Mintz * but we don't care - simply mark it as 220d8c2c7e3SYuval Mintz * legacy and continue. 221d8c2c7e3SYuval Mintz */ 222d8c2c7e3SYuval Mintz req->vfdev_info.capabilities |= 223d8c2c7e3SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI; 2241408cc1fSYuval Mintz } 2251408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n"); 2261408cc1fSYuval Mintz resources_acquired = true; 2271408cc1fSYuval Mintz } else if (resp->hdr.status == PFVF_STATUS_NO_RESOURCE && 2281408cc1fSYuval Mintz attempts < VF_ACQUIRE_THRESH) { 2291cf2b1a9SYuval Mintz qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc, 2301cf2b1a9SYuval Mintz &resp->resc); 231d8c2c7e3SYuval Mintz } else if (resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) { 232d8c2c7e3SYuval Mintz if (pfdev_info->major_fp_hsi && 2331fe614d1SYuval Mintz (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) { 2341fe614d1SYuval Mintz DP_NOTICE(p_hwfn, 2351fe614d1SYuval Mintz "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n", 2361fe614d1SYuval Mintz pfdev_info->major_fp_hsi, 2371fe614d1SYuval Mintz pfdev_info->minor_fp_hsi, 2381fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, 239d8c2c7e3SYuval Mintz ETH_HSI_VER_MINOR, 240d8c2c7e3SYuval Mintz pfdev_info->major_fp_hsi); 241d8c2c7e3SYuval Mintz rc = -EINVAL; 242d8c2c7e3SYuval Mintz goto exit; 243d8c2c7e3SYuval Mintz } 244d8c2c7e3SYuval Mintz 245d8c2c7e3SYuval Mintz if (!pfdev_info->major_fp_hsi) { 246d8c2c7e3SYuval Mintz if (req->vfdev_info.capabilities & 247d8c2c7e3SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI) { 248d8c2c7e3SYuval Mintz DP_NOTICE(p_hwfn, 249d8c2c7e3SYuval Mintz "PF uses very old drivers. Please change to a VF driver using no later than 8.8.x.x.\n"); 250d8c2c7e3SYuval Mintz rc = -EINVAL; 251d8c2c7e3SYuval Mintz goto exit; 252d8c2c7e3SYuval Mintz } else { 253d8c2c7e3SYuval Mintz DP_INFO(p_hwfn, 254d8c2c7e3SYuval Mintz "PF is old - try re-acquire to see if it supports FW-version override\n"); 255d8c2c7e3SYuval Mintz req->vfdev_info.capabilities |= 256d8c2c7e3SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI; 257d8c2c7e3SYuval Mintz continue; 258d8c2c7e3SYuval Mintz } 259d8c2c7e3SYuval Mintz } 260d8c2c7e3SYuval Mintz 261d8c2c7e3SYuval Mintz /* If PF/VF are using same Major, PF must have had 262d8c2c7e3SYuval Mintz * it's reasons. Simply fail. 263d8c2c7e3SYuval Mintz */ 264d8c2c7e3SYuval Mintz DP_NOTICE(p_hwfn, "PF rejected acquisition by VF\n"); 265d8c2c7e3SYuval Mintz rc = -EINVAL; 266d8c2c7e3SYuval Mintz goto exit; 2671408cc1fSYuval Mintz } else { 2681408cc1fSYuval Mintz DP_ERR(p_hwfn, 2691408cc1fSYuval Mintz "PF returned error %d to VF acquisition request\n", 2701408cc1fSYuval Mintz resp->hdr.status); 271d8c2c7e3SYuval Mintz rc = -EAGAIN; 272d8c2c7e3SYuval Mintz goto exit; 2731408cc1fSYuval Mintz } 2741408cc1fSYuval Mintz } 2751408cc1fSYuval Mintz 276d8c2c7e3SYuval Mintz /* Mark the PF as legacy, if needed */ 277d8c2c7e3SYuval Mintz if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_PRE_FP_HSI) 278d8c2c7e3SYuval Mintz p_iov->b_pre_fp_hsi = true; 279d8c2c7e3SYuval Mintz 2801408cc1fSYuval Mintz /* Update bulletin board size with response from PF */ 2811408cc1fSYuval Mintz p_iov->bulletin.size = resp->bulletin_size; 2821408cc1fSYuval Mintz 2831408cc1fSYuval Mintz /* get HW info */ 2841408cc1fSYuval Mintz p_hwfn->cdev->type = resp->pfdev_info.dev_type; 2851408cc1fSYuval Mintz p_hwfn->cdev->chip_rev = resp->pfdev_info.chip_rev; 2861408cc1fSYuval Mintz 2871408cc1fSYuval Mintz p_hwfn->cdev->chip_num = pfdev_info->chip_num & 0xffff; 2881408cc1fSYuval Mintz 2891408cc1fSYuval Mintz /* Learn of the possibility of CMT */ 2901408cc1fSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) { 2911408cc1fSYuval Mintz if (resp->pfdev_info.capabilities & PFVF_ACQUIRE_CAP_100G) { 2921408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "100g VF\n"); 2931408cc1fSYuval Mintz p_hwfn->cdev->num_hwfns = 2; 2941408cc1fSYuval Mintz } 2951408cc1fSYuval Mintz } 2961408cc1fSYuval Mintz 297d8c2c7e3SYuval Mintz if (!p_iov->b_pre_fp_hsi && 298d8c2c7e3SYuval Mintz ETH_HSI_VER_MINOR && 2991fe614d1SYuval Mintz (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) { 3001fe614d1SYuval Mintz DP_INFO(p_hwfn, 3011fe614d1SYuval Mintz "PF is using older fastpath HSI; %02x.%02x is configured\n", 3021fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi); 3031fe614d1SYuval Mintz } 3041fe614d1SYuval Mintz 305d8c2c7e3SYuval Mintz exit: 306b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 307b0bccb69SYuval Mintz 308d8c2c7e3SYuval Mintz return rc; 3091408cc1fSYuval Mintz } 3101408cc1fSYuval Mintz 3111408cc1fSYuval Mintz int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn) 3121408cc1fSYuval Mintz { 3131408cc1fSYuval Mintz struct qed_vf_iov *p_iov; 3141408cc1fSYuval Mintz u32 reg; 3151408cc1fSYuval Mintz 3161408cc1fSYuval Mintz /* Set number of hwfns - might be overriden once leading hwfn learns 3171408cc1fSYuval Mintz * actual configuration from PF. 3181408cc1fSYuval Mintz */ 3191408cc1fSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) 3201408cc1fSYuval Mintz p_hwfn->cdev->num_hwfns = 1; 3211408cc1fSYuval Mintz 3221408cc1fSYuval Mintz /* Set the doorbell bar. Assumption: regview is set */ 3231408cc1fSYuval Mintz p_hwfn->doorbells = (u8 __iomem *)p_hwfn->regview + 3241408cc1fSYuval Mintz PXP_VF_BAR0_START_DQ; 3251408cc1fSYuval Mintz 3261408cc1fSYuval Mintz reg = PXP_VF_BAR0_ME_OPAQUE_ADDRESS; 3271408cc1fSYuval Mintz p_hwfn->hw_info.opaque_fid = (u16)REG_RD(p_hwfn, reg); 3281408cc1fSYuval Mintz 3291408cc1fSYuval Mintz reg = PXP_VF_BAR0_ME_CONCRETE_ADDRESS; 3301408cc1fSYuval Mintz p_hwfn->hw_info.concrete_fid = REG_RD(p_hwfn, reg); 3311408cc1fSYuval Mintz 3321408cc1fSYuval Mintz /* Allocate vf sriov info */ 3331408cc1fSYuval Mintz p_iov = kzalloc(sizeof(*p_iov), GFP_KERNEL); 3342591c280SJoe Perches if (!p_iov) 3351408cc1fSYuval Mintz return -ENOMEM; 3361408cc1fSYuval Mintz 3371408cc1fSYuval Mintz /* Allocate vf2pf msg */ 3381408cc1fSYuval Mintz p_iov->vf2pf_request = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3391408cc1fSYuval Mintz sizeof(union vfpf_tlvs), 3401408cc1fSYuval Mintz &p_iov->vf2pf_request_phys, 3411408cc1fSYuval Mintz GFP_KERNEL); 3422591c280SJoe Perches if (!p_iov->vf2pf_request) 3431408cc1fSYuval Mintz goto free_p_iov; 3441408cc1fSYuval Mintz 3451408cc1fSYuval Mintz p_iov->pf2vf_reply = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3461408cc1fSYuval Mintz sizeof(union pfvf_tlvs), 3471408cc1fSYuval Mintz &p_iov->pf2vf_reply_phys, 3481408cc1fSYuval Mintz GFP_KERNEL); 3492591c280SJoe Perches if (!p_iov->pf2vf_reply) 3501408cc1fSYuval Mintz goto free_vf2pf_request; 3511408cc1fSYuval Mintz 3521408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 3531408cc1fSYuval Mintz QED_MSG_IOV, 3541408cc1fSYuval Mintz "VF's Request mailbox [%p virt 0x%llx phys], Response mailbox [%p virt 0x%llx phys]\n", 3551408cc1fSYuval Mintz p_iov->vf2pf_request, 3561408cc1fSYuval Mintz (u64) p_iov->vf2pf_request_phys, 3571408cc1fSYuval Mintz p_iov->pf2vf_reply, (u64)p_iov->pf2vf_reply_phys); 3581408cc1fSYuval Mintz 3591408cc1fSYuval Mintz /* Allocate Bulletin board */ 3601408cc1fSYuval Mintz p_iov->bulletin.size = sizeof(struct qed_bulletin_content); 3611408cc1fSYuval Mintz p_iov->bulletin.p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3621408cc1fSYuval Mintz p_iov->bulletin.size, 3631408cc1fSYuval Mintz &p_iov->bulletin.phys, 3641408cc1fSYuval Mintz GFP_KERNEL); 3651408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 3661408cc1fSYuval Mintz "VF's bulletin Board [%p virt 0x%llx phys 0x%08x bytes]\n", 3671408cc1fSYuval Mintz p_iov->bulletin.p_virt, 3681408cc1fSYuval Mintz (u64)p_iov->bulletin.phys, p_iov->bulletin.size); 3691408cc1fSYuval Mintz 3701408cc1fSYuval Mintz mutex_init(&p_iov->mutex); 3711408cc1fSYuval Mintz 3721408cc1fSYuval Mintz p_hwfn->vf_iov_info = p_iov; 3731408cc1fSYuval Mintz 3741408cc1fSYuval Mintz p_hwfn->hw_info.personality = QED_PCI_ETH; 3751408cc1fSYuval Mintz 3761408cc1fSYuval Mintz return qed_vf_pf_acquire(p_hwfn); 3771408cc1fSYuval Mintz 3781408cc1fSYuval Mintz free_vf2pf_request: 3791408cc1fSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 3801408cc1fSYuval Mintz sizeof(union vfpf_tlvs), 3811408cc1fSYuval Mintz p_iov->vf2pf_request, p_iov->vf2pf_request_phys); 3821408cc1fSYuval Mintz free_p_iov: 3831408cc1fSYuval Mintz kfree(p_iov); 3841408cc1fSYuval Mintz 3851408cc1fSYuval Mintz return -ENOMEM; 3861408cc1fSYuval Mintz } 387d8c2c7e3SYuval Mintz #define TSTORM_QZONE_START PXP_VF_BAR0_START_SDM_ZONE_A 388d8c2c7e3SYuval Mintz #define MSTORM_QZONE_START(dev) (TSTORM_QZONE_START + \ 389d8c2c7e3SYuval Mintz (TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev))) 3901408cc1fSYuval Mintz 391dacd88d6SYuval Mintz int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn, 392dacd88d6SYuval Mintz u8 rx_qid, 393dacd88d6SYuval Mintz u16 sb, 394dacd88d6SYuval Mintz u8 sb_index, 395dacd88d6SYuval Mintz u16 bd_max_bytes, 396dacd88d6SYuval Mintz dma_addr_t bd_chain_phys_addr, 397dacd88d6SYuval Mintz dma_addr_t cqe_pbl_addr, 398dacd88d6SYuval Mintz u16 cqe_pbl_size, void __iomem **pp_prod) 399dacd88d6SYuval Mintz { 400dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 401dacd88d6SYuval Mintz struct pfvf_start_queue_resp_tlv *resp; 402dacd88d6SYuval Mintz struct vfpf_start_rxq_tlv *req; 403dacd88d6SYuval Mintz int rc; 404dacd88d6SYuval Mintz 405dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 406dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_RXQ, sizeof(*req)); 407dacd88d6SYuval Mintz 408dacd88d6SYuval Mintz req->rx_qid = rx_qid; 409dacd88d6SYuval Mintz req->cqe_pbl_addr = cqe_pbl_addr; 410dacd88d6SYuval Mintz req->cqe_pbl_size = cqe_pbl_size; 411dacd88d6SYuval Mintz req->rxq_addr = bd_chain_phys_addr; 412dacd88d6SYuval Mintz req->hw_sb = sb; 413dacd88d6SYuval Mintz req->sb_index = sb_index; 414dacd88d6SYuval Mintz req->bd_max_bytes = bd_max_bytes; 415dacd88d6SYuval Mintz req->stat_id = -1; 416dacd88d6SYuval Mintz 417d8c2c7e3SYuval Mintz /* If PF is legacy, we'll need to calculate producers ourselves 418d8c2c7e3SYuval Mintz * as well as clean them. 419d8c2c7e3SYuval Mintz */ 420d8c2c7e3SYuval Mintz if (pp_prod && p_iov->b_pre_fp_hsi) { 421d8c2c7e3SYuval Mintz u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid]; 422d8c2c7e3SYuval Mintz u32 init_prod_val = 0; 423d8c2c7e3SYuval Mintz 424d8c2c7e3SYuval Mintz *pp_prod = (u8 __iomem *)p_hwfn->regview + 425d8c2c7e3SYuval Mintz MSTORM_QZONE_START(p_hwfn->cdev) + 426d8c2c7e3SYuval Mintz hw_qid * MSTORM_QZONE_SIZE; 427d8c2c7e3SYuval Mintz 428d8c2c7e3SYuval Mintz /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */ 429d8c2c7e3SYuval Mintz __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32), 430d8c2c7e3SYuval Mintz (u32 *)(&init_prod_val)); 431d8c2c7e3SYuval Mintz } 432dacd88d6SYuval Mintz /* add list termination tlv */ 433dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 434dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 435dacd88d6SYuval Mintz 436dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->queue_start; 437dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 438dacd88d6SYuval Mintz if (rc) 439b0bccb69SYuval Mintz goto exit; 440dacd88d6SYuval Mintz 441b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 442b0bccb69SYuval Mintz rc = -EINVAL; 443b0bccb69SYuval Mintz goto exit; 444b0bccb69SYuval Mintz } 445dacd88d6SYuval Mintz 446dacd88d6SYuval Mintz /* Learn the address of the producer from the response */ 447d8c2c7e3SYuval Mintz if (pp_prod && !p_iov->b_pre_fp_hsi) { 448b21290b7SYuval Mintz u32 init_prod_val = 0; 449dacd88d6SYuval Mintz 450dacd88d6SYuval Mintz *pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset; 451dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 452dacd88d6SYuval Mintz "Rxq[0x%02x]: producer at %p [offset 0x%08x]\n", 453dacd88d6SYuval Mintz rx_qid, *pp_prod, resp->offset); 454dacd88d6SYuval Mintz 455dacd88d6SYuval Mintz /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */ 456b21290b7SYuval Mintz __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32), 457dacd88d6SYuval Mintz (u32 *)&init_prod_val); 458dacd88d6SYuval Mintz } 459b0bccb69SYuval Mintz exit: 460b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 461dacd88d6SYuval Mintz 462dacd88d6SYuval Mintz return rc; 463dacd88d6SYuval Mintz } 464dacd88d6SYuval Mintz 465dacd88d6SYuval Mintz int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, u16 rx_qid, bool cqe_completion) 466dacd88d6SYuval Mintz { 467dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 468dacd88d6SYuval Mintz struct vfpf_stop_rxqs_tlv *req; 469dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 470dacd88d6SYuval Mintz int rc; 471dacd88d6SYuval Mintz 472dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 473dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_RXQS, sizeof(*req)); 474dacd88d6SYuval Mintz 475dacd88d6SYuval Mintz req->rx_qid = rx_qid; 476dacd88d6SYuval Mintz req->num_rxqs = 1; 477dacd88d6SYuval Mintz req->cqe_completion = cqe_completion; 478dacd88d6SYuval Mintz 479dacd88d6SYuval Mintz /* add list termination tlv */ 480dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 481dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 482dacd88d6SYuval Mintz 483dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 484dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 485dacd88d6SYuval Mintz if (rc) 486b0bccb69SYuval Mintz goto exit; 487dacd88d6SYuval Mintz 488b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 489b0bccb69SYuval Mintz rc = -EINVAL; 490b0bccb69SYuval Mintz goto exit; 491b0bccb69SYuval Mintz } 492b0bccb69SYuval Mintz 493b0bccb69SYuval Mintz exit: 494b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 495dacd88d6SYuval Mintz 496dacd88d6SYuval Mintz return rc; 497dacd88d6SYuval Mintz } 498dacd88d6SYuval Mintz 499dacd88d6SYuval Mintz int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn, 500dacd88d6SYuval Mintz u16 tx_queue_id, 501dacd88d6SYuval Mintz u16 sb, 502dacd88d6SYuval Mintz u8 sb_index, 503dacd88d6SYuval Mintz dma_addr_t pbl_addr, 504dacd88d6SYuval Mintz u16 pbl_size, void __iomem **pp_doorbell) 505dacd88d6SYuval Mintz { 506dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 5075040acf5SYuval Mintz struct pfvf_start_queue_resp_tlv *resp; 508dacd88d6SYuval Mintz struct vfpf_start_txq_tlv *req; 509dacd88d6SYuval Mintz int rc; 510dacd88d6SYuval Mintz 511dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 512dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_TXQ, sizeof(*req)); 513dacd88d6SYuval Mintz 514dacd88d6SYuval Mintz req->tx_qid = tx_queue_id; 515dacd88d6SYuval Mintz 516dacd88d6SYuval Mintz /* Tx */ 517dacd88d6SYuval Mintz req->pbl_addr = pbl_addr; 518dacd88d6SYuval Mintz req->pbl_size = pbl_size; 519dacd88d6SYuval Mintz req->hw_sb = sb; 520dacd88d6SYuval Mintz req->sb_index = sb_index; 521dacd88d6SYuval Mintz 522dacd88d6SYuval Mintz /* add list termination tlv */ 523dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 524dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 525dacd88d6SYuval Mintz 5265040acf5SYuval Mintz resp = &p_iov->pf2vf_reply->queue_start; 527dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 528dacd88d6SYuval Mintz if (rc) 5295040acf5SYuval Mintz goto exit; 530dacd88d6SYuval Mintz 5315040acf5SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 5325040acf5SYuval Mintz rc = -EINVAL; 5335040acf5SYuval Mintz goto exit; 5345040acf5SYuval Mintz } 535dacd88d6SYuval Mintz 536dacd88d6SYuval Mintz if (pp_doorbell) { 537d8c2c7e3SYuval Mintz /* Modern PFs provide the actual offsets, while legacy 538d8c2c7e3SYuval Mintz * provided only the queue id. 539d8c2c7e3SYuval Mintz */ 540d8c2c7e3SYuval Mintz if (!p_iov->b_pre_fp_hsi) { 541d8c2c7e3SYuval Mintz *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + 542d8c2c7e3SYuval Mintz resp->offset; 543d8c2c7e3SYuval Mintz } else { 544d8c2c7e3SYuval Mintz u8 cid = p_iov->acquire_resp.resc.cid[tx_queue_id]; 545d8c2c7e3SYuval Mintz u32 db_addr; 546d8c2c7e3SYuval Mintz 54751ff1725SRam Amrani db_addr = qed_db_addr_vf(cid, DQ_DEMS_LEGACY); 548d8c2c7e3SYuval Mintz *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + 549d8c2c7e3SYuval Mintz db_addr; 550d8c2c7e3SYuval Mintz } 551dacd88d6SYuval Mintz 5525040acf5SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 5535040acf5SYuval Mintz "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n", 5545040acf5SYuval Mintz tx_queue_id, *pp_doorbell, resp->offset); 555dacd88d6SYuval Mintz } 5565040acf5SYuval Mintz exit: 557b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 558dacd88d6SYuval Mintz 559dacd88d6SYuval Mintz return rc; 560dacd88d6SYuval Mintz } 561dacd88d6SYuval Mintz 562dacd88d6SYuval Mintz int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid) 563dacd88d6SYuval Mintz { 564dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 565dacd88d6SYuval Mintz struct vfpf_stop_txqs_tlv *req; 566dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 567dacd88d6SYuval Mintz int rc; 568dacd88d6SYuval Mintz 569dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 570dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_TXQS, sizeof(*req)); 571dacd88d6SYuval Mintz 572dacd88d6SYuval Mintz req->tx_qid = tx_qid; 573dacd88d6SYuval Mintz req->num_txqs = 1; 574dacd88d6SYuval Mintz 575dacd88d6SYuval Mintz /* add list termination tlv */ 576dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 577dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 578dacd88d6SYuval Mintz 579dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 580dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 581dacd88d6SYuval Mintz if (rc) 582b0bccb69SYuval Mintz goto exit; 583dacd88d6SYuval Mintz 584b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 585b0bccb69SYuval Mintz rc = -EINVAL; 586b0bccb69SYuval Mintz goto exit; 587b0bccb69SYuval Mintz } 588b0bccb69SYuval Mintz 589b0bccb69SYuval Mintz exit: 590b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 591dacd88d6SYuval Mintz 592dacd88d6SYuval Mintz return rc; 593dacd88d6SYuval Mintz } 594dacd88d6SYuval Mintz 595dacd88d6SYuval Mintz int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, 596dacd88d6SYuval Mintz u8 vport_id, 597dacd88d6SYuval Mintz u16 mtu, 598dacd88d6SYuval Mintz u8 inner_vlan_removal, 599dacd88d6SYuval Mintz enum qed_tpa_mode tpa_mode, 60008feecd7SYuval Mintz u8 max_buffers_per_cqe, u8 only_untagged) 601dacd88d6SYuval Mintz { 602dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 603dacd88d6SYuval Mintz struct vfpf_vport_start_tlv *req; 604dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 605dacd88d6SYuval Mintz int rc, i; 606dacd88d6SYuval Mintz 607dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 608dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_START, sizeof(*req)); 609dacd88d6SYuval Mintz 610dacd88d6SYuval Mintz req->mtu = mtu; 611dacd88d6SYuval Mintz req->vport_id = vport_id; 612dacd88d6SYuval Mintz req->inner_vlan_removal = inner_vlan_removal; 613dacd88d6SYuval Mintz req->tpa_mode = tpa_mode; 614dacd88d6SYuval Mintz req->max_buffers_per_cqe = max_buffers_per_cqe; 61508feecd7SYuval Mintz req->only_untagged = only_untagged; 616dacd88d6SYuval Mintz 617dacd88d6SYuval Mintz /* status blocks */ 618dacd88d6SYuval Mintz for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++) 619dacd88d6SYuval Mintz if (p_hwfn->sbs_info[i]) 620dacd88d6SYuval Mintz req->sb_addr[i] = p_hwfn->sbs_info[i]->sb_phys; 621dacd88d6SYuval Mintz 622dacd88d6SYuval Mintz /* add list termination tlv */ 623dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 624dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 625dacd88d6SYuval Mintz 626dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 627dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 628dacd88d6SYuval Mintz if (rc) 629b0bccb69SYuval Mintz goto exit; 630dacd88d6SYuval Mintz 631b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 632b0bccb69SYuval Mintz rc = -EINVAL; 633b0bccb69SYuval Mintz goto exit; 634b0bccb69SYuval Mintz } 635b0bccb69SYuval Mintz 636b0bccb69SYuval Mintz exit: 637b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 638dacd88d6SYuval Mintz 639dacd88d6SYuval Mintz return rc; 640dacd88d6SYuval Mintz } 641dacd88d6SYuval Mintz 642dacd88d6SYuval Mintz int qed_vf_pf_vport_stop(struct qed_hwfn *p_hwfn) 643dacd88d6SYuval Mintz { 644dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 645dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp = &p_iov->pf2vf_reply->default_resp; 646dacd88d6SYuval Mintz int rc; 647dacd88d6SYuval Mintz 648dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 649dacd88d6SYuval Mintz qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_TEARDOWN, 650dacd88d6SYuval Mintz sizeof(struct vfpf_first_tlv)); 651dacd88d6SYuval Mintz 652dacd88d6SYuval Mintz /* add list termination tlv */ 653dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 654dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 655dacd88d6SYuval Mintz 656dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 657dacd88d6SYuval Mintz if (rc) 658b0bccb69SYuval Mintz goto exit; 659dacd88d6SYuval Mintz 660b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 661b0bccb69SYuval Mintz rc = -EINVAL; 662b0bccb69SYuval Mintz goto exit; 663b0bccb69SYuval Mintz } 664b0bccb69SYuval Mintz 665b0bccb69SYuval Mintz exit: 666b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 667dacd88d6SYuval Mintz 668dacd88d6SYuval Mintz return rc; 669dacd88d6SYuval Mintz } 670dacd88d6SYuval Mintz 671dacd88d6SYuval Mintz static bool 672dacd88d6SYuval Mintz qed_vf_handle_vp_update_is_needed(struct qed_hwfn *p_hwfn, 673dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 674dacd88d6SYuval Mintz u16 tlv) 675dacd88d6SYuval Mintz { 676dacd88d6SYuval Mintz switch (tlv) { 677dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_ACTIVATE: 678dacd88d6SYuval Mintz return !!(p_data->update_vport_active_rx_flg || 679dacd88d6SYuval Mintz p_data->update_vport_active_tx_flg); 68017b235c1SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH: 68117b235c1SYuval Mintz return !!p_data->update_tx_switching_flg; 68217b235c1SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP: 68317b235c1SYuval Mintz return !!p_data->update_inner_vlan_removal_flg; 68408feecd7SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN: 68508feecd7SYuval Mintz return !!p_data->update_accept_any_vlan_flg; 686dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_MCAST: 687dacd88d6SYuval Mintz return !!p_data->update_approx_mcast_flg; 688dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM: 689dacd88d6SYuval Mintz return !!(p_data->accept_flags.update_rx_mode_config || 690dacd88d6SYuval Mintz p_data->accept_flags.update_tx_mode_config); 691dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_RSS: 692dacd88d6SYuval Mintz return !!p_data->rss_params; 69317b235c1SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_SGE_TPA: 69417b235c1SYuval Mintz return !!p_data->sge_tpa_params; 695dacd88d6SYuval Mintz default: 696dacd88d6SYuval Mintz DP_INFO(p_hwfn, "Unexpected vport-update TLV[%d]\n", 697dacd88d6SYuval Mintz tlv); 698dacd88d6SYuval Mintz return false; 699dacd88d6SYuval Mintz } 700dacd88d6SYuval Mintz } 701dacd88d6SYuval Mintz 702dacd88d6SYuval Mintz static void 703dacd88d6SYuval Mintz qed_vf_handle_vp_update_tlvs_resp(struct qed_hwfn *p_hwfn, 704dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data) 705dacd88d6SYuval Mintz { 706dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 707dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *p_resp; 708dacd88d6SYuval Mintz u16 tlv; 709dacd88d6SYuval Mintz 710dacd88d6SYuval Mintz for (tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE; 711dacd88d6SYuval Mintz tlv < CHANNEL_TLV_VPORT_UPDATE_MAX; tlv++) { 712dacd88d6SYuval Mintz if (!qed_vf_handle_vp_update_is_needed(p_hwfn, p_data, tlv)) 713dacd88d6SYuval Mintz continue; 714dacd88d6SYuval Mintz 715dacd88d6SYuval Mintz p_resp = (struct pfvf_def_resp_tlv *) 716dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_iov->pf2vf_reply, 717dacd88d6SYuval Mintz tlv); 718dacd88d6SYuval Mintz if (p_resp && p_resp->hdr.status) 719dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 720dacd88d6SYuval Mintz "TLV[%d] Configuration %s\n", 721dacd88d6SYuval Mintz tlv, 722dacd88d6SYuval Mintz (p_resp && p_resp->hdr.status) ? "succeeded" 723dacd88d6SYuval Mintz : "failed"); 724dacd88d6SYuval Mintz } 725dacd88d6SYuval Mintz } 726dacd88d6SYuval Mintz 727dacd88d6SYuval Mintz int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, 728dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_params) 729dacd88d6SYuval Mintz { 730dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 731dacd88d6SYuval Mintz struct vfpf_vport_update_tlv *req; 732dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 733dacd88d6SYuval Mintz u8 update_rx, update_tx; 734dacd88d6SYuval Mintz u32 resp_size = 0; 735dacd88d6SYuval Mintz u16 size, tlv; 736dacd88d6SYuval Mintz int rc; 737dacd88d6SYuval Mintz 738dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 739dacd88d6SYuval Mintz resp_size = sizeof(*resp); 740dacd88d6SYuval Mintz 741dacd88d6SYuval Mintz update_rx = p_params->update_vport_active_rx_flg; 742dacd88d6SYuval Mintz update_tx = p_params->update_vport_active_tx_flg; 743dacd88d6SYuval Mintz 744dacd88d6SYuval Mintz /* clear mailbox and prep header tlv */ 745dacd88d6SYuval Mintz qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_UPDATE, sizeof(*req)); 746dacd88d6SYuval Mintz 747dacd88d6SYuval Mintz /* Prepare extended tlvs */ 748dacd88d6SYuval Mintz if (update_rx || update_tx) { 749dacd88d6SYuval Mintz struct vfpf_vport_update_activate_tlv *p_act_tlv; 750dacd88d6SYuval Mintz 751dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_activate_tlv); 752dacd88d6SYuval Mintz p_act_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, 753dacd88d6SYuval Mintz CHANNEL_TLV_VPORT_UPDATE_ACTIVATE, 754dacd88d6SYuval Mintz size); 755dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 756dacd88d6SYuval Mintz 757dacd88d6SYuval Mintz if (update_rx) { 758dacd88d6SYuval Mintz p_act_tlv->update_rx = update_rx; 759dacd88d6SYuval Mintz p_act_tlv->active_rx = p_params->vport_active_rx_flg; 760dacd88d6SYuval Mintz } 761dacd88d6SYuval Mintz 762dacd88d6SYuval Mintz if (update_tx) { 763dacd88d6SYuval Mintz p_act_tlv->update_tx = update_tx; 764dacd88d6SYuval Mintz p_act_tlv->active_tx = p_params->vport_active_tx_flg; 765dacd88d6SYuval Mintz } 766dacd88d6SYuval Mintz } 767dacd88d6SYuval Mintz 768831bfb0eSYuval Mintz if (p_params->update_tx_switching_flg) { 769831bfb0eSYuval Mintz struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv; 770831bfb0eSYuval Mintz 771831bfb0eSYuval Mintz size = sizeof(struct vfpf_vport_update_tx_switch_tlv); 772831bfb0eSYuval Mintz tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; 773831bfb0eSYuval Mintz p_tx_switch_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, 774831bfb0eSYuval Mintz tlv, size); 775831bfb0eSYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 776831bfb0eSYuval Mintz 777831bfb0eSYuval Mintz p_tx_switch_tlv->tx_switching = p_params->tx_switching_flg; 778831bfb0eSYuval Mintz } 779831bfb0eSYuval Mintz 780dacd88d6SYuval Mintz if (p_params->update_approx_mcast_flg) { 781dacd88d6SYuval Mintz struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv; 782dacd88d6SYuval Mintz 783dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_mcast_bin_tlv); 784dacd88d6SYuval Mintz p_mcast_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, 785dacd88d6SYuval Mintz CHANNEL_TLV_VPORT_UPDATE_MCAST, size); 786dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 787dacd88d6SYuval Mintz 788dacd88d6SYuval Mintz memcpy(p_mcast_tlv->bins, p_params->bins, 789dacd88d6SYuval Mintz sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS); 790dacd88d6SYuval Mintz } 791dacd88d6SYuval Mintz 792dacd88d6SYuval Mintz update_rx = p_params->accept_flags.update_rx_mode_config; 793dacd88d6SYuval Mintz update_tx = p_params->accept_flags.update_tx_mode_config; 794dacd88d6SYuval Mintz 795dacd88d6SYuval Mintz if (update_rx || update_tx) { 796dacd88d6SYuval Mintz struct vfpf_vport_update_accept_param_tlv *p_accept_tlv; 797dacd88d6SYuval Mintz 798dacd88d6SYuval Mintz tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; 799dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_accept_param_tlv); 800dacd88d6SYuval Mintz p_accept_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); 801dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 802dacd88d6SYuval Mintz 803dacd88d6SYuval Mintz if (update_rx) { 804dacd88d6SYuval Mintz p_accept_tlv->update_rx_mode = update_rx; 805dacd88d6SYuval Mintz p_accept_tlv->rx_accept_filter = 806dacd88d6SYuval Mintz p_params->accept_flags.rx_accept_filter; 807dacd88d6SYuval Mintz } 808dacd88d6SYuval Mintz 809dacd88d6SYuval Mintz if (update_tx) { 810dacd88d6SYuval Mintz p_accept_tlv->update_tx_mode = update_tx; 811dacd88d6SYuval Mintz p_accept_tlv->tx_accept_filter = 812dacd88d6SYuval Mintz p_params->accept_flags.tx_accept_filter; 813dacd88d6SYuval Mintz } 814dacd88d6SYuval Mintz } 815dacd88d6SYuval Mintz 816dacd88d6SYuval Mintz if (p_params->rss_params) { 817dacd88d6SYuval Mintz struct qed_rss_params *rss_params = p_params->rss_params; 818dacd88d6SYuval Mintz struct vfpf_vport_update_rss_tlv *p_rss_tlv; 819dacd88d6SYuval Mintz 820dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_rss_tlv); 821dacd88d6SYuval Mintz p_rss_tlv = qed_add_tlv(p_hwfn, 822dacd88d6SYuval Mintz &p_iov->offset, 823dacd88d6SYuval Mintz CHANNEL_TLV_VPORT_UPDATE_RSS, size); 824dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 825dacd88d6SYuval Mintz 826dacd88d6SYuval Mintz if (rss_params->update_rss_config) 827dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= 828dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CONFIG_FLAG; 829dacd88d6SYuval Mintz if (rss_params->update_rss_capabilities) 830dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= 831dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CAPS_FLAG; 832dacd88d6SYuval Mintz if (rss_params->update_rss_ind_table) 833dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= 834dacd88d6SYuval Mintz VFPF_UPDATE_RSS_IND_TABLE_FLAG; 835dacd88d6SYuval Mintz if (rss_params->update_rss_key) 836dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= VFPF_UPDATE_RSS_KEY_FLAG; 837dacd88d6SYuval Mintz 838dacd88d6SYuval Mintz p_rss_tlv->rss_enable = rss_params->rss_enable; 839dacd88d6SYuval Mintz p_rss_tlv->rss_caps = rss_params->rss_caps; 840dacd88d6SYuval Mintz p_rss_tlv->rss_table_size_log = rss_params->rss_table_size_log; 841dacd88d6SYuval Mintz memcpy(p_rss_tlv->rss_ind_table, rss_params->rss_ind_table, 842dacd88d6SYuval Mintz sizeof(rss_params->rss_ind_table)); 843dacd88d6SYuval Mintz memcpy(p_rss_tlv->rss_key, rss_params->rss_key, 844dacd88d6SYuval Mintz sizeof(rss_params->rss_key)); 845dacd88d6SYuval Mintz } 846dacd88d6SYuval Mintz 84708feecd7SYuval Mintz if (p_params->update_accept_any_vlan_flg) { 84808feecd7SYuval Mintz struct vfpf_vport_update_accept_any_vlan_tlv *p_any_vlan_tlv; 84908feecd7SYuval Mintz 85008feecd7SYuval Mintz size = sizeof(struct vfpf_vport_update_accept_any_vlan_tlv); 85108feecd7SYuval Mintz tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; 85208feecd7SYuval Mintz p_any_vlan_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); 85308feecd7SYuval Mintz 85408feecd7SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 85508feecd7SYuval Mintz p_any_vlan_tlv->accept_any_vlan = p_params->accept_any_vlan; 85608feecd7SYuval Mintz p_any_vlan_tlv->update_accept_any_vlan_flg = 85708feecd7SYuval Mintz p_params->update_accept_any_vlan_flg; 85808feecd7SYuval Mintz } 85908feecd7SYuval Mintz 860dacd88d6SYuval Mintz /* add list termination tlv */ 861dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 862dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 863dacd88d6SYuval Mintz 864dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, resp_size); 865dacd88d6SYuval Mintz if (rc) 866b0bccb69SYuval Mintz goto exit; 867dacd88d6SYuval Mintz 868b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 869b0bccb69SYuval Mintz rc = -EINVAL; 870b0bccb69SYuval Mintz goto exit; 871b0bccb69SYuval Mintz } 872dacd88d6SYuval Mintz 873dacd88d6SYuval Mintz qed_vf_handle_vp_update_tlvs_resp(p_hwfn, p_params); 874dacd88d6SYuval Mintz 875b0bccb69SYuval Mintz exit: 876b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 877b0bccb69SYuval Mintz 878dacd88d6SYuval Mintz return rc; 879dacd88d6SYuval Mintz } 880dacd88d6SYuval Mintz 8810b55e27dSYuval Mintz int qed_vf_pf_reset(struct qed_hwfn *p_hwfn) 8820b55e27dSYuval Mintz { 8830b55e27dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 8840b55e27dSYuval Mintz struct pfvf_def_resp_tlv *resp; 8850b55e27dSYuval Mintz struct vfpf_first_tlv *req; 8860b55e27dSYuval Mintz int rc; 8870b55e27dSYuval Mintz 8880b55e27dSYuval Mintz /* clear mailbox and prep first tlv */ 8890b55e27dSYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_CLOSE, sizeof(*req)); 8900b55e27dSYuval Mintz 8910b55e27dSYuval Mintz /* add list termination tlv */ 8920b55e27dSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 8930b55e27dSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 8940b55e27dSYuval Mintz 8950b55e27dSYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 8960b55e27dSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 8970b55e27dSYuval Mintz if (rc) 898b0bccb69SYuval Mintz goto exit; 8990b55e27dSYuval Mintz 900b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 901b0bccb69SYuval Mintz rc = -EAGAIN; 902b0bccb69SYuval Mintz goto exit; 903b0bccb69SYuval Mintz } 9040b55e27dSYuval Mintz 9050b55e27dSYuval Mintz p_hwfn->b_int_enabled = 0; 9060b55e27dSYuval Mintz 907b0bccb69SYuval Mintz exit: 908b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 909b0bccb69SYuval Mintz 910b0bccb69SYuval Mintz return rc; 9110b55e27dSYuval Mintz } 9120b55e27dSYuval Mintz 9130b55e27dSYuval Mintz int qed_vf_pf_release(struct qed_hwfn *p_hwfn) 9140b55e27dSYuval Mintz { 9150b55e27dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 9160b55e27dSYuval Mintz struct pfvf_def_resp_tlv *resp; 9170b55e27dSYuval Mintz struct vfpf_first_tlv *req; 9180b55e27dSYuval Mintz u32 size; 9190b55e27dSYuval Mintz int rc; 9200b55e27dSYuval Mintz 9210b55e27dSYuval Mintz /* clear mailbox and prep first tlv */ 9220b55e27dSYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_RELEASE, sizeof(*req)); 9230b55e27dSYuval Mintz 9240b55e27dSYuval Mintz /* add list termination tlv */ 9250b55e27dSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 9260b55e27dSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 9270b55e27dSYuval Mintz 9280b55e27dSYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 9290b55e27dSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 9300b55e27dSYuval Mintz 9310b55e27dSYuval Mintz if (!rc && resp->hdr.status != PFVF_STATUS_SUCCESS) 9320b55e27dSYuval Mintz rc = -EAGAIN; 9330b55e27dSYuval Mintz 934b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 935b0bccb69SYuval Mintz 9360b55e27dSYuval Mintz p_hwfn->b_int_enabled = 0; 9370b55e27dSYuval Mintz 9380b55e27dSYuval Mintz if (p_iov->vf2pf_request) 9390b55e27dSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 9400b55e27dSYuval Mintz sizeof(union vfpf_tlvs), 9410b55e27dSYuval Mintz p_iov->vf2pf_request, 9420b55e27dSYuval Mintz p_iov->vf2pf_request_phys); 9430b55e27dSYuval Mintz if (p_iov->pf2vf_reply) 9440b55e27dSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 9450b55e27dSYuval Mintz sizeof(union pfvf_tlvs), 9460b55e27dSYuval Mintz p_iov->pf2vf_reply, p_iov->pf2vf_reply_phys); 9470b55e27dSYuval Mintz 9480b55e27dSYuval Mintz if (p_iov->bulletin.p_virt) { 9490b55e27dSYuval Mintz size = sizeof(struct qed_bulletin_content); 9500b55e27dSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 9510b55e27dSYuval Mintz size, 9520b55e27dSYuval Mintz p_iov->bulletin.p_virt, p_iov->bulletin.phys); 9530b55e27dSYuval Mintz } 9540b55e27dSYuval Mintz 9550b55e27dSYuval Mintz kfree(p_hwfn->vf_iov_info); 9560b55e27dSYuval Mintz p_hwfn->vf_iov_info = NULL; 9570b55e27dSYuval Mintz 9580b55e27dSYuval Mintz return rc; 9590b55e27dSYuval Mintz } 9600b55e27dSYuval Mintz 961dacd88d6SYuval Mintz void qed_vf_pf_filter_mcast(struct qed_hwfn *p_hwfn, 962dacd88d6SYuval Mintz struct qed_filter_mcast *p_filter_cmd) 963dacd88d6SYuval Mintz { 964dacd88d6SYuval Mintz struct qed_sp_vport_update_params sp_params; 965dacd88d6SYuval Mintz int i; 966dacd88d6SYuval Mintz 967dacd88d6SYuval Mintz memset(&sp_params, 0, sizeof(sp_params)); 968dacd88d6SYuval Mintz sp_params.update_approx_mcast_flg = 1; 969dacd88d6SYuval Mintz 970dacd88d6SYuval Mintz if (p_filter_cmd->opcode == QED_FILTER_ADD) { 971dacd88d6SYuval Mintz for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { 972dacd88d6SYuval Mintz u32 bit; 973dacd88d6SYuval Mintz 974dacd88d6SYuval Mintz bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]); 975dacd88d6SYuval Mintz __set_bit(bit, sp_params.bins); 976dacd88d6SYuval Mintz } 977dacd88d6SYuval Mintz } 978dacd88d6SYuval Mintz 979dacd88d6SYuval Mintz qed_vf_pf_vport_update(p_hwfn, &sp_params); 980dacd88d6SYuval Mintz } 981dacd88d6SYuval Mintz 982dacd88d6SYuval Mintz int qed_vf_pf_filter_ucast(struct qed_hwfn *p_hwfn, 983dacd88d6SYuval Mintz struct qed_filter_ucast *p_ucast) 984dacd88d6SYuval Mintz { 985dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 986dacd88d6SYuval Mintz struct vfpf_ucast_filter_tlv *req; 987dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 988dacd88d6SYuval Mintz int rc; 989dacd88d6SYuval Mintz 990dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 991dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_UCAST_FILTER, sizeof(*req)); 992dacd88d6SYuval Mintz req->opcode = (u8) p_ucast->opcode; 993dacd88d6SYuval Mintz req->type = (u8) p_ucast->type; 994dacd88d6SYuval Mintz memcpy(req->mac, p_ucast->mac, ETH_ALEN); 995dacd88d6SYuval Mintz req->vlan = p_ucast->vlan; 996dacd88d6SYuval Mintz 997dacd88d6SYuval Mintz /* add list termination tlv */ 998dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 999dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 1000dacd88d6SYuval Mintz 1001dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 1002dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 1003dacd88d6SYuval Mintz if (rc) 1004b0bccb69SYuval Mintz goto exit; 1005b0bccb69SYuval Mintz 1006b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 1007b0bccb69SYuval Mintz rc = -EAGAIN; 1008b0bccb69SYuval Mintz goto exit; 1009b0bccb69SYuval Mintz } 1010b0bccb69SYuval Mintz 1011b0bccb69SYuval Mintz exit: 1012b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1013b0bccb69SYuval Mintz 1014dacd88d6SYuval Mintz return rc; 1015dacd88d6SYuval Mintz } 1016dacd88d6SYuval Mintz 10170b55e27dSYuval Mintz int qed_vf_pf_int_cleanup(struct qed_hwfn *p_hwfn) 10180b55e27dSYuval Mintz { 10190b55e27dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 10200b55e27dSYuval Mintz struct pfvf_def_resp_tlv *resp = &p_iov->pf2vf_reply->default_resp; 10210b55e27dSYuval Mintz int rc; 10220b55e27dSYuval Mintz 10230b55e27dSYuval Mintz /* clear mailbox and prep first tlv */ 10240b55e27dSYuval Mintz qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_INT_CLEANUP, 10250b55e27dSYuval Mintz sizeof(struct vfpf_first_tlv)); 10260b55e27dSYuval Mintz 10270b55e27dSYuval Mintz /* add list termination tlv */ 10280b55e27dSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 10290b55e27dSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 10300b55e27dSYuval Mintz 10310b55e27dSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 10320b55e27dSYuval Mintz if (rc) 1033b0bccb69SYuval Mintz goto exit; 1034b0bccb69SYuval Mintz 1035b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 1036b0bccb69SYuval Mintz rc = -EINVAL; 1037b0bccb69SYuval Mintz goto exit; 1038b0bccb69SYuval Mintz } 1039b0bccb69SYuval Mintz 1040b0bccb69SYuval Mintz exit: 1041b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1042b0bccb69SYuval Mintz 10430b55e27dSYuval Mintz return rc; 10440b55e27dSYuval Mintz } 10450b55e27dSYuval Mintz 10461408cc1fSYuval Mintz u16 qed_vf_get_igu_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id) 10471408cc1fSYuval Mintz { 10481408cc1fSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 10491408cc1fSYuval Mintz 10501408cc1fSYuval Mintz if (!p_iov) { 10511408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "vf_sriov_info isn't initialized\n"); 10521408cc1fSYuval Mintz return 0; 10531408cc1fSYuval Mintz } 10541408cc1fSYuval Mintz 10551408cc1fSYuval Mintz return p_iov->acquire_resp.resc.hw_sbs[sb_id].hw_sb_id; 10561408cc1fSYuval Mintz } 10571408cc1fSYuval Mintz 105836558c3dSYuval Mintz int qed_vf_read_bulletin(struct qed_hwfn *p_hwfn, u8 *p_change) 105936558c3dSYuval Mintz { 106036558c3dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 106136558c3dSYuval Mintz struct qed_bulletin_content shadow; 106236558c3dSYuval Mintz u32 crc, crc_size; 106336558c3dSYuval Mintz 106436558c3dSYuval Mintz crc_size = sizeof(p_iov->bulletin.p_virt->crc); 106536558c3dSYuval Mintz *p_change = 0; 106636558c3dSYuval Mintz 106736558c3dSYuval Mintz /* Need to guarantee PF is not in the middle of writing it */ 106836558c3dSYuval Mintz memcpy(&shadow, p_iov->bulletin.p_virt, p_iov->bulletin.size); 106936558c3dSYuval Mintz 107036558c3dSYuval Mintz /* If version did not update, no need to do anything */ 107136558c3dSYuval Mintz if (shadow.version == p_iov->bulletin_shadow.version) 107236558c3dSYuval Mintz return 0; 107336558c3dSYuval Mintz 107436558c3dSYuval Mintz /* Verify the bulletin we see is valid */ 107536558c3dSYuval Mintz crc = crc32(0, (u8 *)&shadow + crc_size, 107636558c3dSYuval Mintz p_iov->bulletin.size - crc_size); 107736558c3dSYuval Mintz if (crc != shadow.crc) 107836558c3dSYuval Mintz return -EAGAIN; 107936558c3dSYuval Mintz 108036558c3dSYuval Mintz /* Set the shadow bulletin and process it */ 108136558c3dSYuval Mintz memcpy(&p_iov->bulletin_shadow, &shadow, p_iov->bulletin.size); 108236558c3dSYuval Mintz 108336558c3dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 108436558c3dSYuval Mintz "Read a bulletin update %08x\n", shadow.version); 108536558c3dSYuval Mintz 108636558c3dSYuval Mintz *p_change = 1; 108736558c3dSYuval Mintz 108836558c3dSYuval Mintz return 0; 108936558c3dSYuval Mintz } 109036558c3dSYuval Mintz 109136558c3dSYuval Mintz void __qed_vf_get_link_params(struct qed_hwfn *p_hwfn, 109236558c3dSYuval Mintz struct qed_mcp_link_params *p_params, 109336558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin) 109436558c3dSYuval Mintz { 109536558c3dSYuval Mintz memset(p_params, 0, sizeof(*p_params)); 109636558c3dSYuval Mintz 109736558c3dSYuval Mintz p_params->speed.autoneg = p_bulletin->req_autoneg; 109836558c3dSYuval Mintz p_params->speed.advertised_speeds = p_bulletin->req_adv_speed; 109936558c3dSYuval Mintz p_params->speed.forced_speed = p_bulletin->req_forced_speed; 110036558c3dSYuval Mintz p_params->pause.autoneg = p_bulletin->req_autoneg_pause; 110136558c3dSYuval Mintz p_params->pause.forced_rx = p_bulletin->req_forced_rx; 110236558c3dSYuval Mintz p_params->pause.forced_tx = p_bulletin->req_forced_tx; 110336558c3dSYuval Mintz p_params->loopback_mode = p_bulletin->req_loopback; 110436558c3dSYuval Mintz } 110536558c3dSYuval Mintz 110636558c3dSYuval Mintz void qed_vf_get_link_params(struct qed_hwfn *p_hwfn, 110736558c3dSYuval Mintz struct qed_mcp_link_params *params) 110836558c3dSYuval Mintz { 110936558c3dSYuval Mintz __qed_vf_get_link_params(p_hwfn, params, 111036558c3dSYuval Mintz &(p_hwfn->vf_iov_info->bulletin_shadow)); 111136558c3dSYuval Mintz } 111236558c3dSYuval Mintz 111336558c3dSYuval Mintz void __qed_vf_get_link_state(struct qed_hwfn *p_hwfn, 111436558c3dSYuval Mintz struct qed_mcp_link_state *p_link, 111536558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin) 111636558c3dSYuval Mintz { 111736558c3dSYuval Mintz memset(p_link, 0, sizeof(*p_link)); 111836558c3dSYuval Mintz 111936558c3dSYuval Mintz p_link->link_up = p_bulletin->link_up; 112036558c3dSYuval Mintz p_link->speed = p_bulletin->speed; 112136558c3dSYuval Mintz p_link->full_duplex = p_bulletin->full_duplex; 112236558c3dSYuval Mintz p_link->an = p_bulletin->autoneg; 112336558c3dSYuval Mintz p_link->an_complete = p_bulletin->autoneg_complete; 112436558c3dSYuval Mintz p_link->parallel_detection = p_bulletin->parallel_detection; 112536558c3dSYuval Mintz p_link->pfc_enabled = p_bulletin->pfc_enabled; 112636558c3dSYuval Mintz p_link->partner_adv_speed = p_bulletin->partner_adv_speed; 112736558c3dSYuval Mintz p_link->partner_tx_flow_ctrl_en = p_bulletin->partner_tx_flow_ctrl_en; 112836558c3dSYuval Mintz p_link->partner_rx_flow_ctrl_en = p_bulletin->partner_rx_flow_ctrl_en; 112936558c3dSYuval Mintz p_link->partner_adv_pause = p_bulletin->partner_adv_pause; 113036558c3dSYuval Mintz p_link->sfp_tx_fault = p_bulletin->sfp_tx_fault; 113136558c3dSYuval Mintz } 113236558c3dSYuval Mintz 113336558c3dSYuval Mintz void qed_vf_get_link_state(struct qed_hwfn *p_hwfn, 113436558c3dSYuval Mintz struct qed_mcp_link_state *link) 113536558c3dSYuval Mintz { 113636558c3dSYuval Mintz __qed_vf_get_link_state(p_hwfn, link, 113736558c3dSYuval Mintz &(p_hwfn->vf_iov_info->bulletin_shadow)); 113836558c3dSYuval Mintz } 113936558c3dSYuval Mintz 114036558c3dSYuval Mintz void __qed_vf_get_link_caps(struct qed_hwfn *p_hwfn, 114136558c3dSYuval Mintz struct qed_mcp_link_capabilities *p_link_caps, 114236558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin) 114336558c3dSYuval Mintz { 114436558c3dSYuval Mintz memset(p_link_caps, 0, sizeof(*p_link_caps)); 114536558c3dSYuval Mintz p_link_caps->speed_capabilities = p_bulletin->capability_speed; 114636558c3dSYuval Mintz } 114736558c3dSYuval Mintz 114836558c3dSYuval Mintz void qed_vf_get_link_caps(struct qed_hwfn *p_hwfn, 114936558c3dSYuval Mintz struct qed_mcp_link_capabilities *p_link_caps) 115036558c3dSYuval Mintz { 115136558c3dSYuval Mintz __qed_vf_get_link_caps(p_hwfn, p_link_caps, 115236558c3dSYuval Mintz &(p_hwfn->vf_iov_info->bulletin_shadow)); 115336558c3dSYuval Mintz } 115436558c3dSYuval Mintz 11551408cc1fSYuval Mintz void qed_vf_get_num_rxqs(struct qed_hwfn *p_hwfn, u8 *num_rxqs) 11561408cc1fSYuval Mintz { 11571408cc1fSYuval Mintz *num_rxqs = p_hwfn->vf_iov_info->acquire_resp.resc.num_rxqs; 11581408cc1fSYuval Mintz } 11591408cc1fSYuval Mintz 11601408cc1fSYuval Mintz void qed_vf_get_port_mac(struct qed_hwfn *p_hwfn, u8 *port_mac) 11611408cc1fSYuval Mintz { 11621408cc1fSYuval Mintz memcpy(port_mac, 11631408cc1fSYuval Mintz p_hwfn->vf_iov_info->acquire_resp.pfdev_info.port_mac, ETH_ALEN); 11641408cc1fSYuval Mintz } 11651408cc1fSYuval Mintz 11661408cc1fSYuval Mintz void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters) 11671408cc1fSYuval Mintz { 11681408cc1fSYuval Mintz struct qed_vf_iov *p_vf; 11691408cc1fSYuval Mintz 11701408cc1fSYuval Mintz p_vf = p_hwfn->vf_iov_info; 11711408cc1fSYuval Mintz *num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters; 11721408cc1fSYuval Mintz } 11731408cc1fSYuval Mintz 1174b0fca312SMintz, Yuval void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters) 1175b0fca312SMintz, Yuval { 1176b0fca312SMintz, Yuval struct qed_vf_iov *p_vf = p_hwfn->vf_iov_info; 1177b0fca312SMintz, Yuval 1178b0fca312SMintz, Yuval *num_mac_filters = p_vf->acquire_resp.resc.num_mac_filters; 1179b0fca312SMintz, Yuval } 1180b0fca312SMintz, Yuval 1181eff16960SYuval Mintz bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac) 1182eff16960SYuval Mintz { 1183eff16960SYuval Mintz struct qed_bulletin_content *bulletin; 1184eff16960SYuval Mintz 1185eff16960SYuval Mintz bulletin = &p_hwfn->vf_iov_info->bulletin_shadow; 1186eff16960SYuval Mintz if (!(bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED))) 1187eff16960SYuval Mintz return true; 1188eff16960SYuval Mintz 1189eff16960SYuval Mintz /* Forbid VF from changing a MAC enforced by PF */ 1190eff16960SYuval Mintz if (ether_addr_equal(bulletin->mac, mac)) 1191eff16960SYuval Mintz return false; 1192eff16960SYuval Mintz 1193eff16960SYuval Mintz return false; 1194eff16960SYuval Mintz } 1195eff16960SYuval Mintz 1196ba56947aSBaoyou Xie static bool qed_vf_bulletin_get_forced_mac(struct qed_hwfn *hwfn, 1197eff16960SYuval Mintz u8 *dst_mac, u8 *p_is_forced) 1198eff16960SYuval Mintz { 1199eff16960SYuval Mintz struct qed_bulletin_content *bulletin; 1200eff16960SYuval Mintz 1201eff16960SYuval Mintz bulletin = &hwfn->vf_iov_info->bulletin_shadow; 1202eff16960SYuval Mintz 1203eff16960SYuval Mintz if (bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) { 1204eff16960SYuval Mintz if (p_is_forced) 1205eff16960SYuval Mintz *p_is_forced = 1; 1206eff16960SYuval Mintz } else if (bulletin->valid_bitmap & (1 << VFPF_BULLETIN_MAC_ADDR)) { 1207eff16960SYuval Mintz if (p_is_forced) 1208eff16960SYuval Mintz *p_is_forced = 0; 1209eff16960SYuval Mintz } else { 1210eff16960SYuval Mintz return false; 1211eff16960SYuval Mintz } 1212eff16960SYuval Mintz 1213eff16960SYuval Mintz ether_addr_copy(dst_mac, bulletin->mac); 1214eff16960SYuval Mintz 1215eff16960SYuval Mintz return true; 1216eff16960SYuval Mintz } 1217eff16960SYuval Mintz 12181408cc1fSYuval Mintz void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn, 12191408cc1fSYuval Mintz u16 *fw_major, u16 *fw_minor, 12201408cc1fSYuval Mintz u16 *fw_rev, u16 *fw_eng) 12211408cc1fSYuval Mintz { 12221408cc1fSYuval Mintz struct pf_vf_pfdev_info *info; 12231408cc1fSYuval Mintz 12241408cc1fSYuval Mintz info = &p_hwfn->vf_iov_info->acquire_resp.pfdev_info; 12251408cc1fSYuval Mintz 12261408cc1fSYuval Mintz *fw_major = info->fw_major; 12271408cc1fSYuval Mintz *fw_minor = info->fw_minor; 12281408cc1fSYuval Mintz *fw_rev = info->fw_rev; 12291408cc1fSYuval Mintz *fw_eng = info->fw_eng; 12301408cc1fSYuval Mintz } 123136558c3dSYuval Mintz 123236558c3dSYuval Mintz static void qed_handle_bulletin_change(struct qed_hwfn *hwfn) 123336558c3dSYuval Mintz { 1234eff16960SYuval Mintz struct qed_eth_cb_ops *ops = hwfn->cdev->protocol_ops.eth; 1235eff16960SYuval Mintz u8 mac[ETH_ALEN], is_mac_exist, is_mac_forced; 1236eff16960SYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 1237eff16960SYuval Mintz 1238eff16960SYuval Mintz is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac, 1239eff16960SYuval Mintz &is_mac_forced); 1240c3aaa403SYuval Mintz if (is_mac_exist && cookie) 1241c3aaa403SYuval Mintz ops->force_mac(cookie, mac, !!is_mac_forced); 1242eff16960SYuval Mintz 124336558c3dSYuval Mintz /* Always update link configuration according to bulletin */ 124436558c3dSYuval Mintz qed_link_update(hwfn); 124536558c3dSYuval Mintz } 124636558c3dSYuval Mintz 124736558c3dSYuval Mintz void qed_iov_vf_task(struct work_struct *work) 124836558c3dSYuval Mintz { 124936558c3dSYuval Mintz struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn, 125036558c3dSYuval Mintz iov_task.work); 125136558c3dSYuval Mintz u8 change = 0; 125236558c3dSYuval Mintz 125336558c3dSYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_STOP_WQ_FLAG, &hwfn->iov_task_flags)) 125436558c3dSYuval Mintz return; 125536558c3dSYuval Mintz 125636558c3dSYuval Mintz /* Handle bulletin board changes */ 125736558c3dSYuval Mintz qed_vf_read_bulletin(hwfn, &change); 125836558c3dSYuval Mintz if (change) 125936558c3dSYuval Mintz qed_handle_bulletin_change(hwfn); 126036558c3dSYuval Mintz 126136558c3dSYuval Mintz /* As VF is polling bulletin board, need to constantly re-schedule */ 126236558c3dSYuval Mintz queue_delayed_work(hwfn->iov_wq, &hwfn->iov_task, HZ); 126336558c3dSYuval Mintz } 1264