11408cc1fSYuval Mintz /* QLogic qed NIC Driver 2e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 31408cc1fSYuval Mintz * 4e8f1cb50SMintz, Yuval * This software is available to you under a choice of one of two 5e8f1cb50SMintz, Yuval * licenses. You may choose to be licensed under the terms of the GNU 6e8f1cb50SMintz, Yuval * General Public License (GPL) Version 2, available from the file 7e8f1cb50SMintz, Yuval * COPYING in the main directory of this source tree, or the 8e8f1cb50SMintz, Yuval * OpenIB.org BSD license below: 9e8f1cb50SMintz, Yuval * 10e8f1cb50SMintz, Yuval * Redistribution and use in source and binary forms, with or 11e8f1cb50SMintz, Yuval * without modification, are permitted provided that the following 12e8f1cb50SMintz, Yuval * conditions are met: 13e8f1cb50SMintz, Yuval * 14e8f1cb50SMintz, Yuval * - Redistributions of source code must retain the above 15e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 16e8f1cb50SMintz, Yuval * disclaimer. 17e8f1cb50SMintz, Yuval * 18e8f1cb50SMintz, Yuval * - Redistributions in binary form must reproduce the above 19e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 20e8f1cb50SMintz, Yuval * disclaimer in the documentation and /or other materials 21e8f1cb50SMintz, Yuval * provided with the distribution. 22e8f1cb50SMintz, Yuval * 23e8f1cb50SMintz, Yuval * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e8f1cb50SMintz, Yuval * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e8f1cb50SMintz, Yuval * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e8f1cb50SMintz, Yuval * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e8f1cb50SMintz, Yuval * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e8f1cb50SMintz, Yuval * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e8f1cb50SMintz, Yuval * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e8f1cb50SMintz, Yuval * SOFTWARE. 311408cc1fSYuval Mintz */ 321408cc1fSYuval Mintz 3336558c3dSYuval Mintz #include <linux/crc32.h> 34eff16960SYuval Mintz #include <linux/etherdevice.h> 351408cc1fSYuval Mintz #include "qed.h" 361408cc1fSYuval Mintz #include "qed_sriov.h" 371408cc1fSYuval Mintz #include "qed_vf.h" 381408cc1fSYuval Mintz 391408cc1fSYuval Mintz static void *qed_vf_pf_prep(struct qed_hwfn *p_hwfn, u16 type, u16 length) 401408cc1fSYuval Mintz { 411408cc1fSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 421408cc1fSYuval Mintz void *p_tlv; 431408cc1fSYuval Mintz 441408cc1fSYuval Mintz /* This lock is released when we receive PF's response 451408cc1fSYuval Mintz * in qed_send_msg2pf(). 461408cc1fSYuval Mintz * So, qed_vf_pf_prep() and qed_send_msg2pf() 471408cc1fSYuval Mintz * must come in sequence. 481408cc1fSYuval Mintz */ 491408cc1fSYuval Mintz mutex_lock(&(p_iov->mutex)); 501408cc1fSYuval Mintz 511408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 521408cc1fSYuval Mintz QED_MSG_IOV, 531408cc1fSYuval Mintz "preparing to send 0x%04x tlv over vf pf channel\n", 541408cc1fSYuval Mintz type); 551408cc1fSYuval Mintz 561408cc1fSYuval Mintz /* Reset Requst offset */ 571408cc1fSYuval Mintz p_iov->offset = (u8 *)p_iov->vf2pf_request; 581408cc1fSYuval Mintz 591408cc1fSYuval Mintz /* Clear mailbox - both request and reply */ 601408cc1fSYuval Mintz memset(p_iov->vf2pf_request, 0, sizeof(union vfpf_tlvs)); 611408cc1fSYuval Mintz memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs)); 621408cc1fSYuval Mintz 631408cc1fSYuval Mintz /* Init type and length */ 641408cc1fSYuval Mintz p_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, type, length); 651408cc1fSYuval Mintz 661408cc1fSYuval Mintz /* Init first tlv header */ 671408cc1fSYuval Mintz ((struct vfpf_first_tlv *)p_tlv)->reply_address = 681408cc1fSYuval Mintz (u64)p_iov->pf2vf_reply_phys; 691408cc1fSYuval Mintz 701408cc1fSYuval Mintz return p_tlv; 711408cc1fSYuval Mintz } 721408cc1fSYuval Mintz 73b0bccb69SYuval Mintz static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status) 74b0bccb69SYuval Mintz { 75b0bccb69SYuval Mintz union pfvf_tlvs *resp = p_hwfn->vf_iov_info->pf2vf_reply; 76b0bccb69SYuval Mintz 77b0bccb69SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 78b0bccb69SYuval Mintz "VF request status = 0x%x, PF reply status = 0x%x\n", 79b0bccb69SYuval Mintz req_status, resp->default_resp.hdr.status); 80b0bccb69SYuval Mintz 81b0bccb69SYuval Mintz mutex_unlock(&(p_hwfn->vf_iov_info->mutex)); 82b0bccb69SYuval Mintz } 83b0bccb69SYuval Mintz 841408cc1fSYuval Mintz static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size) 851408cc1fSYuval Mintz { 861408cc1fSYuval Mintz union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request; 871408cc1fSYuval Mintz struct ustorm_trigger_vf_zone trigger; 881408cc1fSYuval Mintz struct ustorm_vf_zone *zone_data; 891408cc1fSYuval Mintz int rc = 0, time = 100; 901408cc1fSYuval Mintz 911408cc1fSYuval Mintz zone_data = (struct ustorm_vf_zone *)PXP_VF_BAR0_START_USDM_ZONE_B; 921408cc1fSYuval Mintz 931408cc1fSYuval Mintz /* output tlvs list */ 941408cc1fSYuval Mintz qed_dp_tlv_list(p_hwfn, p_req); 951408cc1fSYuval Mintz 961408cc1fSYuval Mintz /* need to add the END TLV to the message size */ 971408cc1fSYuval Mintz resp_size += sizeof(struct channel_list_end_tlv); 981408cc1fSYuval Mintz 991408cc1fSYuval Mintz /* Send TLVs over HW channel */ 1001408cc1fSYuval Mintz memset(&trigger, 0, sizeof(struct ustorm_trigger_vf_zone)); 1011408cc1fSYuval Mintz trigger.vf_pf_msg_valid = 1; 1021408cc1fSYuval Mintz 1031408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 1041408cc1fSYuval Mintz QED_MSG_IOV, 1051408cc1fSYuval Mintz "VF -> PF [%02x] message: [%08x, %08x] --> %p, %08x --> %p\n", 1061408cc1fSYuval Mintz GET_FIELD(p_hwfn->hw_info.concrete_fid, 1071408cc1fSYuval Mintz PXP_CONCRETE_FID_PFID), 1081408cc1fSYuval Mintz upper_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys), 1091408cc1fSYuval Mintz lower_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys), 1101408cc1fSYuval Mintz &zone_data->non_trigger.vf_pf_msg_addr, 1111408cc1fSYuval Mintz *((u32 *)&trigger), &zone_data->trigger); 1121408cc1fSYuval Mintz 1131408cc1fSYuval Mintz REG_WR(p_hwfn, 1141408cc1fSYuval Mintz (uintptr_t)&zone_data->non_trigger.vf_pf_msg_addr.lo, 1151408cc1fSYuval Mintz lower_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys)); 1161408cc1fSYuval Mintz 1171408cc1fSYuval Mintz REG_WR(p_hwfn, 1181408cc1fSYuval Mintz (uintptr_t)&zone_data->non_trigger.vf_pf_msg_addr.hi, 1191408cc1fSYuval Mintz upper_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys)); 1201408cc1fSYuval Mintz 1211408cc1fSYuval Mintz /* The message data must be written first, to prevent trigger before 1221408cc1fSYuval Mintz * data is written. 1231408cc1fSYuval Mintz */ 1241408cc1fSYuval Mintz wmb(); 1251408cc1fSYuval Mintz 1261408cc1fSYuval Mintz REG_WR(p_hwfn, (uintptr_t)&zone_data->trigger, *((u32 *)&trigger)); 1271408cc1fSYuval Mintz 1281408cc1fSYuval Mintz /* When PF would be done with the response, it would write back to the 1291408cc1fSYuval Mintz * `done' address. Poll until then. 1301408cc1fSYuval Mintz */ 1311408cc1fSYuval Mintz while ((!*done) && time) { 1321408cc1fSYuval Mintz msleep(25); 1331408cc1fSYuval Mintz time--; 1341408cc1fSYuval Mintz } 1351408cc1fSYuval Mintz 1361408cc1fSYuval Mintz if (!*done) { 13781e64ef6SMintz, Yuval DP_NOTICE(p_hwfn, 1381408cc1fSYuval Mintz "VF <-- PF Timeout [Type %d]\n", 1391408cc1fSYuval Mintz p_req->first_tlv.tl.type); 1401408cc1fSYuval Mintz rc = -EBUSY; 1411408cc1fSYuval Mintz } else { 14281e64ef6SMintz, Yuval if ((*done != PFVF_STATUS_SUCCESS) && 14381e64ef6SMintz, Yuval (*done != PFVF_STATUS_NO_RESOURCE)) 14481e64ef6SMintz, Yuval DP_NOTICE(p_hwfn, 14581e64ef6SMintz, Yuval "PF response: %d [Type %d]\n", 14681e64ef6SMintz, Yuval *done, p_req->first_tlv.tl.type); 14781e64ef6SMintz, Yuval else 1481408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 1491408cc1fSYuval Mintz "PF response: %d [Type %d]\n", 1501408cc1fSYuval Mintz *done, p_req->first_tlv.tl.type); 1511408cc1fSYuval Mintz } 1521408cc1fSYuval Mintz 1531408cc1fSYuval Mintz return rc; 1541408cc1fSYuval Mintz } 1551408cc1fSYuval Mintz 1561408cc1fSYuval Mintz #define VF_ACQUIRE_THRESH 3 1571cf2b1a9SYuval Mintz static void qed_vf_pf_acquire_reduce_resc(struct qed_hwfn *p_hwfn, 1581cf2b1a9SYuval Mintz struct vf_pf_resc_request *p_req, 1591cf2b1a9SYuval Mintz struct pf_vf_resc *p_resp) 1601cf2b1a9SYuval Mintz { 1611cf2b1a9SYuval Mintz DP_VERBOSE(p_hwfn, 1621cf2b1a9SYuval Mintz QED_MSG_IOV, 1631cf2b1a9SYuval 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", 1641cf2b1a9SYuval Mintz p_req->num_rxqs, 1651cf2b1a9SYuval Mintz p_resp->num_rxqs, 1661cf2b1a9SYuval Mintz p_req->num_rxqs, 1671cf2b1a9SYuval Mintz p_resp->num_txqs, 1681cf2b1a9SYuval Mintz p_req->num_sbs, 1691cf2b1a9SYuval Mintz p_resp->num_sbs, 1701cf2b1a9SYuval Mintz p_req->num_mac_filters, 1711cf2b1a9SYuval Mintz p_resp->num_mac_filters, 1721cf2b1a9SYuval Mintz p_req->num_vlan_filters, 1731cf2b1a9SYuval Mintz p_resp->num_vlan_filters, 1741cf2b1a9SYuval Mintz p_req->num_mc_filters, p_resp->num_mc_filters); 1751cf2b1a9SYuval Mintz 1761cf2b1a9SYuval Mintz /* humble our request */ 1771cf2b1a9SYuval Mintz p_req->num_txqs = p_resp->num_txqs; 1781cf2b1a9SYuval Mintz p_req->num_rxqs = p_resp->num_rxqs; 1791cf2b1a9SYuval Mintz p_req->num_sbs = p_resp->num_sbs; 1801cf2b1a9SYuval Mintz p_req->num_mac_filters = p_resp->num_mac_filters; 1811cf2b1a9SYuval Mintz p_req->num_vlan_filters = p_resp->num_vlan_filters; 1821cf2b1a9SYuval Mintz p_req->num_mc_filters = p_resp->num_mc_filters; 1831cf2b1a9SYuval Mintz } 1841408cc1fSYuval Mintz 1851408cc1fSYuval Mintz static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn) 1861408cc1fSYuval Mintz { 1871408cc1fSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 1881408cc1fSYuval Mintz struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp; 1891408cc1fSYuval Mintz struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info; 1901cf2b1a9SYuval Mintz struct vf_pf_resc_request *p_resc; 1911408cc1fSYuval Mintz bool resources_acquired = false; 1921408cc1fSYuval Mintz struct vfpf_acquire_tlv *req; 1931408cc1fSYuval Mintz int rc = 0, attempts = 0; 1941408cc1fSYuval Mintz 1951408cc1fSYuval Mintz /* clear mailbox and prep first tlv */ 1961408cc1fSYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_ACQUIRE, sizeof(*req)); 1971cf2b1a9SYuval Mintz p_resc = &req->resc_request; 1981408cc1fSYuval Mintz 1991408cc1fSYuval Mintz /* starting filling the request */ 2001408cc1fSYuval Mintz req->vfdev_info.opaque_fid = p_hwfn->hw_info.opaque_fid; 2011408cc1fSYuval Mintz 2021cf2b1a9SYuval Mintz p_resc->num_rxqs = QED_MAX_VF_CHAINS_PER_PF; 2031cf2b1a9SYuval Mintz p_resc->num_txqs = QED_MAX_VF_CHAINS_PER_PF; 2041cf2b1a9SYuval Mintz p_resc->num_sbs = QED_MAX_VF_CHAINS_PER_PF; 2051cf2b1a9SYuval Mintz p_resc->num_mac_filters = QED_ETH_VF_NUM_MAC_FILTERS; 2061cf2b1a9SYuval Mintz p_resc->num_vlan_filters = QED_ETH_VF_NUM_VLAN_FILTERS; 2071408cc1fSYuval Mintz 2081408cc1fSYuval Mintz req->vfdev_info.os_type = VFPF_ACQUIRE_OS_LINUX; 2091408cc1fSYuval Mintz req->vfdev_info.fw_major = FW_MAJOR_VERSION; 2101408cc1fSYuval Mintz req->vfdev_info.fw_minor = FW_MINOR_VERSION; 2111408cc1fSYuval Mintz req->vfdev_info.fw_revision = FW_REVISION_VERSION; 2121408cc1fSYuval Mintz req->vfdev_info.fw_engineering = FW_ENGINEERING_VERSION; 2131fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_major = ETH_HSI_VER_MAJOR; 2141fe614d1SYuval Mintz req->vfdev_info.eth_fp_hsi_minor = ETH_HSI_VER_MINOR; 2151408cc1fSYuval Mintz 2161408cc1fSYuval Mintz /* Fill capability field with any non-deprecated config we support */ 2171408cc1fSYuval Mintz req->vfdev_info.capabilities |= VFPF_ACQUIRE_CAP_100G; 2181408cc1fSYuval Mintz 2191408cc1fSYuval Mintz /* pf 2 vf bulletin board address */ 2201408cc1fSYuval Mintz req->bulletin_addr = p_iov->bulletin.phys; 2211408cc1fSYuval Mintz req->bulletin_size = p_iov->bulletin.size; 2221408cc1fSYuval Mintz 2231408cc1fSYuval Mintz /* add list termination tlv */ 2241408cc1fSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 2251408cc1fSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 2261408cc1fSYuval Mintz 2271408cc1fSYuval Mintz while (!resources_acquired) { 2281408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 2291408cc1fSYuval Mintz QED_MSG_IOV, "attempting to acquire resources\n"); 2301408cc1fSYuval Mintz 231d8c2c7e3SYuval Mintz /* Clear response buffer, as this might be a re-send */ 232d8c2c7e3SYuval Mintz memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs)); 233d8c2c7e3SYuval Mintz 2341408cc1fSYuval Mintz /* send acquire request */ 2351408cc1fSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 2361408cc1fSYuval Mintz if (rc) 23766117a9dSDan Carpenter goto exit; 2381408cc1fSYuval Mintz 2391408cc1fSYuval Mintz /* copy acquire response from buffer to p_hwfn */ 2401408cc1fSYuval Mintz memcpy(&p_iov->acquire_resp, resp, sizeof(p_iov->acquire_resp)); 2411408cc1fSYuval Mintz 2421408cc1fSYuval Mintz attempts++; 2431408cc1fSYuval Mintz 2441408cc1fSYuval Mintz if (resp->hdr.status == PFVF_STATUS_SUCCESS) { 2451408cc1fSYuval Mintz /* PF agrees to allocate our resources */ 2461408cc1fSYuval Mintz if (!(resp->pfdev_info.capabilities & 2471408cc1fSYuval Mintz PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) { 248d8c2c7e3SYuval Mintz /* It's possible legacy PF mistakenly accepted; 249d8c2c7e3SYuval Mintz * but we don't care - simply mark it as 250d8c2c7e3SYuval Mintz * legacy and continue. 251d8c2c7e3SYuval Mintz */ 252d8c2c7e3SYuval Mintz req->vfdev_info.capabilities |= 253d8c2c7e3SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI; 2541408cc1fSYuval Mintz } 2551408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n"); 2561408cc1fSYuval Mintz resources_acquired = true; 2571408cc1fSYuval Mintz } else if (resp->hdr.status == PFVF_STATUS_NO_RESOURCE && 2581408cc1fSYuval Mintz attempts < VF_ACQUIRE_THRESH) { 2591cf2b1a9SYuval Mintz qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc, 2601cf2b1a9SYuval Mintz &resp->resc); 261d8c2c7e3SYuval Mintz } else if (resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) { 262d8c2c7e3SYuval Mintz if (pfdev_info->major_fp_hsi && 2631fe614d1SYuval Mintz (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) { 2641fe614d1SYuval Mintz DP_NOTICE(p_hwfn, 2651fe614d1SYuval Mintz "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n", 2661fe614d1SYuval Mintz pfdev_info->major_fp_hsi, 2671fe614d1SYuval Mintz pfdev_info->minor_fp_hsi, 2681fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, 269d8c2c7e3SYuval Mintz ETH_HSI_VER_MINOR, 270d8c2c7e3SYuval Mintz pfdev_info->major_fp_hsi); 271d8c2c7e3SYuval Mintz rc = -EINVAL; 272d8c2c7e3SYuval Mintz goto exit; 273d8c2c7e3SYuval Mintz } 274d8c2c7e3SYuval Mintz 275d8c2c7e3SYuval Mintz if (!pfdev_info->major_fp_hsi) { 276d8c2c7e3SYuval Mintz if (req->vfdev_info.capabilities & 277d8c2c7e3SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI) { 278d8c2c7e3SYuval Mintz DP_NOTICE(p_hwfn, 279d8c2c7e3SYuval Mintz "PF uses very old drivers. Please change to a VF driver using no later than 8.8.x.x.\n"); 280d8c2c7e3SYuval Mintz rc = -EINVAL; 281d8c2c7e3SYuval Mintz goto exit; 282d8c2c7e3SYuval Mintz } else { 283d8c2c7e3SYuval Mintz DP_INFO(p_hwfn, 284d8c2c7e3SYuval Mintz "PF is old - try re-acquire to see if it supports FW-version override\n"); 285d8c2c7e3SYuval Mintz req->vfdev_info.capabilities |= 286d8c2c7e3SYuval Mintz VFPF_ACQUIRE_CAP_PRE_FP_HSI; 287d8c2c7e3SYuval Mintz continue; 288d8c2c7e3SYuval Mintz } 289d8c2c7e3SYuval Mintz } 290d8c2c7e3SYuval Mintz 291d8c2c7e3SYuval Mintz /* If PF/VF are using same Major, PF must have had 292d8c2c7e3SYuval Mintz * it's reasons. Simply fail. 293d8c2c7e3SYuval Mintz */ 294d8c2c7e3SYuval Mintz DP_NOTICE(p_hwfn, "PF rejected acquisition by VF\n"); 295d8c2c7e3SYuval Mintz rc = -EINVAL; 296d8c2c7e3SYuval Mintz goto exit; 2971408cc1fSYuval Mintz } else { 2981408cc1fSYuval Mintz DP_ERR(p_hwfn, 2991408cc1fSYuval Mintz "PF returned error %d to VF acquisition request\n", 3001408cc1fSYuval Mintz resp->hdr.status); 301d8c2c7e3SYuval Mintz rc = -EAGAIN; 302d8c2c7e3SYuval Mintz goto exit; 3031408cc1fSYuval Mintz } 3041408cc1fSYuval Mintz } 3051408cc1fSYuval Mintz 306d8c2c7e3SYuval Mintz /* Mark the PF as legacy, if needed */ 307d8c2c7e3SYuval Mintz if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_PRE_FP_HSI) 308d8c2c7e3SYuval Mintz p_iov->b_pre_fp_hsi = true; 309d8c2c7e3SYuval Mintz 3101408cc1fSYuval Mintz /* Update bulletin board size with response from PF */ 3111408cc1fSYuval Mintz p_iov->bulletin.size = resp->bulletin_size; 3121408cc1fSYuval Mintz 3131408cc1fSYuval Mintz /* get HW info */ 3141408cc1fSYuval Mintz p_hwfn->cdev->type = resp->pfdev_info.dev_type; 3151408cc1fSYuval Mintz p_hwfn->cdev->chip_rev = resp->pfdev_info.chip_rev; 3161408cc1fSYuval Mintz 3171408cc1fSYuval Mintz p_hwfn->cdev->chip_num = pfdev_info->chip_num & 0xffff; 3181408cc1fSYuval Mintz 3191408cc1fSYuval Mintz /* Learn of the possibility of CMT */ 3201408cc1fSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) { 3211408cc1fSYuval Mintz if (resp->pfdev_info.capabilities & PFVF_ACQUIRE_CAP_100G) { 3221408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "100g VF\n"); 3231408cc1fSYuval Mintz p_hwfn->cdev->num_hwfns = 2; 3241408cc1fSYuval Mintz } 3251408cc1fSYuval Mintz } 3261408cc1fSYuval Mintz 327d8c2c7e3SYuval Mintz if (!p_iov->b_pre_fp_hsi && 328d8c2c7e3SYuval Mintz ETH_HSI_VER_MINOR && 3291fe614d1SYuval Mintz (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) { 3301fe614d1SYuval Mintz DP_INFO(p_hwfn, 3311fe614d1SYuval Mintz "PF is using older fastpath HSI; %02x.%02x is configured\n", 3321fe614d1SYuval Mintz ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi); 3331fe614d1SYuval Mintz } 3341fe614d1SYuval Mintz 335d8c2c7e3SYuval Mintz exit: 336b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 337b0bccb69SYuval Mintz 338d8c2c7e3SYuval Mintz return rc; 3391408cc1fSYuval Mintz } 3401408cc1fSYuval Mintz 3411408cc1fSYuval Mintz int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn) 3421408cc1fSYuval Mintz { 3431408cc1fSYuval Mintz struct qed_vf_iov *p_iov; 3441408cc1fSYuval Mintz u32 reg; 3451408cc1fSYuval Mintz 3461408cc1fSYuval Mintz /* Set number of hwfns - might be overriden once leading hwfn learns 3471408cc1fSYuval Mintz * actual configuration from PF. 3481408cc1fSYuval Mintz */ 3491408cc1fSYuval Mintz if (IS_LEAD_HWFN(p_hwfn)) 3501408cc1fSYuval Mintz p_hwfn->cdev->num_hwfns = 1; 3511408cc1fSYuval Mintz 3521408cc1fSYuval Mintz /* Set the doorbell bar. Assumption: regview is set */ 3531408cc1fSYuval Mintz p_hwfn->doorbells = (u8 __iomem *)p_hwfn->regview + 3541408cc1fSYuval Mintz PXP_VF_BAR0_START_DQ; 3551408cc1fSYuval Mintz 3561408cc1fSYuval Mintz reg = PXP_VF_BAR0_ME_OPAQUE_ADDRESS; 3571408cc1fSYuval Mintz p_hwfn->hw_info.opaque_fid = (u16)REG_RD(p_hwfn, reg); 3581408cc1fSYuval Mintz 3591408cc1fSYuval Mintz reg = PXP_VF_BAR0_ME_CONCRETE_ADDRESS; 3601408cc1fSYuval Mintz p_hwfn->hw_info.concrete_fid = REG_RD(p_hwfn, reg); 3611408cc1fSYuval Mintz 3621408cc1fSYuval Mintz /* Allocate vf sriov info */ 3631408cc1fSYuval Mintz p_iov = kzalloc(sizeof(*p_iov), GFP_KERNEL); 3642591c280SJoe Perches if (!p_iov) 3651408cc1fSYuval Mintz return -ENOMEM; 3661408cc1fSYuval Mintz 3671408cc1fSYuval Mintz /* Allocate vf2pf msg */ 3681408cc1fSYuval Mintz p_iov->vf2pf_request = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3691408cc1fSYuval Mintz sizeof(union vfpf_tlvs), 3701408cc1fSYuval Mintz &p_iov->vf2pf_request_phys, 3711408cc1fSYuval Mintz GFP_KERNEL); 3722591c280SJoe Perches if (!p_iov->vf2pf_request) 3731408cc1fSYuval Mintz goto free_p_iov; 3741408cc1fSYuval Mintz 3751408cc1fSYuval Mintz p_iov->pf2vf_reply = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3761408cc1fSYuval Mintz sizeof(union pfvf_tlvs), 3771408cc1fSYuval Mintz &p_iov->pf2vf_reply_phys, 3781408cc1fSYuval Mintz GFP_KERNEL); 3792591c280SJoe Perches if (!p_iov->pf2vf_reply) 3801408cc1fSYuval Mintz goto free_vf2pf_request; 3811408cc1fSYuval Mintz 3821408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, 3831408cc1fSYuval Mintz QED_MSG_IOV, 3841408cc1fSYuval Mintz "VF's Request mailbox [%p virt 0x%llx phys], Response mailbox [%p virt 0x%llx phys]\n", 3851408cc1fSYuval Mintz p_iov->vf2pf_request, 3861408cc1fSYuval Mintz (u64) p_iov->vf2pf_request_phys, 3871408cc1fSYuval Mintz p_iov->pf2vf_reply, (u64)p_iov->pf2vf_reply_phys); 3881408cc1fSYuval Mintz 3891408cc1fSYuval Mintz /* Allocate Bulletin board */ 3901408cc1fSYuval Mintz p_iov->bulletin.size = sizeof(struct qed_bulletin_content); 3911408cc1fSYuval Mintz p_iov->bulletin.p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3921408cc1fSYuval Mintz p_iov->bulletin.size, 3931408cc1fSYuval Mintz &p_iov->bulletin.phys, 3941408cc1fSYuval Mintz GFP_KERNEL); 3951408cc1fSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 3961408cc1fSYuval Mintz "VF's bulletin Board [%p virt 0x%llx phys 0x%08x bytes]\n", 3971408cc1fSYuval Mintz p_iov->bulletin.p_virt, 3981408cc1fSYuval Mintz (u64)p_iov->bulletin.phys, p_iov->bulletin.size); 3991408cc1fSYuval Mintz 4001408cc1fSYuval Mintz mutex_init(&p_iov->mutex); 4011408cc1fSYuval Mintz 4021408cc1fSYuval Mintz p_hwfn->vf_iov_info = p_iov; 4031408cc1fSYuval Mintz 4041408cc1fSYuval Mintz p_hwfn->hw_info.personality = QED_PCI_ETH; 4051408cc1fSYuval Mintz 4061408cc1fSYuval Mintz return qed_vf_pf_acquire(p_hwfn); 4071408cc1fSYuval Mintz 4081408cc1fSYuval Mintz free_vf2pf_request: 4091408cc1fSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4101408cc1fSYuval Mintz sizeof(union vfpf_tlvs), 4111408cc1fSYuval Mintz p_iov->vf2pf_request, p_iov->vf2pf_request_phys); 4121408cc1fSYuval Mintz free_p_iov: 4131408cc1fSYuval Mintz kfree(p_iov); 4141408cc1fSYuval Mintz 4151408cc1fSYuval Mintz return -ENOMEM; 4161408cc1fSYuval Mintz } 417d8c2c7e3SYuval Mintz #define TSTORM_QZONE_START PXP_VF_BAR0_START_SDM_ZONE_A 418d8c2c7e3SYuval Mintz #define MSTORM_QZONE_START(dev) (TSTORM_QZONE_START + \ 419d8c2c7e3SYuval Mintz (TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev))) 4201408cc1fSYuval Mintz 421eaf3c0c6SChopra, Manish static void 422eaf3c0c6SChopra, Manish __qed_vf_prep_tunn_req_tlv(struct vfpf_update_tunn_param_tlv *p_req, 423eaf3c0c6SChopra, Manish struct qed_tunn_update_type *p_src, 424eaf3c0c6SChopra, Manish enum qed_tunn_clss mask, u8 *p_cls) 425eaf3c0c6SChopra, Manish { 426eaf3c0c6SChopra, Manish if (p_src->b_update_mode) { 427eaf3c0c6SChopra, Manish p_req->tun_mode_update_mask |= BIT(mask); 428eaf3c0c6SChopra, Manish 429eaf3c0c6SChopra, Manish if (p_src->b_mode_enabled) 430eaf3c0c6SChopra, Manish p_req->tunn_mode |= BIT(mask); 431eaf3c0c6SChopra, Manish } 432eaf3c0c6SChopra, Manish 433eaf3c0c6SChopra, Manish *p_cls = p_src->tun_cls; 434eaf3c0c6SChopra, Manish } 435eaf3c0c6SChopra, Manish 436eaf3c0c6SChopra, Manish static void 437eaf3c0c6SChopra, Manish qed_vf_prep_tunn_req_tlv(struct vfpf_update_tunn_param_tlv *p_req, 438eaf3c0c6SChopra, Manish struct qed_tunn_update_type *p_src, 439eaf3c0c6SChopra, Manish enum qed_tunn_clss mask, 440eaf3c0c6SChopra, Manish u8 *p_cls, struct qed_tunn_update_udp_port *p_port, 441eaf3c0c6SChopra, Manish u8 *p_update_port, u16 *p_udp_port) 442eaf3c0c6SChopra, Manish { 443eaf3c0c6SChopra, Manish if (p_port->b_update_port) { 444eaf3c0c6SChopra, Manish *p_update_port = 1; 445eaf3c0c6SChopra, Manish *p_udp_port = p_port->port; 446eaf3c0c6SChopra, Manish } 447eaf3c0c6SChopra, Manish 448eaf3c0c6SChopra, Manish __qed_vf_prep_tunn_req_tlv(p_req, p_src, mask, p_cls); 449eaf3c0c6SChopra, Manish } 450eaf3c0c6SChopra, Manish 451eaf3c0c6SChopra, Manish void qed_vf_set_vf_start_tunn_update_param(struct qed_tunnel_info *p_tun) 452eaf3c0c6SChopra, Manish { 453eaf3c0c6SChopra, Manish if (p_tun->vxlan.b_mode_enabled) 454eaf3c0c6SChopra, Manish p_tun->vxlan.b_update_mode = true; 455eaf3c0c6SChopra, Manish if (p_tun->l2_geneve.b_mode_enabled) 456eaf3c0c6SChopra, Manish p_tun->l2_geneve.b_update_mode = true; 457eaf3c0c6SChopra, Manish if (p_tun->ip_geneve.b_mode_enabled) 458eaf3c0c6SChopra, Manish p_tun->ip_geneve.b_update_mode = true; 459eaf3c0c6SChopra, Manish if (p_tun->l2_gre.b_mode_enabled) 460eaf3c0c6SChopra, Manish p_tun->l2_gre.b_update_mode = true; 461eaf3c0c6SChopra, Manish if (p_tun->ip_gre.b_mode_enabled) 462eaf3c0c6SChopra, Manish p_tun->ip_gre.b_update_mode = true; 463eaf3c0c6SChopra, Manish 464eaf3c0c6SChopra, Manish p_tun->b_update_rx_cls = true; 465eaf3c0c6SChopra, Manish p_tun->b_update_tx_cls = true; 466eaf3c0c6SChopra, Manish } 467eaf3c0c6SChopra, Manish 468eaf3c0c6SChopra, Manish static void 469eaf3c0c6SChopra, Manish __qed_vf_update_tunn_param(struct qed_tunn_update_type *p_tun, 470eaf3c0c6SChopra, Manish u16 feature_mask, u8 tunn_mode, 471eaf3c0c6SChopra, Manish u8 tunn_cls, enum qed_tunn_mode val) 472eaf3c0c6SChopra, Manish { 473eaf3c0c6SChopra, Manish if (feature_mask & BIT(val)) { 474eaf3c0c6SChopra, Manish p_tun->b_mode_enabled = tunn_mode; 475eaf3c0c6SChopra, Manish p_tun->tun_cls = tunn_cls; 476eaf3c0c6SChopra, Manish } else { 477eaf3c0c6SChopra, Manish p_tun->b_mode_enabled = false; 478eaf3c0c6SChopra, Manish } 479eaf3c0c6SChopra, Manish } 480eaf3c0c6SChopra, Manish 481eaf3c0c6SChopra, Manish static void qed_vf_update_tunn_param(struct qed_hwfn *p_hwfn, 482eaf3c0c6SChopra, Manish struct qed_tunnel_info *p_tun, 483eaf3c0c6SChopra, Manish struct pfvf_update_tunn_param_tlv *p_resp) 484eaf3c0c6SChopra, Manish { 485eaf3c0c6SChopra, Manish /* Update mode and classes provided by PF */ 486eaf3c0c6SChopra, Manish u16 feat_mask = p_resp->tunn_feature_mask; 487eaf3c0c6SChopra, Manish 488eaf3c0c6SChopra, Manish __qed_vf_update_tunn_param(&p_tun->vxlan, feat_mask, 489eaf3c0c6SChopra, Manish p_resp->vxlan_mode, p_resp->vxlan_clss, 490eaf3c0c6SChopra, Manish QED_MODE_VXLAN_TUNN); 491eaf3c0c6SChopra, Manish __qed_vf_update_tunn_param(&p_tun->l2_geneve, feat_mask, 492eaf3c0c6SChopra, Manish p_resp->l2geneve_mode, 493eaf3c0c6SChopra, Manish p_resp->l2geneve_clss, 494eaf3c0c6SChopra, Manish QED_MODE_L2GENEVE_TUNN); 495eaf3c0c6SChopra, Manish __qed_vf_update_tunn_param(&p_tun->ip_geneve, feat_mask, 496eaf3c0c6SChopra, Manish p_resp->ipgeneve_mode, 497eaf3c0c6SChopra, Manish p_resp->ipgeneve_clss, 498eaf3c0c6SChopra, Manish QED_MODE_IPGENEVE_TUNN); 499eaf3c0c6SChopra, Manish __qed_vf_update_tunn_param(&p_tun->l2_gre, feat_mask, 500eaf3c0c6SChopra, Manish p_resp->l2gre_mode, p_resp->l2gre_clss, 501eaf3c0c6SChopra, Manish QED_MODE_L2GRE_TUNN); 502eaf3c0c6SChopra, Manish __qed_vf_update_tunn_param(&p_tun->ip_gre, feat_mask, 503eaf3c0c6SChopra, Manish p_resp->ipgre_mode, p_resp->ipgre_clss, 504eaf3c0c6SChopra, Manish QED_MODE_IPGRE_TUNN); 505eaf3c0c6SChopra, Manish p_tun->geneve_port.port = p_resp->geneve_udp_port; 506eaf3c0c6SChopra, Manish p_tun->vxlan_port.port = p_resp->vxlan_udp_port; 507eaf3c0c6SChopra, Manish 508eaf3c0c6SChopra, Manish DP_VERBOSE(p_hwfn, QED_MSG_IOV, 509eaf3c0c6SChopra, Manish "tunn mode: vxlan=0x%x, l2geneve=0x%x, ipgeneve=0x%x, l2gre=0x%x, ipgre=0x%x", 510eaf3c0c6SChopra, Manish p_tun->vxlan.b_mode_enabled, p_tun->l2_geneve.b_mode_enabled, 511eaf3c0c6SChopra, Manish p_tun->ip_geneve.b_mode_enabled, 512eaf3c0c6SChopra, Manish p_tun->l2_gre.b_mode_enabled, p_tun->ip_gre.b_mode_enabled); 513eaf3c0c6SChopra, Manish } 514eaf3c0c6SChopra, Manish 515eaf3c0c6SChopra, Manish int qed_vf_pf_tunnel_param_update(struct qed_hwfn *p_hwfn, 516eaf3c0c6SChopra, Manish struct qed_tunnel_info *p_src) 517eaf3c0c6SChopra, Manish { 518eaf3c0c6SChopra, Manish struct qed_tunnel_info *p_tun = &p_hwfn->cdev->tunnel; 519eaf3c0c6SChopra, Manish struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 520eaf3c0c6SChopra, Manish struct pfvf_update_tunn_param_tlv *p_resp; 521eaf3c0c6SChopra, Manish struct vfpf_update_tunn_param_tlv *p_req; 522eaf3c0c6SChopra, Manish int rc; 523eaf3c0c6SChopra, Manish 524eaf3c0c6SChopra, Manish p_req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_UPDATE_TUNN_PARAM, 525eaf3c0c6SChopra, Manish sizeof(*p_req)); 526eaf3c0c6SChopra, Manish 527eaf3c0c6SChopra, Manish if (p_src->b_update_rx_cls && p_src->b_update_tx_cls) 528eaf3c0c6SChopra, Manish p_req->update_tun_cls = 1; 529eaf3c0c6SChopra, Manish 530eaf3c0c6SChopra, Manish qed_vf_prep_tunn_req_tlv(p_req, &p_src->vxlan, QED_MODE_VXLAN_TUNN, 531eaf3c0c6SChopra, Manish &p_req->vxlan_clss, &p_src->vxlan_port, 532eaf3c0c6SChopra, Manish &p_req->update_vxlan_port, 533eaf3c0c6SChopra, Manish &p_req->vxlan_port); 534eaf3c0c6SChopra, Manish qed_vf_prep_tunn_req_tlv(p_req, &p_src->l2_geneve, 535eaf3c0c6SChopra, Manish QED_MODE_L2GENEVE_TUNN, 536eaf3c0c6SChopra, Manish &p_req->l2geneve_clss, &p_src->geneve_port, 537eaf3c0c6SChopra, Manish &p_req->update_geneve_port, 538eaf3c0c6SChopra, Manish &p_req->geneve_port); 539eaf3c0c6SChopra, Manish __qed_vf_prep_tunn_req_tlv(p_req, &p_src->ip_geneve, 540eaf3c0c6SChopra, Manish QED_MODE_IPGENEVE_TUNN, 541eaf3c0c6SChopra, Manish &p_req->ipgeneve_clss); 542eaf3c0c6SChopra, Manish __qed_vf_prep_tunn_req_tlv(p_req, &p_src->l2_gre, 543eaf3c0c6SChopra, Manish QED_MODE_L2GRE_TUNN, &p_req->l2gre_clss); 544eaf3c0c6SChopra, Manish __qed_vf_prep_tunn_req_tlv(p_req, &p_src->ip_gre, 545eaf3c0c6SChopra, Manish QED_MODE_IPGRE_TUNN, &p_req->ipgre_clss); 546eaf3c0c6SChopra, Manish 547eaf3c0c6SChopra, Manish /* add list termination tlv */ 548eaf3c0c6SChopra, Manish qed_add_tlv(p_hwfn, &p_iov->offset, 549eaf3c0c6SChopra, Manish CHANNEL_TLV_LIST_END, 550eaf3c0c6SChopra, Manish sizeof(struct channel_list_end_tlv)); 551eaf3c0c6SChopra, Manish 552eaf3c0c6SChopra, Manish p_resp = &p_iov->pf2vf_reply->tunn_param_resp; 553eaf3c0c6SChopra, Manish rc = qed_send_msg2pf(p_hwfn, &p_resp->hdr.status, sizeof(*p_resp)); 554eaf3c0c6SChopra, Manish 555eaf3c0c6SChopra, Manish if (rc) 556eaf3c0c6SChopra, Manish goto exit; 557eaf3c0c6SChopra, Manish 558eaf3c0c6SChopra, Manish if (p_resp->hdr.status != PFVF_STATUS_SUCCESS) { 559eaf3c0c6SChopra, Manish DP_VERBOSE(p_hwfn, QED_MSG_IOV, 560eaf3c0c6SChopra, Manish "Failed to update tunnel parameters\n"); 561eaf3c0c6SChopra, Manish rc = -EINVAL; 562eaf3c0c6SChopra, Manish } 563eaf3c0c6SChopra, Manish 564eaf3c0c6SChopra, Manish qed_vf_update_tunn_param(p_hwfn, p_tun, p_resp); 565eaf3c0c6SChopra, Manish exit: 566eaf3c0c6SChopra, Manish qed_vf_pf_req_end(p_hwfn, rc); 567eaf3c0c6SChopra, Manish return rc; 568eaf3c0c6SChopra, Manish } 569eaf3c0c6SChopra, Manish 5703da7a37aSMintz, Yuval int 5713da7a37aSMintz, Yuval qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn, 5723da7a37aSMintz, Yuval struct qed_queue_cid *p_cid, 573dacd88d6SYuval Mintz u16 bd_max_bytes, 574dacd88d6SYuval Mintz dma_addr_t bd_chain_phys_addr, 575dacd88d6SYuval Mintz dma_addr_t cqe_pbl_addr, 576dacd88d6SYuval Mintz u16 cqe_pbl_size, void __iomem **pp_prod) 577dacd88d6SYuval Mintz { 578dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 579dacd88d6SYuval Mintz struct pfvf_start_queue_resp_tlv *resp; 580dacd88d6SYuval Mintz struct vfpf_start_rxq_tlv *req; 5813da7a37aSMintz, Yuval u8 rx_qid = p_cid->rel.queue_id; 582dacd88d6SYuval Mintz int rc; 583dacd88d6SYuval Mintz 584dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 585dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_RXQ, sizeof(*req)); 586dacd88d6SYuval Mintz 587dacd88d6SYuval Mintz req->rx_qid = rx_qid; 588dacd88d6SYuval Mintz req->cqe_pbl_addr = cqe_pbl_addr; 589dacd88d6SYuval Mintz req->cqe_pbl_size = cqe_pbl_size; 590dacd88d6SYuval Mintz req->rxq_addr = bd_chain_phys_addr; 5913da7a37aSMintz, Yuval req->hw_sb = p_cid->rel.sb; 5923da7a37aSMintz, Yuval req->sb_index = p_cid->rel.sb_idx; 593dacd88d6SYuval Mintz req->bd_max_bytes = bd_max_bytes; 594dacd88d6SYuval Mintz req->stat_id = -1; 595dacd88d6SYuval Mintz 596d8c2c7e3SYuval Mintz /* If PF is legacy, we'll need to calculate producers ourselves 597d8c2c7e3SYuval Mintz * as well as clean them. 598d8c2c7e3SYuval Mintz */ 5993da7a37aSMintz, Yuval if (p_iov->b_pre_fp_hsi) { 600d8c2c7e3SYuval Mintz u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid]; 601d8c2c7e3SYuval Mintz u32 init_prod_val = 0; 602d8c2c7e3SYuval Mintz 6033da7a37aSMintz, Yuval *pp_prod = (u8 __iomem *) 6043da7a37aSMintz, Yuval p_hwfn->regview + 605d8c2c7e3SYuval Mintz MSTORM_QZONE_START(p_hwfn->cdev) + 606d8c2c7e3SYuval Mintz hw_qid * MSTORM_QZONE_SIZE; 607d8c2c7e3SYuval Mintz 608d8c2c7e3SYuval Mintz /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */ 609d8c2c7e3SYuval Mintz __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32), 610d8c2c7e3SYuval Mintz (u32 *)(&init_prod_val)); 611d8c2c7e3SYuval Mintz } 612dacd88d6SYuval Mintz /* add list termination tlv */ 613dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 614dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 615dacd88d6SYuval Mintz 616dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->queue_start; 617dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 618dacd88d6SYuval Mintz if (rc) 619b0bccb69SYuval Mintz goto exit; 620dacd88d6SYuval Mintz 621b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 622b0bccb69SYuval Mintz rc = -EINVAL; 623b0bccb69SYuval Mintz goto exit; 624b0bccb69SYuval Mintz } 625dacd88d6SYuval Mintz 626dacd88d6SYuval Mintz /* Learn the address of the producer from the response */ 6273da7a37aSMintz, Yuval if (!p_iov->b_pre_fp_hsi) { 628b21290b7SYuval Mintz u32 init_prod_val = 0; 629dacd88d6SYuval Mintz 630dacd88d6SYuval Mintz *pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset; 631dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 632dacd88d6SYuval Mintz "Rxq[0x%02x]: producer at %p [offset 0x%08x]\n", 633dacd88d6SYuval Mintz rx_qid, *pp_prod, resp->offset); 634dacd88d6SYuval Mintz 635dacd88d6SYuval Mintz /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */ 636b21290b7SYuval Mintz __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32), 637dacd88d6SYuval Mintz (u32 *)&init_prod_val); 638dacd88d6SYuval Mintz } 639b0bccb69SYuval Mintz exit: 640b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 641dacd88d6SYuval Mintz 642dacd88d6SYuval Mintz return rc; 643dacd88d6SYuval Mintz } 644dacd88d6SYuval Mintz 6453da7a37aSMintz, Yuval int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, 6463da7a37aSMintz, Yuval struct qed_queue_cid *p_cid, bool cqe_completion) 647dacd88d6SYuval Mintz { 648dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 649dacd88d6SYuval Mintz struct vfpf_stop_rxqs_tlv *req; 650dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 651dacd88d6SYuval Mintz int rc; 652dacd88d6SYuval Mintz 653dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 654dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_RXQS, sizeof(*req)); 655dacd88d6SYuval Mintz 6563da7a37aSMintz, Yuval req->rx_qid = p_cid->rel.queue_id; 657dacd88d6SYuval Mintz req->num_rxqs = 1; 658dacd88d6SYuval Mintz req->cqe_completion = cqe_completion; 659dacd88d6SYuval Mintz 660dacd88d6SYuval Mintz /* add list termination tlv */ 661dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 662dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 663dacd88d6SYuval Mintz 664dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 665dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 666dacd88d6SYuval Mintz if (rc) 667b0bccb69SYuval Mintz goto exit; 668dacd88d6SYuval Mintz 669b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 670b0bccb69SYuval Mintz rc = -EINVAL; 671b0bccb69SYuval Mintz goto exit; 672b0bccb69SYuval Mintz } 673b0bccb69SYuval Mintz 674b0bccb69SYuval Mintz exit: 675b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 676dacd88d6SYuval Mintz 677dacd88d6SYuval Mintz return rc; 678dacd88d6SYuval Mintz } 679dacd88d6SYuval Mintz 6803da7a37aSMintz, Yuval int 6813da7a37aSMintz, Yuval qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn, 6823da7a37aSMintz, Yuval struct qed_queue_cid *p_cid, 683dacd88d6SYuval Mintz dma_addr_t pbl_addr, 684dacd88d6SYuval Mintz u16 pbl_size, void __iomem **pp_doorbell) 685dacd88d6SYuval Mintz { 686dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 6875040acf5SYuval Mintz struct pfvf_start_queue_resp_tlv *resp; 688dacd88d6SYuval Mintz struct vfpf_start_txq_tlv *req; 6893da7a37aSMintz, Yuval u16 qid = p_cid->rel.queue_id; 690dacd88d6SYuval Mintz int rc; 691dacd88d6SYuval Mintz 692dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 693dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_TXQ, sizeof(*req)); 694dacd88d6SYuval Mintz 6953da7a37aSMintz, Yuval req->tx_qid = qid; 696dacd88d6SYuval Mintz 697dacd88d6SYuval Mintz /* Tx */ 698dacd88d6SYuval Mintz req->pbl_addr = pbl_addr; 699dacd88d6SYuval Mintz req->pbl_size = pbl_size; 7003da7a37aSMintz, Yuval req->hw_sb = p_cid->rel.sb; 7013da7a37aSMintz, Yuval req->sb_index = p_cid->rel.sb_idx; 702dacd88d6SYuval Mintz 703dacd88d6SYuval Mintz /* add list termination tlv */ 704dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 705dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 706dacd88d6SYuval Mintz 7075040acf5SYuval Mintz resp = &p_iov->pf2vf_reply->queue_start; 708dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 709dacd88d6SYuval Mintz if (rc) 7105040acf5SYuval Mintz goto exit; 711dacd88d6SYuval Mintz 7125040acf5SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 7135040acf5SYuval Mintz rc = -EINVAL; 7145040acf5SYuval Mintz goto exit; 7155040acf5SYuval Mintz } 716dacd88d6SYuval Mintz 717d8c2c7e3SYuval Mintz /* Modern PFs provide the actual offsets, while legacy 718d8c2c7e3SYuval Mintz * provided only the queue id. 719d8c2c7e3SYuval Mintz */ 720d8c2c7e3SYuval Mintz if (!p_iov->b_pre_fp_hsi) { 7213da7a37aSMintz, Yuval *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + resp->offset; 722d8c2c7e3SYuval Mintz } else { 7233da7a37aSMintz, Yuval u8 cid = p_iov->acquire_resp.resc.cid[qid]; 724d8c2c7e3SYuval Mintz 725d8c2c7e3SYuval Mintz *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + 7263da7a37aSMintz, Yuval qed_db_addr_vf(cid, 7273da7a37aSMintz, Yuval DQ_DEMS_LEGACY); 728d8c2c7e3SYuval Mintz } 729dacd88d6SYuval Mintz 7305040acf5SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 7315040acf5SYuval Mintz "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n", 7323da7a37aSMintz, Yuval qid, *pp_doorbell, resp->offset); 7335040acf5SYuval Mintz exit: 734b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 735dacd88d6SYuval Mintz 736dacd88d6SYuval Mintz return rc; 737dacd88d6SYuval Mintz } 738dacd88d6SYuval Mintz 7393da7a37aSMintz, Yuval int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid) 740dacd88d6SYuval Mintz { 741dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 742dacd88d6SYuval Mintz struct vfpf_stop_txqs_tlv *req; 743dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 744dacd88d6SYuval Mintz int rc; 745dacd88d6SYuval Mintz 746dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 747dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_TXQS, sizeof(*req)); 748dacd88d6SYuval Mintz 7493da7a37aSMintz, Yuval req->tx_qid = p_cid->rel.queue_id; 750dacd88d6SYuval Mintz req->num_txqs = 1; 751dacd88d6SYuval Mintz 752dacd88d6SYuval Mintz /* add list termination tlv */ 753dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 754dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 755dacd88d6SYuval Mintz 756dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 757dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 758dacd88d6SYuval Mintz if (rc) 759b0bccb69SYuval Mintz goto exit; 760dacd88d6SYuval Mintz 761b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 762b0bccb69SYuval Mintz rc = -EINVAL; 763b0bccb69SYuval Mintz goto exit; 764b0bccb69SYuval Mintz } 765b0bccb69SYuval Mintz 766b0bccb69SYuval Mintz exit: 767b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 768dacd88d6SYuval Mintz 769dacd88d6SYuval Mintz return rc; 770dacd88d6SYuval Mintz } 771dacd88d6SYuval Mintz 772dacd88d6SYuval Mintz int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, 773dacd88d6SYuval Mintz u8 vport_id, 774dacd88d6SYuval Mintz u16 mtu, 775dacd88d6SYuval Mintz u8 inner_vlan_removal, 776dacd88d6SYuval Mintz enum qed_tpa_mode tpa_mode, 77708feecd7SYuval Mintz u8 max_buffers_per_cqe, u8 only_untagged) 778dacd88d6SYuval Mintz { 779dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 780dacd88d6SYuval Mintz struct vfpf_vport_start_tlv *req; 781dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 782dacd88d6SYuval Mintz int rc, i; 783dacd88d6SYuval Mintz 784dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 785dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_START, sizeof(*req)); 786dacd88d6SYuval Mintz 787dacd88d6SYuval Mintz req->mtu = mtu; 788dacd88d6SYuval Mintz req->vport_id = vport_id; 789dacd88d6SYuval Mintz req->inner_vlan_removal = inner_vlan_removal; 790dacd88d6SYuval Mintz req->tpa_mode = tpa_mode; 791dacd88d6SYuval Mintz req->max_buffers_per_cqe = max_buffers_per_cqe; 79208feecd7SYuval Mintz req->only_untagged = only_untagged; 793dacd88d6SYuval Mintz 794dacd88d6SYuval Mintz /* status blocks */ 79550a20714SMintz, Yuval for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++) { 79650a20714SMintz, Yuval struct qed_sb_info *p_sb = p_hwfn->vf_iov_info->sbs_info[i]; 79750a20714SMintz, Yuval 79850a20714SMintz, Yuval if (p_sb) 79950a20714SMintz, Yuval req->sb_addr[i] = p_sb->sb_phys; 80050a20714SMintz, Yuval } 801dacd88d6SYuval Mintz 802dacd88d6SYuval Mintz /* add list termination tlv */ 803dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 804dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 805dacd88d6SYuval Mintz 806dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 807dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 808dacd88d6SYuval Mintz if (rc) 809b0bccb69SYuval Mintz goto exit; 810dacd88d6SYuval Mintz 811b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 812b0bccb69SYuval Mintz rc = -EINVAL; 813b0bccb69SYuval Mintz goto exit; 814b0bccb69SYuval Mintz } 815b0bccb69SYuval Mintz 816b0bccb69SYuval Mintz exit: 817b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 818dacd88d6SYuval Mintz 819dacd88d6SYuval Mintz return rc; 820dacd88d6SYuval Mintz } 821dacd88d6SYuval Mintz 822dacd88d6SYuval Mintz int qed_vf_pf_vport_stop(struct qed_hwfn *p_hwfn) 823dacd88d6SYuval Mintz { 824dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 825dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp = &p_iov->pf2vf_reply->default_resp; 826dacd88d6SYuval Mintz int rc; 827dacd88d6SYuval Mintz 828dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 829dacd88d6SYuval Mintz qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_TEARDOWN, 830dacd88d6SYuval Mintz sizeof(struct vfpf_first_tlv)); 831dacd88d6SYuval Mintz 832dacd88d6SYuval Mintz /* add list termination tlv */ 833dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 834dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 835dacd88d6SYuval Mintz 836dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 837dacd88d6SYuval Mintz if (rc) 838b0bccb69SYuval Mintz goto exit; 839dacd88d6SYuval Mintz 840b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 841b0bccb69SYuval Mintz rc = -EINVAL; 842b0bccb69SYuval Mintz goto exit; 843b0bccb69SYuval Mintz } 844b0bccb69SYuval Mintz 845b0bccb69SYuval Mintz exit: 846b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 847dacd88d6SYuval Mintz 848dacd88d6SYuval Mintz return rc; 849dacd88d6SYuval Mintz } 850dacd88d6SYuval Mintz 851dacd88d6SYuval Mintz static bool 852dacd88d6SYuval Mintz qed_vf_handle_vp_update_is_needed(struct qed_hwfn *p_hwfn, 853dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data, 854dacd88d6SYuval Mintz u16 tlv) 855dacd88d6SYuval Mintz { 856dacd88d6SYuval Mintz switch (tlv) { 857dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_ACTIVATE: 858dacd88d6SYuval Mintz return !!(p_data->update_vport_active_rx_flg || 859dacd88d6SYuval Mintz p_data->update_vport_active_tx_flg); 86017b235c1SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH: 86117b235c1SYuval Mintz return !!p_data->update_tx_switching_flg; 86217b235c1SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP: 86317b235c1SYuval Mintz return !!p_data->update_inner_vlan_removal_flg; 86408feecd7SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN: 86508feecd7SYuval Mintz return !!p_data->update_accept_any_vlan_flg; 866dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_MCAST: 867dacd88d6SYuval Mintz return !!p_data->update_approx_mcast_flg; 868dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM: 869dacd88d6SYuval Mintz return !!(p_data->accept_flags.update_rx_mode_config || 870dacd88d6SYuval Mintz p_data->accept_flags.update_tx_mode_config); 871dacd88d6SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_RSS: 872dacd88d6SYuval Mintz return !!p_data->rss_params; 87317b235c1SYuval Mintz case CHANNEL_TLV_VPORT_UPDATE_SGE_TPA: 87417b235c1SYuval Mintz return !!p_data->sge_tpa_params; 875dacd88d6SYuval Mintz default: 876dacd88d6SYuval Mintz DP_INFO(p_hwfn, "Unexpected vport-update TLV[%d]\n", 877dacd88d6SYuval Mintz tlv); 878dacd88d6SYuval Mintz return false; 879dacd88d6SYuval Mintz } 880dacd88d6SYuval Mintz } 881dacd88d6SYuval Mintz 882dacd88d6SYuval Mintz static void 883dacd88d6SYuval Mintz qed_vf_handle_vp_update_tlvs_resp(struct qed_hwfn *p_hwfn, 884dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_data) 885dacd88d6SYuval Mintz { 886dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 887dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *p_resp; 888dacd88d6SYuval Mintz u16 tlv; 889dacd88d6SYuval Mintz 890dacd88d6SYuval Mintz for (tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE; 891dacd88d6SYuval Mintz tlv < CHANNEL_TLV_VPORT_UPDATE_MAX; tlv++) { 892dacd88d6SYuval Mintz if (!qed_vf_handle_vp_update_is_needed(p_hwfn, p_data, tlv)) 893dacd88d6SYuval Mintz continue; 894dacd88d6SYuval Mintz 895dacd88d6SYuval Mintz p_resp = (struct pfvf_def_resp_tlv *) 896dacd88d6SYuval Mintz qed_iov_search_list_tlvs(p_hwfn, p_iov->pf2vf_reply, 897dacd88d6SYuval Mintz tlv); 898dacd88d6SYuval Mintz if (p_resp && p_resp->hdr.status) 899dacd88d6SYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 900dacd88d6SYuval Mintz "TLV[%d] Configuration %s\n", 901dacd88d6SYuval Mintz tlv, 902dacd88d6SYuval Mintz (p_resp && p_resp->hdr.status) ? "succeeded" 903dacd88d6SYuval Mintz : "failed"); 904dacd88d6SYuval Mintz } 905dacd88d6SYuval Mintz } 906dacd88d6SYuval Mintz 907dacd88d6SYuval Mintz int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, 908dacd88d6SYuval Mintz struct qed_sp_vport_update_params *p_params) 909dacd88d6SYuval Mintz { 910dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 911dacd88d6SYuval Mintz struct vfpf_vport_update_tlv *req; 912dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 913dacd88d6SYuval Mintz u8 update_rx, update_tx; 914dacd88d6SYuval Mintz u32 resp_size = 0; 915dacd88d6SYuval Mintz u16 size, tlv; 916dacd88d6SYuval Mintz int rc; 917dacd88d6SYuval Mintz 918dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 919dacd88d6SYuval Mintz resp_size = sizeof(*resp); 920dacd88d6SYuval Mintz 921dacd88d6SYuval Mintz update_rx = p_params->update_vport_active_rx_flg; 922dacd88d6SYuval Mintz update_tx = p_params->update_vport_active_tx_flg; 923dacd88d6SYuval Mintz 924dacd88d6SYuval Mintz /* clear mailbox and prep header tlv */ 925dacd88d6SYuval Mintz qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_UPDATE, sizeof(*req)); 926dacd88d6SYuval Mintz 927dacd88d6SYuval Mintz /* Prepare extended tlvs */ 928dacd88d6SYuval Mintz if (update_rx || update_tx) { 929dacd88d6SYuval Mintz struct vfpf_vport_update_activate_tlv *p_act_tlv; 930dacd88d6SYuval Mintz 931dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_activate_tlv); 932dacd88d6SYuval Mintz p_act_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, 933dacd88d6SYuval Mintz CHANNEL_TLV_VPORT_UPDATE_ACTIVATE, 934dacd88d6SYuval Mintz size); 935dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 936dacd88d6SYuval Mintz 937dacd88d6SYuval Mintz if (update_rx) { 938dacd88d6SYuval Mintz p_act_tlv->update_rx = update_rx; 939dacd88d6SYuval Mintz p_act_tlv->active_rx = p_params->vport_active_rx_flg; 940dacd88d6SYuval Mintz } 941dacd88d6SYuval Mintz 942dacd88d6SYuval Mintz if (update_tx) { 943dacd88d6SYuval Mintz p_act_tlv->update_tx = update_tx; 944dacd88d6SYuval Mintz p_act_tlv->active_tx = p_params->vport_active_tx_flg; 945dacd88d6SYuval Mintz } 946dacd88d6SYuval Mintz } 947dacd88d6SYuval Mintz 948831bfb0eSYuval Mintz if (p_params->update_tx_switching_flg) { 949831bfb0eSYuval Mintz struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv; 950831bfb0eSYuval Mintz 951831bfb0eSYuval Mintz size = sizeof(struct vfpf_vport_update_tx_switch_tlv); 952831bfb0eSYuval Mintz tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; 953831bfb0eSYuval Mintz p_tx_switch_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, 954831bfb0eSYuval Mintz tlv, size); 955831bfb0eSYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 956831bfb0eSYuval Mintz 957831bfb0eSYuval Mintz p_tx_switch_tlv->tx_switching = p_params->tx_switching_flg; 958831bfb0eSYuval Mintz } 959831bfb0eSYuval Mintz 960dacd88d6SYuval Mintz if (p_params->update_approx_mcast_flg) { 961dacd88d6SYuval Mintz struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv; 962dacd88d6SYuval Mintz 963dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_mcast_bin_tlv); 964dacd88d6SYuval Mintz p_mcast_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, 965dacd88d6SYuval Mintz CHANNEL_TLV_VPORT_UPDATE_MCAST, size); 966dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 967dacd88d6SYuval Mintz 968dacd88d6SYuval Mintz memcpy(p_mcast_tlv->bins, p_params->bins, 969dacd88d6SYuval Mintz sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS); 970dacd88d6SYuval Mintz } 971dacd88d6SYuval Mintz 972dacd88d6SYuval Mintz update_rx = p_params->accept_flags.update_rx_mode_config; 973dacd88d6SYuval Mintz update_tx = p_params->accept_flags.update_tx_mode_config; 974dacd88d6SYuval Mintz 975dacd88d6SYuval Mintz if (update_rx || update_tx) { 976dacd88d6SYuval Mintz struct vfpf_vport_update_accept_param_tlv *p_accept_tlv; 977dacd88d6SYuval Mintz 978dacd88d6SYuval Mintz tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; 979dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_accept_param_tlv); 980dacd88d6SYuval Mintz p_accept_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); 981dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 982dacd88d6SYuval Mintz 983dacd88d6SYuval Mintz if (update_rx) { 984dacd88d6SYuval Mintz p_accept_tlv->update_rx_mode = update_rx; 985dacd88d6SYuval Mintz p_accept_tlv->rx_accept_filter = 986dacd88d6SYuval Mintz p_params->accept_flags.rx_accept_filter; 987dacd88d6SYuval Mintz } 988dacd88d6SYuval Mintz 989dacd88d6SYuval Mintz if (update_tx) { 990dacd88d6SYuval Mintz p_accept_tlv->update_tx_mode = update_tx; 991dacd88d6SYuval Mintz p_accept_tlv->tx_accept_filter = 992dacd88d6SYuval Mintz p_params->accept_flags.tx_accept_filter; 993dacd88d6SYuval Mintz } 994dacd88d6SYuval Mintz } 995dacd88d6SYuval Mintz 996dacd88d6SYuval Mintz if (p_params->rss_params) { 997dacd88d6SYuval Mintz struct qed_rss_params *rss_params = p_params->rss_params; 998dacd88d6SYuval Mintz struct vfpf_vport_update_rss_tlv *p_rss_tlv; 999f29ffdb6SMintz, Yuval int i, table_size; 1000dacd88d6SYuval Mintz 1001dacd88d6SYuval Mintz size = sizeof(struct vfpf_vport_update_rss_tlv); 1002dacd88d6SYuval Mintz p_rss_tlv = qed_add_tlv(p_hwfn, 1003dacd88d6SYuval Mintz &p_iov->offset, 1004dacd88d6SYuval Mintz CHANNEL_TLV_VPORT_UPDATE_RSS, size); 1005dacd88d6SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 1006dacd88d6SYuval Mintz 1007dacd88d6SYuval Mintz if (rss_params->update_rss_config) 1008dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= 1009dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CONFIG_FLAG; 1010dacd88d6SYuval Mintz if (rss_params->update_rss_capabilities) 1011dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= 1012dacd88d6SYuval Mintz VFPF_UPDATE_RSS_CAPS_FLAG; 1013dacd88d6SYuval Mintz if (rss_params->update_rss_ind_table) 1014dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= 1015dacd88d6SYuval Mintz VFPF_UPDATE_RSS_IND_TABLE_FLAG; 1016dacd88d6SYuval Mintz if (rss_params->update_rss_key) 1017dacd88d6SYuval Mintz p_rss_tlv->update_rss_flags |= VFPF_UPDATE_RSS_KEY_FLAG; 1018dacd88d6SYuval Mintz 1019dacd88d6SYuval Mintz p_rss_tlv->rss_enable = rss_params->rss_enable; 1020dacd88d6SYuval Mintz p_rss_tlv->rss_caps = rss_params->rss_caps; 1021dacd88d6SYuval Mintz p_rss_tlv->rss_table_size_log = rss_params->rss_table_size_log; 1022f29ffdb6SMintz, Yuval 1023f29ffdb6SMintz, Yuval table_size = min_t(int, T_ETH_INDIRECTION_TABLE_SIZE, 1024f29ffdb6SMintz, Yuval 1 << p_rss_tlv->rss_table_size_log); 1025f29ffdb6SMintz, Yuval for (i = 0; i < table_size; i++) { 1026f29ffdb6SMintz, Yuval struct qed_queue_cid *p_queue; 1027f29ffdb6SMintz, Yuval 1028f29ffdb6SMintz, Yuval p_queue = rss_params->rss_ind_table[i]; 1029f29ffdb6SMintz, Yuval p_rss_tlv->rss_ind_table[i] = p_queue->rel.queue_id; 1030f29ffdb6SMintz, Yuval } 1031dacd88d6SYuval Mintz memcpy(p_rss_tlv->rss_key, rss_params->rss_key, 1032dacd88d6SYuval Mintz sizeof(rss_params->rss_key)); 1033dacd88d6SYuval Mintz } 1034dacd88d6SYuval Mintz 103508feecd7SYuval Mintz if (p_params->update_accept_any_vlan_flg) { 103608feecd7SYuval Mintz struct vfpf_vport_update_accept_any_vlan_tlv *p_any_vlan_tlv; 103708feecd7SYuval Mintz 103808feecd7SYuval Mintz size = sizeof(struct vfpf_vport_update_accept_any_vlan_tlv); 103908feecd7SYuval Mintz tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; 104008feecd7SYuval Mintz p_any_vlan_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); 104108feecd7SYuval Mintz 104208feecd7SYuval Mintz resp_size += sizeof(struct pfvf_def_resp_tlv); 104308feecd7SYuval Mintz p_any_vlan_tlv->accept_any_vlan = p_params->accept_any_vlan; 104408feecd7SYuval Mintz p_any_vlan_tlv->update_accept_any_vlan_flg = 104508feecd7SYuval Mintz p_params->update_accept_any_vlan_flg; 104608feecd7SYuval Mintz } 104708feecd7SYuval Mintz 1048dacd88d6SYuval Mintz /* add list termination tlv */ 1049dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 1050dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 1051dacd88d6SYuval Mintz 1052dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, resp_size); 1053dacd88d6SYuval Mintz if (rc) 1054b0bccb69SYuval Mintz goto exit; 1055dacd88d6SYuval Mintz 1056b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 1057b0bccb69SYuval Mintz rc = -EINVAL; 1058b0bccb69SYuval Mintz goto exit; 1059b0bccb69SYuval Mintz } 1060dacd88d6SYuval Mintz 1061dacd88d6SYuval Mintz qed_vf_handle_vp_update_tlvs_resp(p_hwfn, p_params); 1062dacd88d6SYuval Mintz 1063b0bccb69SYuval Mintz exit: 1064b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1065b0bccb69SYuval Mintz 1066dacd88d6SYuval Mintz return rc; 1067dacd88d6SYuval Mintz } 1068dacd88d6SYuval Mintz 10690b55e27dSYuval Mintz int qed_vf_pf_reset(struct qed_hwfn *p_hwfn) 10700b55e27dSYuval Mintz { 10710b55e27dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 10720b55e27dSYuval Mintz struct pfvf_def_resp_tlv *resp; 10730b55e27dSYuval Mintz struct vfpf_first_tlv *req; 10740b55e27dSYuval Mintz int rc; 10750b55e27dSYuval Mintz 10760b55e27dSYuval Mintz /* clear mailbox and prep first tlv */ 10770b55e27dSYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_CLOSE, sizeof(*req)); 10780b55e27dSYuval Mintz 10790b55e27dSYuval Mintz /* add list termination tlv */ 10800b55e27dSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 10810b55e27dSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 10820b55e27dSYuval Mintz 10830b55e27dSYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 10840b55e27dSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 10850b55e27dSYuval Mintz if (rc) 1086b0bccb69SYuval Mintz goto exit; 10870b55e27dSYuval Mintz 1088b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 1089b0bccb69SYuval Mintz rc = -EAGAIN; 1090b0bccb69SYuval Mintz goto exit; 1091b0bccb69SYuval Mintz } 10920b55e27dSYuval Mintz 10930b55e27dSYuval Mintz p_hwfn->b_int_enabled = 0; 10940b55e27dSYuval Mintz 1095b0bccb69SYuval Mintz exit: 1096b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1097b0bccb69SYuval Mintz 1098b0bccb69SYuval Mintz return rc; 10990b55e27dSYuval Mintz } 11000b55e27dSYuval Mintz 11010b55e27dSYuval Mintz int qed_vf_pf_release(struct qed_hwfn *p_hwfn) 11020b55e27dSYuval Mintz { 11030b55e27dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 11040b55e27dSYuval Mintz struct pfvf_def_resp_tlv *resp; 11050b55e27dSYuval Mintz struct vfpf_first_tlv *req; 11060b55e27dSYuval Mintz u32 size; 11070b55e27dSYuval Mintz int rc; 11080b55e27dSYuval Mintz 11090b55e27dSYuval Mintz /* clear mailbox and prep first tlv */ 11100b55e27dSYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_RELEASE, sizeof(*req)); 11110b55e27dSYuval Mintz 11120b55e27dSYuval Mintz /* add list termination tlv */ 11130b55e27dSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 11140b55e27dSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 11150b55e27dSYuval Mintz 11160b55e27dSYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 11170b55e27dSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 11180b55e27dSYuval Mintz 11190b55e27dSYuval Mintz if (!rc && resp->hdr.status != PFVF_STATUS_SUCCESS) 11200b55e27dSYuval Mintz rc = -EAGAIN; 11210b55e27dSYuval Mintz 1122b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1123b0bccb69SYuval Mintz 11240b55e27dSYuval Mintz p_hwfn->b_int_enabled = 0; 11250b55e27dSYuval Mintz 11260b55e27dSYuval Mintz if (p_iov->vf2pf_request) 11270b55e27dSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 11280b55e27dSYuval Mintz sizeof(union vfpf_tlvs), 11290b55e27dSYuval Mintz p_iov->vf2pf_request, 11300b55e27dSYuval Mintz p_iov->vf2pf_request_phys); 11310b55e27dSYuval Mintz if (p_iov->pf2vf_reply) 11320b55e27dSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 11330b55e27dSYuval Mintz sizeof(union pfvf_tlvs), 11340b55e27dSYuval Mintz p_iov->pf2vf_reply, p_iov->pf2vf_reply_phys); 11350b55e27dSYuval Mintz 11360b55e27dSYuval Mintz if (p_iov->bulletin.p_virt) { 11370b55e27dSYuval Mintz size = sizeof(struct qed_bulletin_content); 11380b55e27dSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 11390b55e27dSYuval Mintz size, 11400b55e27dSYuval Mintz p_iov->bulletin.p_virt, p_iov->bulletin.phys); 11410b55e27dSYuval Mintz } 11420b55e27dSYuval Mintz 11430b55e27dSYuval Mintz kfree(p_hwfn->vf_iov_info); 11440b55e27dSYuval Mintz p_hwfn->vf_iov_info = NULL; 11450b55e27dSYuval Mintz 11460b55e27dSYuval Mintz return rc; 11470b55e27dSYuval Mintz } 11480b55e27dSYuval Mintz 1149dacd88d6SYuval Mintz void qed_vf_pf_filter_mcast(struct qed_hwfn *p_hwfn, 1150dacd88d6SYuval Mintz struct qed_filter_mcast *p_filter_cmd) 1151dacd88d6SYuval Mintz { 1152dacd88d6SYuval Mintz struct qed_sp_vport_update_params sp_params; 1153dacd88d6SYuval Mintz int i; 1154dacd88d6SYuval Mintz 1155dacd88d6SYuval Mintz memset(&sp_params, 0, sizeof(sp_params)); 1156dacd88d6SYuval Mintz sp_params.update_approx_mcast_flg = 1; 1157dacd88d6SYuval Mintz 1158dacd88d6SYuval Mintz if (p_filter_cmd->opcode == QED_FILTER_ADD) { 1159dacd88d6SYuval Mintz for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { 1160dacd88d6SYuval Mintz u32 bit; 1161dacd88d6SYuval Mintz 1162dacd88d6SYuval Mintz bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]); 1163dacd88d6SYuval Mintz __set_bit(bit, sp_params.bins); 1164dacd88d6SYuval Mintz } 1165dacd88d6SYuval Mintz } 1166dacd88d6SYuval Mintz 1167dacd88d6SYuval Mintz qed_vf_pf_vport_update(p_hwfn, &sp_params); 1168dacd88d6SYuval Mintz } 1169dacd88d6SYuval Mintz 1170dacd88d6SYuval Mintz int qed_vf_pf_filter_ucast(struct qed_hwfn *p_hwfn, 1171dacd88d6SYuval Mintz struct qed_filter_ucast *p_ucast) 1172dacd88d6SYuval Mintz { 1173dacd88d6SYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 1174dacd88d6SYuval Mintz struct vfpf_ucast_filter_tlv *req; 1175dacd88d6SYuval Mintz struct pfvf_def_resp_tlv *resp; 1176dacd88d6SYuval Mintz int rc; 1177dacd88d6SYuval Mintz 1178dacd88d6SYuval Mintz /* clear mailbox and prep first tlv */ 1179dacd88d6SYuval Mintz req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_UCAST_FILTER, sizeof(*req)); 1180dacd88d6SYuval Mintz req->opcode = (u8) p_ucast->opcode; 1181dacd88d6SYuval Mintz req->type = (u8) p_ucast->type; 1182dacd88d6SYuval Mintz memcpy(req->mac, p_ucast->mac, ETH_ALEN); 1183dacd88d6SYuval Mintz req->vlan = p_ucast->vlan; 1184dacd88d6SYuval Mintz 1185dacd88d6SYuval Mintz /* add list termination tlv */ 1186dacd88d6SYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 1187dacd88d6SYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 1188dacd88d6SYuval Mintz 1189dacd88d6SYuval Mintz resp = &p_iov->pf2vf_reply->default_resp; 1190dacd88d6SYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 1191dacd88d6SYuval Mintz if (rc) 1192b0bccb69SYuval Mintz goto exit; 1193b0bccb69SYuval Mintz 1194b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 1195b0bccb69SYuval Mintz rc = -EAGAIN; 1196b0bccb69SYuval Mintz goto exit; 1197b0bccb69SYuval Mintz } 1198b0bccb69SYuval Mintz 1199b0bccb69SYuval Mintz exit: 1200b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1201b0bccb69SYuval Mintz 1202dacd88d6SYuval Mintz return rc; 1203dacd88d6SYuval Mintz } 1204dacd88d6SYuval Mintz 12050b55e27dSYuval Mintz int qed_vf_pf_int_cleanup(struct qed_hwfn *p_hwfn) 12060b55e27dSYuval Mintz { 12070b55e27dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 12080b55e27dSYuval Mintz struct pfvf_def_resp_tlv *resp = &p_iov->pf2vf_reply->default_resp; 12090b55e27dSYuval Mintz int rc; 12100b55e27dSYuval Mintz 12110b55e27dSYuval Mintz /* clear mailbox and prep first tlv */ 12120b55e27dSYuval Mintz qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_INT_CLEANUP, 12130b55e27dSYuval Mintz sizeof(struct vfpf_first_tlv)); 12140b55e27dSYuval Mintz 12150b55e27dSYuval Mintz /* add list termination tlv */ 12160b55e27dSYuval Mintz qed_add_tlv(p_hwfn, &p_iov->offset, 12170b55e27dSYuval Mintz CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 12180b55e27dSYuval Mintz 12190b55e27dSYuval Mintz rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 12200b55e27dSYuval Mintz if (rc) 1221b0bccb69SYuval Mintz goto exit; 1222b0bccb69SYuval Mintz 1223b0bccb69SYuval Mintz if (resp->hdr.status != PFVF_STATUS_SUCCESS) { 1224b0bccb69SYuval Mintz rc = -EINVAL; 1225b0bccb69SYuval Mintz goto exit; 1226b0bccb69SYuval Mintz } 1227b0bccb69SYuval Mintz 1228b0bccb69SYuval Mintz exit: 1229b0bccb69SYuval Mintz qed_vf_pf_req_end(p_hwfn, rc); 1230b0bccb69SYuval Mintz 12310b55e27dSYuval Mintz return rc; 12320b55e27dSYuval Mintz } 12330b55e27dSYuval Mintz 12341408cc1fSYuval Mintz u16 qed_vf_get_igu_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id) 12351408cc1fSYuval Mintz { 12361408cc1fSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 12371408cc1fSYuval Mintz 12381408cc1fSYuval Mintz if (!p_iov) { 12391408cc1fSYuval Mintz DP_NOTICE(p_hwfn, "vf_sriov_info isn't initialized\n"); 12401408cc1fSYuval Mintz return 0; 12411408cc1fSYuval Mintz } 12421408cc1fSYuval Mintz 12431408cc1fSYuval Mintz return p_iov->acquire_resp.resc.hw_sbs[sb_id].hw_sb_id; 12441408cc1fSYuval Mintz } 12451408cc1fSYuval Mintz 124650a20714SMintz, Yuval void qed_vf_set_sb_info(struct qed_hwfn *p_hwfn, 124750a20714SMintz, Yuval u16 sb_id, struct qed_sb_info *p_sb) 124850a20714SMintz, Yuval { 124950a20714SMintz, Yuval struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 125050a20714SMintz, Yuval 125150a20714SMintz, Yuval if (!p_iov) { 125250a20714SMintz, Yuval DP_NOTICE(p_hwfn, "vf_sriov_info isn't initialized\n"); 125350a20714SMintz, Yuval return; 125450a20714SMintz, Yuval } 125550a20714SMintz, Yuval 125650a20714SMintz, Yuval if (sb_id >= PFVF_MAX_SBS_PER_VF) { 125750a20714SMintz, Yuval DP_NOTICE(p_hwfn, "Can't configure SB %04x\n", sb_id); 125850a20714SMintz, Yuval return; 125950a20714SMintz, Yuval } 126050a20714SMintz, Yuval 126150a20714SMintz, Yuval p_iov->sbs_info[sb_id] = p_sb; 126250a20714SMintz, Yuval } 126350a20714SMintz, Yuval 126436558c3dSYuval Mintz int qed_vf_read_bulletin(struct qed_hwfn *p_hwfn, u8 *p_change) 126536558c3dSYuval Mintz { 126636558c3dSYuval Mintz struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 126736558c3dSYuval Mintz struct qed_bulletin_content shadow; 126836558c3dSYuval Mintz u32 crc, crc_size; 126936558c3dSYuval Mintz 127036558c3dSYuval Mintz crc_size = sizeof(p_iov->bulletin.p_virt->crc); 127136558c3dSYuval Mintz *p_change = 0; 127236558c3dSYuval Mintz 127336558c3dSYuval Mintz /* Need to guarantee PF is not in the middle of writing it */ 127436558c3dSYuval Mintz memcpy(&shadow, p_iov->bulletin.p_virt, p_iov->bulletin.size); 127536558c3dSYuval Mintz 127636558c3dSYuval Mintz /* If version did not update, no need to do anything */ 127736558c3dSYuval Mintz if (shadow.version == p_iov->bulletin_shadow.version) 127836558c3dSYuval Mintz return 0; 127936558c3dSYuval Mintz 128036558c3dSYuval Mintz /* Verify the bulletin we see is valid */ 128136558c3dSYuval Mintz crc = crc32(0, (u8 *)&shadow + crc_size, 128236558c3dSYuval Mintz p_iov->bulletin.size - crc_size); 128336558c3dSYuval Mintz if (crc != shadow.crc) 128436558c3dSYuval Mintz return -EAGAIN; 128536558c3dSYuval Mintz 128636558c3dSYuval Mintz /* Set the shadow bulletin and process it */ 128736558c3dSYuval Mintz memcpy(&p_iov->bulletin_shadow, &shadow, p_iov->bulletin.size); 128836558c3dSYuval Mintz 128936558c3dSYuval Mintz DP_VERBOSE(p_hwfn, QED_MSG_IOV, 129036558c3dSYuval Mintz "Read a bulletin update %08x\n", shadow.version); 129136558c3dSYuval Mintz 129236558c3dSYuval Mintz *p_change = 1; 129336558c3dSYuval Mintz 129436558c3dSYuval Mintz return 0; 129536558c3dSYuval Mintz } 129636558c3dSYuval Mintz 129736558c3dSYuval Mintz void __qed_vf_get_link_params(struct qed_hwfn *p_hwfn, 129836558c3dSYuval Mintz struct qed_mcp_link_params *p_params, 129936558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin) 130036558c3dSYuval Mintz { 130136558c3dSYuval Mintz memset(p_params, 0, sizeof(*p_params)); 130236558c3dSYuval Mintz 130336558c3dSYuval Mintz p_params->speed.autoneg = p_bulletin->req_autoneg; 130436558c3dSYuval Mintz p_params->speed.advertised_speeds = p_bulletin->req_adv_speed; 130536558c3dSYuval Mintz p_params->speed.forced_speed = p_bulletin->req_forced_speed; 130636558c3dSYuval Mintz p_params->pause.autoneg = p_bulletin->req_autoneg_pause; 130736558c3dSYuval Mintz p_params->pause.forced_rx = p_bulletin->req_forced_rx; 130836558c3dSYuval Mintz p_params->pause.forced_tx = p_bulletin->req_forced_tx; 130936558c3dSYuval Mintz p_params->loopback_mode = p_bulletin->req_loopback; 131036558c3dSYuval Mintz } 131136558c3dSYuval Mintz 131236558c3dSYuval Mintz void qed_vf_get_link_params(struct qed_hwfn *p_hwfn, 131336558c3dSYuval Mintz struct qed_mcp_link_params *params) 131436558c3dSYuval Mintz { 131536558c3dSYuval Mintz __qed_vf_get_link_params(p_hwfn, params, 131636558c3dSYuval Mintz &(p_hwfn->vf_iov_info->bulletin_shadow)); 131736558c3dSYuval Mintz } 131836558c3dSYuval Mintz 131936558c3dSYuval Mintz void __qed_vf_get_link_state(struct qed_hwfn *p_hwfn, 132036558c3dSYuval Mintz struct qed_mcp_link_state *p_link, 132136558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin) 132236558c3dSYuval Mintz { 132336558c3dSYuval Mintz memset(p_link, 0, sizeof(*p_link)); 132436558c3dSYuval Mintz 132536558c3dSYuval Mintz p_link->link_up = p_bulletin->link_up; 132636558c3dSYuval Mintz p_link->speed = p_bulletin->speed; 132736558c3dSYuval Mintz p_link->full_duplex = p_bulletin->full_duplex; 132836558c3dSYuval Mintz p_link->an = p_bulletin->autoneg; 132936558c3dSYuval Mintz p_link->an_complete = p_bulletin->autoneg_complete; 133036558c3dSYuval Mintz p_link->parallel_detection = p_bulletin->parallel_detection; 133136558c3dSYuval Mintz p_link->pfc_enabled = p_bulletin->pfc_enabled; 133236558c3dSYuval Mintz p_link->partner_adv_speed = p_bulletin->partner_adv_speed; 133336558c3dSYuval Mintz p_link->partner_tx_flow_ctrl_en = p_bulletin->partner_tx_flow_ctrl_en; 133436558c3dSYuval Mintz p_link->partner_rx_flow_ctrl_en = p_bulletin->partner_rx_flow_ctrl_en; 133536558c3dSYuval Mintz p_link->partner_adv_pause = p_bulletin->partner_adv_pause; 133636558c3dSYuval Mintz p_link->sfp_tx_fault = p_bulletin->sfp_tx_fault; 133736558c3dSYuval Mintz } 133836558c3dSYuval Mintz 133936558c3dSYuval Mintz void qed_vf_get_link_state(struct qed_hwfn *p_hwfn, 134036558c3dSYuval Mintz struct qed_mcp_link_state *link) 134136558c3dSYuval Mintz { 134236558c3dSYuval Mintz __qed_vf_get_link_state(p_hwfn, link, 134336558c3dSYuval Mintz &(p_hwfn->vf_iov_info->bulletin_shadow)); 134436558c3dSYuval Mintz } 134536558c3dSYuval Mintz 134636558c3dSYuval Mintz void __qed_vf_get_link_caps(struct qed_hwfn *p_hwfn, 134736558c3dSYuval Mintz struct qed_mcp_link_capabilities *p_link_caps, 134836558c3dSYuval Mintz struct qed_bulletin_content *p_bulletin) 134936558c3dSYuval Mintz { 135036558c3dSYuval Mintz memset(p_link_caps, 0, sizeof(*p_link_caps)); 135136558c3dSYuval Mintz p_link_caps->speed_capabilities = p_bulletin->capability_speed; 135236558c3dSYuval Mintz } 135336558c3dSYuval Mintz 135436558c3dSYuval Mintz void qed_vf_get_link_caps(struct qed_hwfn *p_hwfn, 135536558c3dSYuval Mintz struct qed_mcp_link_capabilities *p_link_caps) 135636558c3dSYuval Mintz { 135736558c3dSYuval Mintz __qed_vf_get_link_caps(p_hwfn, p_link_caps, 135836558c3dSYuval Mintz &(p_hwfn->vf_iov_info->bulletin_shadow)); 135936558c3dSYuval Mintz } 136036558c3dSYuval Mintz 13611408cc1fSYuval Mintz void qed_vf_get_num_rxqs(struct qed_hwfn *p_hwfn, u8 *num_rxqs) 13621408cc1fSYuval Mintz { 13631408cc1fSYuval Mintz *num_rxqs = p_hwfn->vf_iov_info->acquire_resp.resc.num_rxqs; 13641408cc1fSYuval Mintz } 13651408cc1fSYuval Mintz 13660db711bbSMintz, Yuval void qed_vf_get_num_txqs(struct qed_hwfn *p_hwfn, u8 *num_txqs) 13670db711bbSMintz, Yuval { 13680db711bbSMintz, Yuval *num_txqs = p_hwfn->vf_iov_info->acquire_resp.resc.num_txqs; 13690db711bbSMintz, Yuval } 13700db711bbSMintz, Yuval 13711408cc1fSYuval Mintz void qed_vf_get_port_mac(struct qed_hwfn *p_hwfn, u8 *port_mac) 13721408cc1fSYuval Mintz { 13731408cc1fSYuval Mintz memcpy(port_mac, 13741408cc1fSYuval Mintz p_hwfn->vf_iov_info->acquire_resp.pfdev_info.port_mac, ETH_ALEN); 13751408cc1fSYuval Mintz } 13761408cc1fSYuval Mintz 13771408cc1fSYuval Mintz void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters) 13781408cc1fSYuval Mintz { 13791408cc1fSYuval Mintz struct qed_vf_iov *p_vf; 13801408cc1fSYuval Mintz 13811408cc1fSYuval Mintz p_vf = p_hwfn->vf_iov_info; 13821408cc1fSYuval Mintz *num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters; 13831408cc1fSYuval Mintz } 13841408cc1fSYuval Mintz 1385b0fca312SMintz, Yuval void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters) 1386b0fca312SMintz, Yuval { 1387b0fca312SMintz, Yuval struct qed_vf_iov *p_vf = p_hwfn->vf_iov_info; 1388b0fca312SMintz, Yuval 1389b0fca312SMintz, Yuval *num_mac_filters = p_vf->acquire_resp.resc.num_mac_filters; 1390b0fca312SMintz, Yuval } 1391b0fca312SMintz, Yuval 1392eff16960SYuval Mintz bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac) 1393eff16960SYuval Mintz { 1394eff16960SYuval Mintz struct qed_bulletin_content *bulletin; 1395eff16960SYuval Mintz 1396eff16960SYuval Mintz bulletin = &p_hwfn->vf_iov_info->bulletin_shadow; 1397eff16960SYuval Mintz if (!(bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED))) 1398eff16960SYuval Mintz return true; 1399eff16960SYuval Mintz 1400eff16960SYuval Mintz /* Forbid VF from changing a MAC enforced by PF */ 1401eff16960SYuval Mintz if (ether_addr_equal(bulletin->mac, mac)) 1402eff16960SYuval Mintz return false; 1403eff16960SYuval Mintz 1404eff16960SYuval Mintz return false; 1405eff16960SYuval Mintz } 1406eff16960SYuval Mintz 1407ba56947aSBaoyou Xie static bool qed_vf_bulletin_get_forced_mac(struct qed_hwfn *hwfn, 1408eff16960SYuval Mintz u8 *dst_mac, u8 *p_is_forced) 1409eff16960SYuval Mintz { 1410eff16960SYuval Mintz struct qed_bulletin_content *bulletin; 1411eff16960SYuval Mintz 1412eff16960SYuval Mintz bulletin = &hwfn->vf_iov_info->bulletin_shadow; 1413eff16960SYuval Mintz 1414eff16960SYuval Mintz if (bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) { 1415eff16960SYuval Mintz if (p_is_forced) 1416eff16960SYuval Mintz *p_is_forced = 1; 1417eff16960SYuval Mintz } else if (bulletin->valid_bitmap & (1 << VFPF_BULLETIN_MAC_ADDR)) { 1418eff16960SYuval Mintz if (p_is_forced) 1419eff16960SYuval Mintz *p_is_forced = 0; 1420eff16960SYuval Mintz } else { 1421eff16960SYuval Mintz return false; 1422eff16960SYuval Mintz } 1423eff16960SYuval Mintz 1424eff16960SYuval Mintz ether_addr_copy(dst_mac, bulletin->mac); 1425eff16960SYuval Mintz 1426eff16960SYuval Mintz return true; 1427eff16960SYuval Mintz } 1428eff16960SYuval Mintz 142997379f15SChopra, Manish static void 143097379f15SChopra, Manish qed_vf_bulletin_get_udp_ports(struct qed_hwfn *p_hwfn, 143197379f15SChopra, Manish u16 *p_vxlan_port, u16 *p_geneve_port) 143297379f15SChopra, Manish { 143397379f15SChopra, Manish struct qed_bulletin_content *p_bulletin; 143497379f15SChopra, Manish 143597379f15SChopra, Manish p_bulletin = &p_hwfn->vf_iov_info->bulletin_shadow; 143697379f15SChopra, Manish 143797379f15SChopra, Manish *p_vxlan_port = p_bulletin->vxlan_udp_port; 143897379f15SChopra, Manish *p_geneve_port = p_bulletin->geneve_udp_port; 143997379f15SChopra, Manish } 144097379f15SChopra, Manish 14411408cc1fSYuval Mintz void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn, 14421408cc1fSYuval Mintz u16 *fw_major, u16 *fw_minor, 14431408cc1fSYuval Mintz u16 *fw_rev, u16 *fw_eng) 14441408cc1fSYuval Mintz { 14451408cc1fSYuval Mintz struct pf_vf_pfdev_info *info; 14461408cc1fSYuval Mintz 14471408cc1fSYuval Mintz info = &p_hwfn->vf_iov_info->acquire_resp.pfdev_info; 14481408cc1fSYuval Mintz 14491408cc1fSYuval Mintz *fw_major = info->fw_major; 14501408cc1fSYuval Mintz *fw_minor = info->fw_minor; 14511408cc1fSYuval Mintz *fw_rev = info->fw_rev; 14521408cc1fSYuval Mintz *fw_eng = info->fw_eng; 14531408cc1fSYuval Mintz } 145436558c3dSYuval Mintz 145536558c3dSYuval Mintz static void qed_handle_bulletin_change(struct qed_hwfn *hwfn) 145636558c3dSYuval Mintz { 1457eff16960SYuval Mintz struct qed_eth_cb_ops *ops = hwfn->cdev->protocol_ops.eth; 1458eff16960SYuval Mintz u8 mac[ETH_ALEN], is_mac_exist, is_mac_forced; 1459eff16960SYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 146097379f15SChopra, Manish u16 vxlan_port, geneve_port; 1461eff16960SYuval Mintz 146297379f15SChopra, Manish qed_vf_bulletin_get_udp_ports(hwfn, &vxlan_port, &geneve_port); 1463eff16960SYuval Mintz is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac, 1464eff16960SYuval Mintz &is_mac_forced); 1465c3aaa403SYuval Mintz if (is_mac_exist && cookie) 1466c3aaa403SYuval Mintz ops->force_mac(cookie, mac, !!is_mac_forced); 1467eff16960SYuval Mintz 146897379f15SChopra, Manish ops->ports_update(cookie, vxlan_port, geneve_port); 146997379f15SChopra, Manish 147036558c3dSYuval Mintz /* Always update link configuration according to bulletin */ 147136558c3dSYuval Mintz qed_link_update(hwfn); 147236558c3dSYuval Mintz } 147336558c3dSYuval Mintz 147436558c3dSYuval Mintz void qed_iov_vf_task(struct work_struct *work) 147536558c3dSYuval Mintz { 147636558c3dSYuval Mintz struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn, 147736558c3dSYuval Mintz iov_task.work); 147836558c3dSYuval Mintz u8 change = 0; 147936558c3dSYuval Mintz 148036558c3dSYuval Mintz if (test_and_clear_bit(QED_IOV_WQ_STOP_WQ_FLAG, &hwfn->iov_task_flags)) 148136558c3dSYuval Mintz return; 148236558c3dSYuval Mintz 148336558c3dSYuval Mintz /* Handle bulletin board changes */ 148436558c3dSYuval Mintz qed_vf_read_bulletin(hwfn, &change); 148565ed2ffdSMintz, Yuval if (test_and_clear_bit(QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG, 148665ed2ffdSMintz, Yuval &hwfn->iov_task_flags)) 148765ed2ffdSMintz, Yuval change = 1; 148836558c3dSYuval Mintz if (change) 148936558c3dSYuval Mintz qed_handle_bulletin_change(hwfn); 149036558c3dSYuval Mintz 149136558c3dSYuval Mintz /* As VF is polling bulletin board, need to constantly re-schedule */ 149236558c3dSYuval Mintz queue_delayed_work(hwfn->iov_wq, &hwfn->iov_task, HZ); 149336558c3dSYuval Mintz } 1494