// SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2022 - 2024 Mucse Corporation. */ #include #include #include #include #include #include #include #include #include #include #ifdef NETIF_F_HW_VLAN_CTAG_TX #include #endif #include "rnpm.h" #include "rnpm_type.h" #include "rnpm_sriov.h" #ifdef CONFIG_PCI_IOV static int __rnpm_enable_sriov(struct rnpm_adapter *adapter) { struct rnpm_hw *hw = &adapter->hw; int num_vf_macvlans, i; struct vf_macvlans *mv_list; u32 v; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); adapter->flags |= RNPM_FLAG_SRIOV_ENABLED; e_info(probe, "SR-IOV enabled with %d VFs\n", adapter->num_vfs); dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); /* Enable VMDq flag so device will be set in VM mode */ adapter->flags |= RNPM_FLAG_VMDQ_ENABLED; if (!adapter->ring_feature[RING_F_VMDQ].limit) adapter->ring_feature[RING_F_VMDQ].limit = 1; adapter->ring_feature[RING_F_VMDQ].offset = adapter->num_vfs; num_vf_macvlans = hw->mac.num_rar_entries - (RNPM_MAX_PF_MACVLANS + 1 + adapter->num_vfs); adapter->mv_list = mv_list = kcalloc( num_vf_macvlans, sizeof(struct vf_macvlans), GFP_KERNEL); if (mv_list) { /* Initialize list of VF macvlans */ INIT_LIST_HEAD(&adapter->vf_mvs.l); for (i = 0; i < num_vf_macvlans; i++) { mv_list->vf = -1; mv_list->free = true; mv_list->rar_entry = hw->mac.num_rar_entries - (i + adapter->num_vfs + 1); list_add(&mv_list->l, &adapter->vf_mvs.l); mv_list++; } } /* Initialize default switching mode VEB */ wr32(hw, RNPM_DMA_CONFIG, rd32(hw, RNPM_DMA_CONFIG) & (~DMA_VEB_BYPASS)); adapter->flags2 |= RNPM_FLAG2_BRIDGE_MODE_VEB; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); //ETH_BYPASS rd32(hw, RNPM_ETH_BYPASS); wr32(hw, RNPM_HOST_FILTER_EN, 1); wr32(hw, RNPM_REDIR_EN, 1); v = rd32(hw, RNPM_MRQC_IOV_EN); v |= RNPM_IOV_ENABLED; wr32(hw, RNPM_MRQC_IOV_EN, v); wr32(hw, RNPM_ETH_DMAC_FCTRL, rd32(hw, RNPM_ETH_DMAC_FCTRL) | RNPM_FCTRL_BROADCASE_BYPASS); //wr32(hw, RNPM_ETH_DMAC_MCSTCTRL, v); /* If call to enable VFs succeeded then allocate memory * for per VF control structures. */ adapter->vfinfo = kcalloc(adapter->num_vfs, sizeof(struct vf_data_storage), GFP_KERNEL); if (adapter->vfinfo) { /* limit trafffic classes based on VFs enabled */ /* TODO analyze VF need support pfc or traffic classes */ /* We do not support RSS w/ SR-IOV */ adapter->ring_feature[RING_F_RSS].limit = 2; /* Disable RSC when in SR-IOV mode */ adapter->flags2 &= ~(RNPM_FLAG2_RSC_CAPABLE | RNPM_FLAG2_RSC_ENABLED); /* enable spoof checking for all VFs */ //for (i = 0; i < adapter->num_vfs; i++) //adapter->vfinfo[i].spoofchk_enabled = true; return 0; } dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); return -ENOMEM; } /* Note this function is called when the user wants to enable SR-IOV * VFs using the now deprecated module parameter */ void rnpm_enable_sriov(struct rnpm_adapter *adapter) { int pre_existing_vfs = 0; pre_existing_vfs = pci_num_vf(adapter->pdev); if (!pre_existing_vfs && !adapter->num_vfs) return; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); if (!pre_existing_vfs) dev_warn( &adapter->pdev->dev, "Enabling SR-IOV VFs using the module parameter is deprecated - please use the pci sysfs interface.\n"); dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); /* If there are pre-existing VFs then we have to force * use of that many - over ride any module parameter value. * This may result from the user unloading the PF driver * while VFs were assigned to guest VMs or because the VFs * have been created via the new PCI SR-IOV sysfs interface. */ if (pre_existing_vfs) { adapter->num_vfs = pre_existing_vfs; dev_warn( &adapter->pdev->dev, "Virtual Functions already enabled for this device - Please reload all VF drivers to avoid spoofed packet errors\n"); } else { int err; /* The n10 supports up to 64 VFs per physical function * but this implementation limits allocation to 127 so that * basic networking resources are still available to the * physical function. If the user requests greater than * 64 VFs then it is an error - reset to default of zero. */ adapter->num_vfs = min_t(unsigned int, adapter->num_vfs, RNPM_MAX_VF_CNT - 1); err = pci_enable_sriov(adapter->pdev, adapter->num_vfs); if (err) { e_err(probe, "Failed to enable PCI sriov: %d\n", err); adapter->num_vfs = 0; return; } dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); } dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); if (!__rnpm_enable_sriov(adapter)) return; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); /* If we have gotten to this point then there is no memory available * to manage the VF devices - print message and bail. */ e_err(probe, "Unable to allocate memory for VF Data Storage\n"); rnpm_disable_sriov(adapter); } static bool rnpm_vfs_are_assigned(struct rnpm_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct pci_dev *vfdev; int dev_id; unsigned int vendor_id; if (adapter->pdev->device == RNPM_DEV_ID_N10_PF0) { vendor_id = 0x1dab; dev_id = RNPM_DEV_ID_N10_PF0_VF; } else if (adapter->pdev->device == RNPM_DEV_ID_N10_PF1) { vendor_id = 0x1dab; dev_id = RNPM_DEV_ID_N10_PF1_VF; } else if (adapter->pdev->device == RNPM_DEV_ID_N10_PF0_N) { vendor_id = PCI_VENDOR_ID_MUCSE; dev_id = RNPM_DEV_ID_N10_PF0_VF_N; } else { vendor_id = PCI_VENDOR_ID_MUCSE; dev_id = RNPM_DEV_ID_N10_PF1_VF_N; } /* loop through all the VFs to see if we own any that are assigned */ vfdev = pci_get_device(vendor_id, dev_id, NULL); while (vfdev) { /* if we don't own it we don't care */ if (vfdev->is_virtfn && vfdev->physfn == pdev) { /* if it is assigned we cannot release it */ if (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) return true; } vfdev = pci_get_device(vendor_id, dev_id, vfdev); } return false; } #endif /* #ifdef CONFIG_PCI_IOV */ int rnpm_disable_sriov(struct rnpm_adapter *adapter) { struct rnpm_hw *hw = &adapter->hw; u32 v; int rss; // disable v = rd32(hw, RNPM_MRQC_IOV_EN); v &= ~(RNPM_IOV_ENABLED); wr32(hw, RNPM_MRQC_IOV_EN, v); /* set num VFs to 0 to prevent access to vfinfo */ adapter->num_vfs = 0; /* free VF control structures */ kfree(adapter->vfinfo); adapter->vfinfo = NULL; /* free macvlan list */ kfree(adapter->mv_list); adapter->mv_list = NULL; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); /* if SR-IOV is already disabled then there is nothing to do */ if (!(adapter->flags & RNPM_FLAG_SRIOV_ENABLED)) return 0; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); #ifdef CONFIG_PCI_IOV /* If our VFs are assigned we cannot shut down SR-IOV * without causing issues, so just leave the hardware * available but disabled */ if (rnpm_vfs_are_assigned(adapter)) { e_dev_warn( "Unloading driver while VFs are assigned - VFs will not be deallocated\n"); return -EPERM; } /* disable iov and allow time for transactions to clear */ pci_disable_sriov(adapter->pdev); #endif dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); /* set default pool back to 0 */ /* Disable VMDq flag so device will be set in VM mode */ if (adapter->ring_feature[RING_F_VMDQ].limit == 1) adapter->flags &= ~RNPM_FLAG_VMDQ_ENABLED; adapter->ring_feature[RING_F_VMDQ].offset = 0; rss = min_t(int, adapter->max_ring_pair_counts, num_online_cpus()); adapter->ring_feature[RING_F_RSS].limit = rss; /* take a breather then clean up driver data */ msleep(100); adapter->flags &= ~RNPM_FLAG_SRIOV_ENABLED; dbg("%s:%d flags:0x%x\n", __func__, __LINE__, adapter->flags); return 0; } static int rnpm_pci_sriov_enable(struct pci_dev *dev, int num_vfs) { #ifdef CONFIG_PCI_IOV // todo fix me struct rnpm_adapter *adapter = pci_get_drvdata(dev); //struct rnpm_pf_adapter *pf_adapter = pci_get_drvdata(pdev); int err = 0; int i; int pre_existing_vfs = pci_num_vf(dev); if (adapter->flags & RNPM_FLAG_MUTIPORT_ENABLED) { err = -EACCES; goto err_out; } if (pre_existing_vfs && pre_existing_vfs != num_vfs) err = rnpm_disable_sriov(adapter); else if (pre_existing_vfs && pre_existing_vfs == num_vfs) goto out; if (err) goto err_out; /* While the SR-IOV capability structure reports total VFs to be * 64 we limit the actual number that can be allocated to 63 so * that some transmit/receive resources can be reserved to the * PF. The PCI bus driver already checks for other values out of * range. */ if (num_vfs > (RNPM_MAX_VF_FUNCTIONS - 1)) { err = -EPERM; goto err_out; } adapter->num_vfs = num_vfs; err = __rnpm_enable_sriov(adapter); if (err) goto err_out; for (i = 0; i < adapter->num_vfs; i++) rnpm_vf_configuration(dev, (i | 0x10000000)); err = pci_enable_sriov(dev, num_vfs); if (err) { e_dev_warn("Failed to enable PCI sriov: %d\n", err); goto err_out; } dbg("flags:0x%x\n", adapter->flags); rnpm_sriov_reinit(adapter); out: return num_vfs; err_out: return err; #endif return 0; } static int rnpm_pci_sriov_disable(struct pci_dev *dev) { struct rnpm_adapter *adapter = pci_get_drvdata(dev); int err; u32 current_flags = adapter->flags; err = rnpm_disable_sriov(adapter); /* Only reinit if no error and state changed */ if (!err && current_flags != adapter->flags) { /* rnpm_disable_sriov() doesn't clear VMDQ flag */ adapter->flags &= ~RNPM_FLAG_VMDQ_ENABLED; #ifdef CONFIG_PCI_IOV rnpm_sriov_reinit(adapter); #endif } return err; } static int rnpm_set_vf_multicasts(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { int entries = (msgbuf[0] & RNPM_VT_MSGINFO_MASK) >> RNPM_VT_MSGINFO_SHIFT; u16 *hash_list = (u16 *)&msgbuf[1]; struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; struct rnpm_hw *hw = &adapter->hw; int i; u32 vector_bit; u32 vector_reg; u32 mta_reg; /* only so many hash values supported */ entries = min(entries, RNPM_MAX_VF_MC_ENTRIES); // enable multicast and unicast filter mta_reg = rd32(hw, RNPM_ETH_DMAC_MCSTCTRL); wr32(hw, RNPM_ETH_DMAC_MCSTCTRL, mta_reg | RNPM_MCSTCTRL_MULTICASE_TBL_EN | RNPM_MCSTCTRL_UNICASE_TBL_EN); /* salt away the number of multi cast addresses assigned * to this VF for later use to restore when the PF multi cast * list changes */ vfinfo->num_vf_mc_hashes = entries; /* VFs are limited to using the MTA hash table for their multicast * addresses */ for (i = 0; i < entries; i++) vfinfo->vf_mc_hashes[i] = hash_list[i]; for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F; vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F; mta_reg = rd32(hw, RNPM_ETH_MUTICAST_HASH_TABLE(vector_reg)); mta_reg |= (1 << vector_bit); wr32(hw, RNPM_ETH_MUTICAST_HASH_TABLE(vector_reg), mta_reg); } return 0; } static void rnpm_restore_vf_macvlans(struct rnpm_adapter *adapter) { struct rnpm_hw *hw = &adapter->hw; struct list_head *pos; struct vf_macvlans *entry; list_for_each(pos, &adapter->vf_mvs.l) { entry = list_entry(pos, struct vf_macvlans, l); if (!entry->free) { hw_dbg(hw, " vf:%d MACVLAN: RAR[%d] <= %pM\n", entry->vf, entry->rar_entry, entry->vf_macvlan); hw->mac.ops.set_rar(hw, entry->rar_entry, entry->vf_macvlan, entry->vf, RNPM_RAH_AV); } } } void rnpm_restore_vf_multicasts(struct rnpm_adapter *adapter) { struct rnpm_hw *hw = &adapter->hw; struct vf_data_storage *vfinfo; int i, j; u32 vector_bit; u32 vector_reg; u32 mta_reg; hw_dbg(hw, "%s num_vf:%d\n", __func__, adapter->num_vfs); for (i = 0; i < adapter->num_vfs; i++) { vfinfo = &adapter->vfinfo[i]; for (j = 0; j < vfinfo->num_vf_mc_hashes; j++) { hw->addr_ctrl.mta_in_use++; vector_reg = (vfinfo->vf_mc_hashes[j] >> 5) & 0x7F; vector_bit = vfinfo->vf_mc_hashes[j] & 0x1F; mta_reg = rd32( hw, RNPM_ETH_MUTICAST_HASH_TABLE(vector_reg)); mta_reg |= (1 << vector_bit); wr32(hw, RNPM_ETH_MUTICAST_HASH_TABLE(vector_reg), mta_reg); hw_dbg(hw, " VF:%2d mc_hash:0x%x, MTA[%2d][%2d]=1\n", i, vfinfo->vf_mc_hashes[j], vector_reg, vector_bit); } } /* Restore any VF macvlans */ rnpm_restore_vf_macvlans(adapter); } static int rnpm_set_vf_vlan(struct rnpm_adapter *adapter, int add, int vid, u32 vf) { /* VLAN 0 is a special case, don't allow it to be removed */ if (!vid && !add) return 0; return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); } static s32 rnpm_set_vf_lpe(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { return 0; } static void __maybe_unused rnpm_set_vmolr(struct rnpm_hw *hw, u32 vf, bool aupe) { } static void __maybe_unused rnpm_clear_vmvir(struct rnpm_adapter *adapter, u32 vf) { // struct rnpm_hw *hw = &adapter->hw; //RNPM_WRITE_REG(hw, RNPM_VMVIR(vf), 0); } static inline void rnpm_vf_reset_event(struct rnpm_adapter *adapter, u32 vf) { struct rnpm_hw *hw = &adapter->hw; struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; int rar_entry = hw->mac.num_rar_entries - (vf + 1); u8 num_tcs = netdev_get_num_tc(adapter->netdev); /* add PF assigned VLAN or VLAN 0 */ // rnpm_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf); /* reset offloads to defaults */ // rnpm_set_vmolr(hw, vf, !vfinfo->pf_vlan); /* set outgoing tags for VFs */ if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) { // rnpm_clear_vmvir(adapter, vf); } else { if (vfinfo->pf_qos || !num_tcs) rnpm_set_vmvir(adapter, vfinfo->pf_vlan, vfinfo->pf_qos, vf); else rnpm_set_vmvir(adapter, vfinfo->pf_vlan, adapter->default_up, vf); //if (vfinfo->spoofchk_enabled) // hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); } /* reset multicast table array for vf */ adapter->vfinfo[vf].num_vf_mc_hashes = 0; /* Flush and reset the mta with the new values */ rnpm_set_rx_mode(adapter->netdev); /* clear this rar_entry */ hw->mac.ops.clear_rar(hw, rar_entry); /* reset VF api back to unknown */ adapter->vfinfo[vf].vf_api = 0; } static int rnpm_set_vf_mac(struct rnpm_adapter *adapter, int vf, unsigned char *mac_addr) { struct rnpm_hw *hw = &adapter->hw; /* this rar_entry may be cofict with mac vlan with pf */ int rar_entry = hw->mac.num_rar_entries - (vf + 1); int vf_ring = vf * 2; memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, 6); hw->mac.ops.set_rar(hw, rar_entry, mac_addr, vf_ring / 2, RNPM_RAH_AV); return 0; } static int rnpm_set_vf_macvlan(struct rnpm_adapter *adapter, int vf, int index, unsigned char *mac_addr) { struct rnpm_hw *hw = &adapter->hw; struct list_head *pos; struct vf_macvlans *entry; if (index <= 1) { list_for_each(pos, &adapter->vf_mvs.l) { entry = list_entry(pos, struct vf_macvlans, l); if (entry->vf == vf) { entry->vf = -1; entry->free = true; entry->is_macvlan = false; hw->mac.ops.clear_rar(hw, entry->rar_entry); } } } /* If index was zero then we were asked to clear the uc list * for the VF. We're done. */ if (!index) return 0; entry = NULL; list_for_each(pos, &adapter->vf_mvs.l) { entry = list_entry(pos, struct vf_macvlans, l); if (entry->free) break; } /* If we traversed the entire list and didn't find a free entry * then we're out of space on the RAR table. Also entry may * be NULL because the original memory allocation for the list * failed, which is not fatal but does mean we can't support * VF requests for MACVLAN because we couldn't allocate * memory for the list management required. */ if (!entry || !entry->free) return -ENOSPC; entry->free = false; entry->is_macvlan = true; entry->vf = vf; memcpy(entry->vf_macvlan, mac_addr, ETH_ALEN); hw->mac.ops.set_rar(hw, entry->rar_entry, mac_addr, vf, RNPM_RAH_AV); return 0; } int rnpm_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) { unsigned char vf_mac_addr[6]; struct rnpm_adapter *adapter = pci_get_drvdata(pdev); unsigned int vfn = (event_mask & 0x3f); bool enable = ((event_mask & 0x10000000U) != 0); if (enable) { eth_zero_addr(vf_mac_addr); memcpy(vf_mac_addr, adapter->hw.mac.perm_addr, 6); vf_mac_addr[5] = vf_mac_addr[5] + (0x80 | vfn); memcpy(adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr, 6); } return 0; } static int rnpm_vf_reset_msg(struct rnpm_adapter *adapter, u32 vf) { struct rnpm_hw *hw = &adapter->hw; unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; u32 msgbuf[5]; // u32 reg_offset, vf_shift; u8 *addr = (u8 *)(&msgbuf[1]); e_info(probe, "VF Reset msg received from vf %d. cmd:0x%x\n", vf, msgbuf[0]); /* reset the filters for the device */ rnpm_vf_reset_event(adapter, vf); /* set vf mac address */ if (!is_zero_ether_addr(vf_mac)) rnpm_set_vf_mac(adapter, vf, vf_mac); /* enable VF mailbox for further messages */ adapter->vfinfo[vf].clear_to_send = true; /* Enable counting of spoofed packets in the SSVPC register */ /* reply to reset with ack and vf mac address */ msgbuf[0] = RNPM_VF_RESET; if (!is_zero_ether_addr(vf_mac)) { msgbuf[0] |= RNPM_VT_MSGTYPE_ACK; memcpy(addr, vf_mac, ETH_ALEN); } else { msgbuf[0] |= RNPM_VT_MSGTYPE_NACK; dev_warn( &adapter->pdev->dev, "VF %d has no MAC address assigned, you may have to assign one manually\n", vf); } /* Piggyback the multicast filter type so VF can compute the * correct vectors */ msgbuf[RNPM_VF_MC_TYPE_WORD] = 0; /* setup link status , pause mode, ft padding mode */ /* link status */ // to-do /* pause mode */ msgbuf[RNPM_VF_MC_TYPE_WORD] |= (0xff & hw->fc.current_mode) << 16; if (adapter->priv_flags & RNPM_PRIV_FLAG_PCIE_CACHE_ALIGN_PATCH) msgbuf[RNPM_VF_MC_TYPE_WORD] |= (0x01 << 8); else msgbuf[RNPM_VF_MC_TYPE_WORD] |= (0x00 << 8); /* mc_type */ msgbuf[RNPM_VF_MC_TYPE_WORD] |= rd32(hw, RNPM_ETH_DMAC_MCSTCTRL) & 0x3; msgbuf[RNPM_VF_DMA_VERSION_WORD] = rd32(hw, RNPM_DMA_VERSION); ; /* now vf maybe has no irq handler if it is the first reset*/ rnpm_write_mbx(hw, msgbuf, RNPM_VF_PERMADDR_MSG_LEN, vf); return 0; } static int rnpm_set_vf_mac_addr(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { u8 *new_mac = ((u8 *)(&msgbuf[1])); if (!is_valid_ether_addr(new_mac)) { e_warn(drv, "VF %d attempted to set invalid mac\n", vf); return -1; } if (adapter->vfinfo[vf].pf_set_mac && memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac, ETH_ALEN)) { e_warn(drv, "VF %d attempted to override administratively set MAC address\n" "Reload the VF driver to resume operations\n", vf); return -1; } return rnpm_set_vf_mac(adapter, vf, new_mac) < 0; } static int rnpm_set_vf_vlan_msg(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { // struct rnpm_hw *hw = &adapter->hw; int add = ((msgbuf[0] & RNPM_VT_MSGINFO_MASK) >> RNPM_VT_MSGINFO_SHIFT); int vid = (msgbuf[1] & RNPM_VLVF_VLANID_MASK); int err; //u8 tcs = netdev_get_num_tc(adapter->netdev); if (adapter->vfinfo[vf].pf_vlan) { e_warn(drv, "VF %d attempted to override administratively set VLAN configuration\n" "Reload the VF driver to resume operations\n", vf); return -1; } if (add) adapter->vfinfo[vf].vlan_count++; else if (adapter->vfinfo[vf].vlan_count) adapter->vfinfo[vf].vlan_count--; err = rnpm_set_vf_vlan(adapter, add, vid, vf); return err; } static int rnpm_set_vf_vlan_strip_msg(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { struct rnpm_hw *hw = &adapter->hw; int vlan_strip_on = !!(msgbuf[1] >> 31); int queue_cnt = msgbuf[1] & 0xffff; int err = 0, i; vf_dbg("strip_on:%d queeu_cnt:%d, %d %d\n", vlan_strip_on, queue_cnt, msgbuf[2], msgbuf[3]); for (i = 0; i < queue_cnt; i++) { if (vlan_strip_on) hw_queue_strip_rx_vlan(hw, msgbuf[2 + i], true); else hw_queue_strip_rx_vlan(hw, msgbuf[2 + i], false); } return err; } static int rnpm_set_vf_macvlan_msg(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { u8 *new_mac = ((u8 *)(&msgbuf[1])); int index = (msgbuf[0] & RNPM_VT_MSGINFO_MASK) >> RNPM_VT_MSGINFO_SHIFT; int err; if (adapter->vfinfo[vf].pf_set_mac && index > 0) { e_warn(drv, "VF %d requested MACVLAN filter but is administratively denied\n", vf); return -1; } /* An non-zero index indicates the VF is setting a filter */ if (index) { if (!is_valid_ether_addr(new_mac)) { e_warn(drv, "VF %d attempted to set invalid mac\n", vf); return -1; } } err = rnpm_set_vf_macvlan(adapter, vf, index, new_mac); if (err == -ENOSPC) e_warn(drv, "VF %d has requested a MACVLAN filter but there is no space for it\n", vf); return err < 0; return 0; } static int rnpm_negotiate_vf_api(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { adapter->vfinfo[vf].vf_api = 0; return 0; } static int rnpm_get_vf_reg(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { // struct net_device *dev = adapter->netdev; u32 reg = msgbuf[1]; if (reg == 0) { //FIXME check regs return -1; } msgbuf[1] = rd32(&adapter->hw, reg); return 0; } static int rnpm_get_vf_queues(struct rnpm_adapter *adapter, u32 *msgbuf, u32 vf) { struct net_device *dev = adapter->netdev; // struct rnpm_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; unsigned int default_tc = 0; u8 num_tcs = netdev_get_num_tc(dev); /* verify the PF is supporting the correct APIs */ /* only allow 1 Tx queue for bandwidth limiting */ msgbuf[RNPM_VF_TX_QUEUES] = 1; msgbuf[RNPM_VF_RX_QUEUES] = 1; /* if TCs > 1 determine which TC belongs to default user priority */ if (num_tcs > 1) default_tc = netdev_get_prio_tc_map(dev, adapter->default_up); /* notify VF of need for VLAN tag stripping, and correct queue */ if (num_tcs) msgbuf[RNPM_VF_TRANS_VLAN] = num_tcs; else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos) msgbuf[RNPM_VF_TRANS_VLAN] = 1; else msgbuf[RNPM_VF_TRANS_VLAN] = 0; /* notify VF of default queue */ msgbuf[RNPM_VF_DEF_QUEUE] = default_tc; return 0; } static int __maybe_unused rnpm_rcv_msg_from_vf(struct rnpm_adapter *adapter, u32 vf) { u32 mbx_size = RNPM_VFMAILBOX_SIZE; u32 msgbuf[RNPM_VFMAILBOX_SIZE]; struct rnpm_hw *hw = &adapter->hw; s32 retval; retval = rnpm_read_mbx(hw, msgbuf, mbx_size, vf); if (retval) { pr_err("Error receiving message from VF\n"); return retval; } vf_dbg("msg[0]=0x%08x\n", msgbuf[0]); /* this is a message we already processed, do nothing */ if (msgbuf[0] & (RNPM_VT_MSGTYPE_ACK | RNPM_VT_MSGTYPE_NACK)) return retval; /* this is a vf reset irq */ if (msgbuf[0] == RNPM_VF_RESET) return rnpm_vf_reset_msg(adapter, vf); /* until the vf completes a virtual function reset it should not be * allowed to start any configuration. */ if (!adapter->vfinfo[vf].clear_to_send) { msgbuf[0] |= RNPM_VT_MSGTYPE_NACK; rnpm_write_mbx(hw, msgbuf, 1, vf); return retval; } switch ((msgbuf[0] & 0xFFFF)) { case RNPM_VF_SET_MAC_ADDR: retval = rnpm_set_vf_mac_addr(adapter, msgbuf, vf); break; case RNPM_VF_SET_MULTICAST: retval = rnpm_set_vf_multicasts(adapter, msgbuf, vf); break; case RNPM_VF_SET_VLAN: retval = rnpm_set_vf_vlan_msg(adapter, msgbuf, vf); break; case RNPM_VF_SET_VLAN_STRIP: retval = rnpm_set_vf_vlan_strip_msg(adapter, msgbuf, vf); break; case RNPM_VF_SET_LPE: retval = rnpm_set_vf_lpe(adapter, msgbuf, vf); break; case RNPM_VF_SET_MACVLAN: retval = rnpm_set_vf_macvlan_msg(adapter, msgbuf, vf); break; case RNPM_VF_API_NEGOTIATE: retval = rnpm_negotiate_vf_api(adapter, msgbuf, vf); break; case RNPM_VF_GET_QUEUES: retval = rnpm_get_vf_queues(adapter, msgbuf, vf); break; case RNPM_VF_REG_RD: retval = rnpm_get_vf_reg(adapter, msgbuf, vf); break; case RNPM_PF_REMOVE: //dbg("vf %d down\n", vf); adapter->vfinfo[vf].clear_to_send = false; retval = 1; break; default: e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); retval = RNPM_ERR_MBX; break; } /* notify the VF of the results of what it sent us */ if (retval) msgbuf[0] |= RNPM_VT_MSGTYPE_NACK; else msgbuf[0] |= RNPM_VT_MSGTYPE_ACK; msgbuf[0] |= RNPM_VT_MSGTYPE_CTS; rnpm_write_mbx(hw, msgbuf, mbx_size, vf); return retval; } static void __maybe_unused rnpm_rcv_ack_from_vf(struct rnpm_adapter *adapter, u32 vf) { struct rnpm_hw *hw = &adapter->hw; u32 msg = RNPM_VT_MSGTYPE_NACK; /* if device isn't clear to send it shouldn't be reading either */ if (!adapter->vfinfo[vf].clear_to_send) rnpm_write_mbx(hw, &msg, 1, vf); } void rnpm_msg_task(struct rnpm_pf_adapter *pf_adapter) { rnpm_fw_msg_handler(pf_adapter); } /* try to send mailbox to all active vf */ void rnpm_msg_post_status(struct rnpm_adapter *adapter, enum PF_STATUS status) { u32 msgbuf[RNPM_VFMAILBOX_SIZE]; struct rnpm_hw *hw = &adapter->hw; struct rnpm_mbx_info *mbx = &hw->mbx; u32 vf; for (vf = 0; vf < adapter->num_vfs; vf++) { if (adapter->vfinfo[vf].clear_to_send) { dbg("now send msg to vf %d\n", vf); switch (status) { case PF_FCS_STATUS: msgbuf[0] = RNPM_PF_SET_FCS; if (adapter->netdev->features & NETIF_F_RXFCS) msgbuf[1] = 1; else msgbuf[1] = 0; break; case PF_PAUSE_STATUS: msgbuf[0] = RNPM_PF_SET_PAUSE; msgbuf[1] = hw->fc.requested_mode; break; case PF_FT_PADDING_STATUS: msgbuf[0] = RNPM_PF_SET_FT_PADDING; if (adapter->priv_flags & RNPM_PRIV_FLAG_PCIE_CACHE_ALIGN_PATCH) { msgbuf[1] = 1; } else { msgbuf[1] = 0; } break; default: break; } //dbg("msg 0 is %x\n", msgbuf[0]); //dbg("msg 1 is %x\n", msgbuf[1]); // mbx->ops.write(hw, msgbuf, 2, vf); } } } void rnpm_disable_tx_rx(struct rnpm_adapter *adapter) { // struct rnpm_hw *hw = &adapter->hw; /* disable transmit and receive for all vfs */ } void rnpm_ping_all_vfs(struct rnpm_adapter *adapter) { struct rnpm_hw *hw = &adapter->hw; u32 ping; int i; for (i = 0; i < adapter->num_vfs; i++) { ping = RNPM_PF_CONTROL_PRING_MSG; /* only send to active vf */ //if (adapter->vfinfo[i].clear_to_send) { ping |= RNPM_VT_MSGTYPE_CTS; rnpm_write_mbx(hw, &ping, 1, i); // } } } int rnpm_get_vf_ringnum(int vf, int num) { //fix me if ring alloc reset return (vf * 2 + num); } int rnpm_setup_ring_maxrate(struct rnpm_adapter *adapter, int ring, u64 max_rate) { u64 x, y, result; #define RNPM_SAMPING_1SEC_INTERNAL (180000000) /* set hardware samping internal 1S */ rnpm_wr_reg(adapter->hw.hw_addr + RNPM_DMA_REG_TX_FLOW_CTRL_TM(ring), RNPM_SAMPING_1SEC_INTERNAL / 10); x = max_rate; y = do_div(x, 10); result = x; result = x * 3; rnpm_wr_reg(adapter->hw.hw_addr + RNPM_DMA_REG_TX_FLOW_CTRL_TH(ring), result); return 0; } #ifdef HAVE_NDO_SET_VF_MIN_MAX_TX_RATE int rnpm_ndo_set_vf_bw(struct net_device *netdev, int vf, int __always_unused min_tx_rate, int max_tx_rate) #else int rnpm_ndo_set_vf_bw(struct net_device *netdev, int vf, int max_tx_rate) #endif /* HAVE_NDO_SET_VF_MIN_MAX_TX_RATE */ { struct rnpm_adapter *adapter = netdev_priv(netdev); /* limit vf ring rate */ int ring_max_rate; int vf_ring; int link_speed; if (vf >= RNPM_MAX_VF_CNT - 1) return -EINVAL; // todo link_speed = 10000; //link_speed = rnpm_link_mbps(adapter); /* rate limit cannot be less than 10Mbs or greater than link speed */ if (max_tx_rate && ((max_tx_rate <= 10) || (max_tx_rate > link_speed))) return -EINVAL; ring_max_rate = max_tx_rate / PF_RING_CNT_WHEN_IOV_ENABLED; vf_ring = rnpm_get_vf_ringnum(vf, 0); rnpm_setup_ring_maxrate(adapter, vf_ring, ring_max_rate); vf_ring = rnpm_get_vf_ringnum(vf, 1); rnpm_setup_ring_maxrate(adapter, vf_ring, ring_max_rate); return 0; } int rnpm_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) { struct rnpm_adapter *adapter = netdev_priv(netdev); if (!is_valid_ether_addr(mac) || (vf >= adapter->num_vfs)) return -EINVAL; adapter->vfinfo[vf].pf_set_mac = true; dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf); if (test_bit(__RNPM_DOWN, &adapter->state)) { dev_warn( &adapter->pdev->dev, "The VF MAC address has been set but the PFis not up.\n"); } return rnpm_set_vf_mac(adapter, vf, mac); } static int __maybe_unused rnpm_link_mbps(struct rnpm_adapter *adapter) { switch (adapter->link_speed) { case RNPM_LINK_SPEED_100_FULL: return 100; case RNPM_LINK_SPEED_1GB_FULL: return 1000; case RNPM_LINK_SPEED_10GB_FULL: return 10000; default: return 0; } } int rnpm_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) { struct rnpm_adapter *adapter = netdev_priv(netdev); if (vf >= adapter->num_vfs) return -EINVAL; ivi->vf = vf; memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN); //ivi->tx_rate = adapter->vfinfo[vf].tx_rate; ivi->vlan = adapter->vfinfo[vf].pf_vlan; ivi->qos = adapter->vfinfo[vf].pf_qos; #ifdef HAVE_VF_SPOOFCHK_CONFIGURE ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled; #endif return 0; } int rnpm_pci_sriov_configure(struct pci_dev *dev, int num_vfs) { vf_dbg("\n\n !!!! %s:%d num_vfs:%d\n", __func__, __LINE__, num_vfs); if (num_vfs == 0) return rnpm_pci_sriov_disable(dev); else return rnpm_pci_sriov_enable(dev, num_vfs); }