1837f08fdSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 2837f08fdSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 3837f08fdSAnirudh Venkataramanan 4837f08fdSAnirudh Venkataramanan /* Intel(R) Ethernet Connection E800 Series Linux Driver */ 5837f08fdSAnirudh Venkataramanan 6837f08fdSAnirudh Venkataramanan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7837f08fdSAnirudh Venkataramanan 8837f08fdSAnirudh Venkataramanan #include "ice.h" 945d3d428SAnirudh Venkataramanan #include "ice_lib.h" 10837f08fdSAnirudh Venkataramanan 119ea47d81SAnirudh Venkataramanan #define DRV_VERSION "0.7.1-k" 12837f08fdSAnirudh Venkataramanan #define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver" 13fcea6f3dSAnirudh Venkataramanan const char ice_drv_ver[] = DRV_VERSION; 14837f08fdSAnirudh Venkataramanan static const char ice_driver_string[] = DRV_SUMMARY; 15837f08fdSAnirudh Venkataramanan static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation."; 16837f08fdSAnirudh Venkataramanan 17837f08fdSAnirudh Venkataramanan MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); 18837f08fdSAnirudh Venkataramanan MODULE_DESCRIPTION(DRV_SUMMARY); 1998674ebeSJesse Brandeburg MODULE_LICENSE("GPL v2"); 20837f08fdSAnirudh Venkataramanan MODULE_VERSION(DRV_VERSION); 21837f08fdSAnirudh Venkataramanan 22837f08fdSAnirudh Venkataramanan static int debug = -1; 23837f08fdSAnirudh Venkataramanan module_param(debug, int, 0644); 247ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 257ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXXXXX)"); 267ec59eeaSAnirudh Venkataramanan #else 277ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)"); 287ec59eeaSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 29837f08fdSAnirudh Venkataramanan 30940b61afSAnirudh Venkataramanan static struct workqueue_struct *ice_wq; 31cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops; 32940b61afSAnirudh Venkataramanan 330b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf); 340b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf); 3528c2a645SAnirudh Venkataramanan 360f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf); 37fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi); 38fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf); 393a858ba3SAnirudh Venkataramanan 403a858ba3SAnirudh Venkataramanan /** 41b3969fd7SSudheer Mogilappagari * ice_get_tx_pending - returns number of Tx descriptors not processed 42b3969fd7SSudheer Mogilappagari * @ring: the ring of descriptors 43b3969fd7SSudheer Mogilappagari */ 44b3969fd7SSudheer Mogilappagari static u32 ice_get_tx_pending(struct ice_ring *ring) 45b3969fd7SSudheer Mogilappagari { 46b3969fd7SSudheer Mogilappagari u32 head, tail; 47b3969fd7SSudheer Mogilappagari 48b3969fd7SSudheer Mogilappagari head = ring->next_to_clean; 49b3969fd7SSudheer Mogilappagari tail = readl(ring->tail); 50b3969fd7SSudheer Mogilappagari 51b3969fd7SSudheer Mogilappagari if (head != tail) 52b3969fd7SSudheer Mogilappagari return (head < tail) ? 53b3969fd7SSudheer Mogilappagari tail - head : (tail + ring->count - head); 54b3969fd7SSudheer Mogilappagari return 0; 55b3969fd7SSudheer Mogilappagari } 56b3969fd7SSudheer Mogilappagari 57b3969fd7SSudheer Mogilappagari /** 58b3969fd7SSudheer Mogilappagari * ice_check_for_hang_subtask - check for and recover hung queues 59b3969fd7SSudheer Mogilappagari * @pf: pointer to PF struct 60b3969fd7SSudheer Mogilappagari */ 61b3969fd7SSudheer Mogilappagari static void ice_check_for_hang_subtask(struct ice_pf *pf) 62b3969fd7SSudheer Mogilappagari { 63b3969fd7SSudheer Mogilappagari struct ice_vsi *vsi = NULL; 64b3969fd7SSudheer Mogilappagari unsigned int i; 65b3969fd7SSudheer Mogilappagari u32 v, v_idx; 66b3969fd7SSudheer Mogilappagari int packets; 67b3969fd7SSudheer Mogilappagari 68b3969fd7SSudheer Mogilappagari ice_for_each_vsi(pf, v) 69b3969fd7SSudheer Mogilappagari if (pf->vsi[v] && pf->vsi[v]->type == ICE_VSI_PF) { 70b3969fd7SSudheer Mogilappagari vsi = pf->vsi[v]; 71b3969fd7SSudheer Mogilappagari break; 72b3969fd7SSudheer Mogilappagari } 73b3969fd7SSudheer Mogilappagari 74b3969fd7SSudheer Mogilappagari if (!vsi || test_bit(__ICE_DOWN, vsi->state)) 75b3969fd7SSudheer Mogilappagari return; 76b3969fd7SSudheer Mogilappagari 77b3969fd7SSudheer Mogilappagari if (!(vsi->netdev && netif_carrier_ok(vsi->netdev))) 78b3969fd7SSudheer Mogilappagari return; 79b3969fd7SSudheer Mogilappagari 80b3969fd7SSudheer Mogilappagari for (i = 0; i < vsi->num_txq; i++) { 81b3969fd7SSudheer Mogilappagari struct ice_ring *tx_ring = vsi->tx_rings[i]; 82b3969fd7SSudheer Mogilappagari 83b3969fd7SSudheer Mogilappagari if (tx_ring && tx_ring->desc) { 84b3969fd7SSudheer Mogilappagari int itr = ICE_ITR_NONE; 85b3969fd7SSudheer Mogilappagari 86b3969fd7SSudheer Mogilappagari /* If packet counter has not changed the queue is 87b3969fd7SSudheer Mogilappagari * likely stalled, so force an interrupt for this 88b3969fd7SSudheer Mogilappagari * queue. 89b3969fd7SSudheer Mogilappagari * 90b3969fd7SSudheer Mogilappagari * prev_pkt would be negative if there was no 91b3969fd7SSudheer Mogilappagari * pending work. 92b3969fd7SSudheer Mogilappagari */ 93b3969fd7SSudheer Mogilappagari packets = tx_ring->stats.pkts & INT_MAX; 94b3969fd7SSudheer Mogilappagari if (tx_ring->tx_stats.prev_pkt == packets) { 95b3969fd7SSudheer Mogilappagari /* Trigger sw interrupt to revive the queue */ 96b3969fd7SSudheer Mogilappagari v_idx = tx_ring->q_vector->v_idx; 97b3969fd7SSudheer Mogilappagari wr32(&vsi->back->hw, 98eb0208ecSPreethi Banala GLINT_DYN_CTL(vsi->hw_base_vector + v_idx), 99b3969fd7SSudheer Mogilappagari (itr << GLINT_DYN_CTL_ITR_INDX_S) | 100b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL_SWINT_TRIG_M | 101b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL_INTENA_MSK_M); 102b3969fd7SSudheer Mogilappagari continue; 103b3969fd7SSudheer Mogilappagari } 104b3969fd7SSudheer Mogilappagari 105b3969fd7SSudheer Mogilappagari /* Memory barrier between read of packet count and call 106b3969fd7SSudheer Mogilappagari * to ice_get_tx_pending() 107b3969fd7SSudheer Mogilappagari */ 108b3969fd7SSudheer Mogilappagari smp_rmb(); 109b3969fd7SSudheer Mogilappagari tx_ring->tx_stats.prev_pkt = 110b3969fd7SSudheer Mogilappagari ice_get_tx_pending(tx_ring) ? packets : -1; 111b3969fd7SSudheer Mogilappagari } 112b3969fd7SSudheer Mogilappagari } 113b3969fd7SSudheer Mogilappagari } 114b3969fd7SSudheer Mogilappagari 115b3969fd7SSudheer Mogilappagari /** 116e94d4478SAnirudh Venkataramanan * ice_add_mac_to_sync_list - creates list of mac addresses to be synced 117e94d4478SAnirudh Venkataramanan * @netdev: the net device on which the sync is happening 118e94d4478SAnirudh Venkataramanan * @addr: mac address to sync 119e94d4478SAnirudh Venkataramanan * 120e94d4478SAnirudh Venkataramanan * This is a callback function which is called by the in kernel device sync 121e94d4478SAnirudh Venkataramanan * functions (like __dev_uc_sync, __dev_mc_sync, etc). This function only 122e94d4478SAnirudh Venkataramanan * populates the tmp_sync_list, which is later used by ice_add_mac to add the 123e94d4478SAnirudh Venkataramanan * mac filters from the hardware. 124e94d4478SAnirudh Venkataramanan */ 125e94d4478SAnirudh Venkataramanan static int ice_add_mac_to_sync_list(struct net_device *netdev, const u8 *addr) 126e94d4478SAnirudh Venkataramanan { 127e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 128e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 129e94d4478SAnirudh Venkataramanan 130e94d4478SAnirudh Venkataramanan if (ice_add_mac_to_list(vsi, &vsi->tmp_sync_list, addr)) 131e94d4478SAnirudh Venkataramanan return -EINVAL; 132e94d4478SAnirudh Venkataramanan 133e94d4478SAnirudh Venkataramanan return 0; 134e94d4478SAnirudh Venkataramanan } 135e94d4478SAnirudh Venkataramanan 136e94d4478SAnirudh Venkataramanan /** 137e94d4478SAnirudh Venkataramanan * ice_add_mac_to_unsync_list - creates list of mac addresses to be unsynced 138e94d4478SAnirudh Venkataramanan * @netdev: the net device on which the unsync is happening 139e94d4478SAnirudh Venkataramanan * @addr: mac address to unsync 140e94d4478SAnirudh Venkataramanan * 141e94d4478SAnirudh Venkataramanan * This is a callback function which is called by the in kernel device unsync 142e94d4478SAnirudh Venkataramanan * functions (like __dev_uc_unsync, __dev_mc_unsync, etc). This function only 143e94d4478SAnirudh Venkataramanan * populates the tmp_unsync_list, which is later used by ice_remove_mac to 144e94d4478SAnirudh Venkataramanan * delete the mac filters from the hardware. 145e94d4478SAnirudh Venkataramanan */ 146e94d4478SAnirudh Venkataramanan static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr) 147e94d4478SAnirudh Venkataramanan { 148e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 149e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 150e94d4478SAnirudh Venkataramanan 151e94d4478SAnirudh Venkataramanan if (ice_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr)) 152e94d4478SAnirudh Venkataramanan return -EINVAL; 153e94d4478SAnirudh Venkataramanan 154e94d4478SAnirudh Venkataramanan return 0; 155e94d4478SAnirudh Venkataramanan } 156e94d4478SAnirudh Venkataramanan 157e94d4478SAnirudh Venkataramanan /** 158e94d4478SAnirudh Venkataramanan * ice_vsi_fltr_changed - check if filter state changed 159e94d4478SAnirudh Venkataramanan * @vsi: VSI to be checked 160e94d4478SAnirudh Venkataramanan * 161e94d4478SAnirudh Venkataramanan * returns true if filter state has changed, false otherwise. 162e94d4478SAnirudh Venkataramanan */ 163e94d4478SAnirudh Venkataramanan static bool ice_vsi_fltr_changed(struct ice_vsi *vsi) 164e94d4478SAnirudh Venkataramanan { 165e94d4478SAnirudh Venkataramanan return test_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags) || 166e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags) || 167e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 168e94d4478SAnirudh Venkataramanan } 169e94d4478SAnirudh Venkataramanan 170e94d4478SAnirudh Venkataramanan /** 171e94d4478SAnirudh Venkataramanan * ice_vsi_sync_fltr - Update the VSI filter list to the HW 172e94d4478SAnirudh Venkataramanan * @vsi: ptr to the VSI 173e94d4478SAnirudh Venkataramanan * 174e94d4478SAnirudh Venkataramanan * Push any outstanding VSI filter changes through the AdminQ. 175e94d4478SAnirudh Venkataramanan */ 176e94d4478SAnirudh Venkataramanan static int ice_vsi_sync_fltr(struct ice_vsi *vsi) 177e94d4478SAnirudh Venkataramanan { 178e94d4478SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 179e94d4478SAnirudh Venkataramanan struct net_device *netdev = vsi->netdev; 180e94d4478SAnirudh Venkataramanan bool promisc_forced_on = false; 181e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 182e94d4478SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 183e94d4478SAnirudh Venkataramanan enum ice_status status = 0; 184e94d4478SAnirudh Venkataramanan u32 changed_flags = 0; 185e94d4478SAnirudh Venkataramanan int err = 0; 186e94d4478SAnirudh Venkataramanan 187e94d4478SAnirudh Venkataramanan if (!vsi->netdev) 188e94d4478SAnirudh Venkataramanan return -EINVAL; 189e94d4478SAnirudh Venkataramanan 190e94d4478SAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, vsi->state)) 191e94d4478SAnirudh Venkataramanan usleep_range(1000, 2000); 192e94d4478SAnirudh Venkataramanan 193e94d4478SAnirudh Venkataramanan changed_flags = vsi->current_netdev_flags ^ vsi->netdev->flags; 194e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags = vsi->netdev->flags; 195e94d4478SAnirudh Venkataramanan 196e94d4478SAnirudh Venkataramanan INIT_LIST_HEAD(&vsi->tmp_sync_list); 197e94d4478SAnirudh Venkataramanan INIT_LIST_HEAD(&vsi->tmp_unsync_list); 198e94d4478SAnirudh Venkataramanan 199e94d4478SAnirudh Venkataramanan if (ice_vsi_fltr_changed(vsi)) { 200e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 201e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 202e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 203e94d4478SAnirudh Venkataramanan 204e94d4478SAnirudh Venkataramanan /* grab the netdev's addr_list_lock */ 205e94d4478SAnirudh Venkataramanan netif_addr_lock_bh(netdev); 206e94d4478SAnirudh Venkataramanan __dev_uc_sync(netdev, ice_add_mac_to_sync_list, 207e94d4478SAnirudh Venkataramanan ice_add_mac_to_unsync_list); 208e94d4478SAnirudh Venkataramanan __dev_mc_sync(netdev, ice_add_mac_to_sync_list, 209e94d4478SAnirudh Venkataramanan ice_add_mac_to_unsync_list); 210e94d4478SAnirudh Venkataramanan /* our temp lists are populated. release lock */ 211e94d4478SAnirudh Venkataramanan netif_addr_unlock_bh(netdev); 212e94d4478SAnirudh Venkataramanan } 213e94d4478SAnirudh Venkataramanan 214e94d4478SAnirudh Venkataramanan /* Remove mac addresses in the unsync list */ 215e94d4478SAnirudh Venkataramanan status = ice_remove_mac(hw, &vsi->tmp_unsync_list); 216e94d4478SAnirudh Venkataramanan ice_free_fltr_list(dev, &vsi->tmp_unsync_list); 217e94d4478SAnirudh Venkataramanan if (status) { 218e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Failed to delete MAC filters\n"); 219e94d4478SAnirudh Venkataramanan /* if we failed because of alloc failures, just bail */ 220e94d4478SAnirudh Venkataramanan if (status == ICE_ERR_NO_MEMORY) { 221e94d4478SAnirudh Venkataramanan err = -ENOMEM; 222e94d4478SAnirudh Venkataramanan goto out; 223e94d4478SAnirudh Venkataramanan } 224e94d4478SAnirudh Venkataramanan } 225e94d4478SAnirudh Venkataramanan 226e94d4478SAnirudh Venkataramanan /* Add mac addresses in the sync list */ 227e94d4478SAnirudh Venkataramanan status = ice_add_mac(hw, &vsi->tmp_sync_list); 228e94d4478SAnirudh Venkataramanan ice_free_fltr_list(dev, &vsi->tmp_sync_list); 229e94d4478SAnirudh Venkataramanan if (status) { 230e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Failed to add MAC filters\n"); 231e94d4478SAnirudh Venkataramanan /* If there is no more space for new umac filters, vsi 232e94d4478SAnirudh Venkataramanan * should go into promiscuous mode. There should be some 233e94d4478SAnirudh Venkataramanan * space reserved for promiscuous filters. 234e94d4478SAnirudh Venkataramanan */ 235e94d4478SAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOSPC && 236e94d4478SAnirudh Venkataramanan !test_and_set_bit(__ICE_FLTR_OVERFLOW_PROMISC, 237e94d4478SAnirudh Venkataramanan vsi->state)) { 238e94d4478SAnirudh Venkataramanan promisc_forced_on = true; 239e94d4478SAnirudh Venkataramanan netdev_warn(netdev, 240e94d4478SAnirudh Venkataramanan "Reached MAC filter limit, forcing promisc mode on VSI %d\n", 241e94d4478SAnirudh Venkataramanan vsi->vsi_num); 242e94d4478SAnirudh Venkataramanan } else { 243e94d4478SAnirudh Venkataramanan err = -EIO; 244e94d4478SAnirudh Venkataramanan goto out; 245e94d4478SAnirudh Venkataramanan } 246e94d4478SAnirudh Venkataramanan } 247e94d4478SAnirudh Venkataramanan /* check for changes in promiscuous modes */ 248e94d4478SAnirudh Venkataramanan if (changed_flags & IFF_ALLMULTI) 249e94d4478SAnirudh Venkataramanan netdev_warn(netdev, "Unsupported configuration\n"); 250e94d4478SAnirudh Venkataramanan 251e94d4478SAnirudh Venkataramanan if (((changed_flags & IFF_PROMISC) || promisc_forced_on) || 252e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) { 253e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags); 254e94d4478SAnirudh Venkataramanan if (vsi->current_netdev_flags & IFF_PROMISC) { 255e94d4478SAnirudh Venkataramanan /* Apply TX filter rule to get traffic from VMs */ 2564fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, true, 257e94d4478SAnirudh Venkataramanan ICE_FLTR_TX); 258e94d4478SAnirudh Venkataramanan if (status) { 259e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error setting default VSI %i tx rule\n", 260e94d4478SAnirudh Venkataramanan vsi->vsi_num); 261e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags &= ~IFF_PROMISC; 262e94d4478SAnirudh Venkataramanan err = -EIO; 263e94d4478SAnirudh Venkataramanan goto out_promisc; 264e94d4478SAnirudh Venkataramanan } 265e94d4478SAnirudh Venkataramanan /* Apply RX filter rule to get traffic from wire */ 2664fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, true, 267e94d4478SAnirudh Venkataramanan ICE_FLTR_RX); 268e94d4478SAnirudh Venkataramanan if (status) { 269e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error setting default VSI %i rx rule\n", 270e94d4478SAnirudh Venkataramanan vsi->vsi_num); 271e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags &= ~IFF_PROMISC; 272e94d4478SAnirudh Venkataramanan err = -EIO; 273e94d4478SAnirudh Venkataramanan goto out_promisc; 274e94d4478SAnirudh Venkataramanan } 275e94d4478SAnirudh Venkataramanan } else { 276e94d4478SAnirudh Venkataramanan /* Clear TX filter rule to stop traffic from VMs */ 2774fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, false, 278e94d4478SAnirudh Venkataramanan ICE_FLTR_TX); 279e94d4478SAnirudh Venkataramanan if (status) { 280e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error clearing default VSI %i tx rule\n", 281e94d4478SAnirudh Venkataramanan vsi->vsi_num); 282e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags |= IFF_PROMISC; 283e94d4478SAnirudh Venkataramanan err = -EIO; 284e94d4478SAnirudh Venkataramanan goto out_promisc; 285e94d4478SAnirudh Venkataramanan } 2864fb33f31SAnirudh Venkataramanan /* Clear RX filter to remove traffic from wire */ 2874fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, false, 288e94d4478SAnirudh Venkataramanan ICE_FLTR_RX); 289e94d4478SAnirudh Venkataramanan if (status) { 290e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error clearing default VSI %i rx rule\n", 291e94d4478SAnirudh Venkataramanan vsi->vsi_num); 292e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags |= IFF_PROMISC; 293e94d4478SAnirudh Venkataramanan err = -EIO; 294e94d4478SAnirudh Venkataramanan goto out_promisc; 295e94d4478SAnirudh Venkataramanan } 296e94d4478SAnirudh Venkataramanan } 297e94d4478SAnirudh Venkataramanan } 298e94d4478SAnirudh Venkataramanan goto exit; 299e94d4478SAnirudh Venkataramanan 300e94d4478SAnirudh Venkataramanan out_promisc: 301e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags); 302e94d4478SAnirudh Venkataramanan goto exit; 303e94d4478SAnirudh Venkataramanan out: 304e94d4478SAnirudh Venkataramanan /* if something went wrong then set the changed flag so we try again */ 305e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 306e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 307e94d4478SAnirudh Venkataramanan exit: 308e94d4478SAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, vsi->state); 309e94d4478SAnirudh Venkataramanan return err; 310e94d4478SAnirudh Venkataramanan } 311e94d4478SAnirudh Venkataramanan 312e94d4478SAnirudh Venkataramanan /** 313e94d4478SAnirudh Venkataramanan * ice_sync_fltr_subtask - Sync the VSI filter list with HW 314e94d4478SAnirudh Venkataramanan * @pf: board private structure 315e94d4478SAnirudh Venkataramanan */ 316e94d4478SAnirudh Venkataramanan static void ice_sync_fltr_subtask(struct ice_pf *pf) 317e94d4478SAnirudh Venkataramanan { 318e94d4478SAnirudh Venkataramanan int v; 319e94d4478SAnirudh Venkataramanan 320e94d4478SAnirudh Venkataramanan if (!pf || !(test_bit(ICE_FLAG_FLTR_SYNC, pf->flags))) 321e94d4478SAnirudh Venkataramanan return; 322e94d4478SAnirudh Venkataramanan 323e94d4478SAnirudh Venkataramanan clear_bit(ICE_FLAG_FLTR_SYNC, pf->flags); 324e94d4478SAnirudh Venkataramanan 325e94d4478SAnirudh Venkataramanan for (v = 0; v < pf->num_alloc_vsi; v++) 326e94d4478SAnirudh Venkataramanan if (pf->vsi[v] && ice_vsi_fltr_changed(pf->vsi[v]) && 327e94d4478SAnirudh Venkataramanan ice_vsi_sync_fltr(pf->vsi[v])) { 328e94d4478SAnirudh Venkataramanan /* come back and try again later */ 329e94d4478SAnirudh Venkataramanan set_bit(ICE_FLAG_FLTR_SYNC, pf->flags); 330e94d4478SAnirudh Venkataramanan break; 331e94d4478SAnirudh Venkataramanan } 332e94d4478SAnirudh Venkataramanan } 333e94d4478SAnirudh Venkataramanan 334e94d4478SAnirudh Venkataramanan /** 3350b28b702SAnirudh Venkataramanan * ice_prepare_for_reset - prep for the core to reset 3360b28b702SAnirudh Venkataramanan * @pf: board private structure 3370b28b702SAnirudh Venkataramanan * 3380b28b702SAnirudh Venkataramanan * Inform or close all dependent features in prep for reset. 3390b28b702SAnirudh Venkataramanan */ 3400b28b702SAnirudh Venkataramanan static void 3410b28b702SAnirudh Venkataramanan ice_prepare_for_reset(struct ice_pf *pf) 3420b28b702SAnirudh Venkataramanan { 3430b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3440b28b702SAnirudh Venkataramanan 3450b28b702SAnirudh Venkataramanan /* disable the VSIs and their queues that are not already DOWN */ 3460b28b702SAnirudh Venkataramanan ice_pf_dis_all_vsi(pf); 3470b28b702SAnirudh Venkataramanan 3480b28b702SAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 3490f9d5027SAnirudh Venkataramanan 3500f9d5027SAnirudh Venkataramanan set_bit(__ICE_PREPARED_FOR_RESET, pf->state); 3510b28b702SAnirudh Venkataramanan } 3520b28b702SAnirudh Venkataramanan 3530b28b702SAnirudh Venkataramanan /** 3540b28b702SAnirudh Venkataramanan * ice_do_reset - Initiate one of many types of resets 3550b28b702SAnirudh Venkataramanan * @pf: board private structure 3560b28b702SAnirudh Venkataramanan * @reset_type: reset type requested 3570b28b702SAnirudh Venkataramanan * before this function was called. 3580b28b702SAnirudh Venkataramanan */ 3590b28b702SAnirudh Venkataramanan static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type) 3600b28b702SAnirudh Venkataramanan { 3610b28b702SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 3620b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3630b28b702SAnirudh Venkataramanan 3640b28b702SAnirudh Venkataramanan dev_dbg(dev, "reset_type 0x%x requested\n", reset_type); 3650b28b702SAnirudh Venkataramanan WARN_ON(in_interrupt()); 3660b28b702SAnirudh Venkataramanan 3670b28b702SAnirudh Venkataramanan ice_prepare_for_reset(pf); 3680b28b702SAnirudh Venkataramanan 3690b28b702SAnirudh Venkataramanan /* trigger the reset */ 3700b28b702SAnirudh Venkataramanan if (ice_reset(hw, reset_type)) { 3710b28b702SAnirudh Venkataramanan dev_err(dev, "reset %d failed\n", reset_type); 3720b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 3735df7e45dSDave Ertman clear_bit(__ICE_RESET_OICR_RECV, pf->state); 3740f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 3755df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 3765df7e45dSDave Ertman clear_bit(__ICE_CORER_REQ, pf->state); 3775df7e45dSDave Ertman clear_bit(__ICE_GLOBR_REQ, pf->state); 3780b28b702SAnirudh Venkataramanan return; 3790b28b702SAnirudh Venkataramanan } 3800b28b702SAnirudh Venkataramanan 3810f9d5027SAnirudh Venkataramanan /* PFR is a bit of a special case because it doesn't result in an OICR 3820f9d5027SAnirudh Venkataramanan * interrupt. So for PFR, rebuild after the reset and clear the reset- 3830f9d5027SAnirudh Venkataramanan * associated state bits. 3840f9d5027SAnirudh Venkataramanan */ 3850b28b702SAnirudh Venkataramanan if (reset_type == ICE_RESET_PFR) { 3860b28b702SAnirudh Venkataramanan pf->pfr_count++; 3870b28b702SAnirudh Venkataramanan ice_rebuild(pf); 3880f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 3895df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 3900b28b702SAnirudh Venkataramanan } 3910b28b702SAnirudh Venkataramanan } 3920b28b702SAnirudh Venkataramanan 3930b28b702SAnirudh Venkataramanan /** 3940b28b702SAnirudh Venkataramanan * ice_reset_subtask - Set up for resetting the device and driver 3950b28b702SAnirudh Venkataramanan * @pf: board private structure 3960b28b702SAnirudh Venkataramanan */ 3970b28b702SAnirudh Venkataramanan static void ice_reset_subtask(struct ice_pf *pf) 3980b28b702SAnirudh Venkataramanan { 3990f9d5027SAnirudh Venkataramanan enum ice_reset_req reset_type = ICE_RESET_INVAL; 4000b28b702SAnirudh Venkataramanan 4010b28b702SAnirudh Venkataramanan /* When a CORER/GLOBR/EMPR is about to happen, the hardware triggers an 4020f9d5027SAnirudh Venkataramanan * OICR interrupt. The OICR handler (ice_misc_intr) determines what type 4030f9d5027SAnirudh Venkataramanan * of reset is pending and sets bits in pf->state indicating the reset 4045df7e45dSDave Ertman * type and __ICE_RESET_OICR_RECV. So, if the latter bit is set 4050f9d5027SAnirudh Venkataramanan * prepare for pending reset if not already (for PF software-initiated 4060f9d5027SAnirudh Venkataramanan * global resets the software should already be prepared for it as 4070f9d5027SAnirudh Venkataramanan * indicated by __ICE_PREPARED_FOR_RESET; for global resets initiated 4080f9d5027SAnirudh Venkataramanan * by firmware or software on other PFs, that bit is not set so prepare 4090f9d5027SAnirudh Venkataramanan * for the reset now), poll for reset done, rebuild and return. 4100b28b702SAnirudh Venkataramanan */ 4115df7e45dSDave Ertman if (test_bit(__ICE_RESET_OICR_RECV, pf->state)) { 4120b28b702SAnirudh Venkataramanan clear_bit(__ICE_GLOBR_RECV, pf->state); 4130b28b702SAnirudh Venkataramanan clear_bit(__ICE_CORER_RECV, pf->state); 4140f9d5027SAnirudh Venkataramanan if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) 4150b28b702SAnirudh Venkataramanan ice_prepare_for_reset(pf); 4160b28b702SAnirudh Venkataramanan 4170b28b702SAnirudh Venkataramanan /* make sure we are ready to rebuild */ 418fd2a9817SAnirudh Venkataramanan if (ice_check_reset(&pf->hw)) { 4190b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 420fd2a9817SAnirudh Venkataramanan } else { 421fd2a9817SAnirudh Venkataramanan /* done with reset. start rebuild */ 422fd2a9817SAnirudh Venkataramanan pf->hw.reset_ongoing = false; 4230b28b702SAnirudh Venkataramanan ice_rebuild(pf); 4240f9d5027SAnirudh Venkataramanan /* clear bit to resume normal operations, but 4250f9d5027SAnirudh Venkataramanan * ICE_NEEDS_RESTART bit is set incase rebuild failed 4260f9d5027SAnirudh Venkataramanan */ 4275df7e45dSDave Ertman clear_bit(__ICE_RESET_OICR_RECV, pf->state); 4280f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 4295df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 4305df7e45dSDave Ertman clear_bit(__ICE_CORER_REQ, pf->state); 4315df7e45dSDave Ertman clear_bit(__ICE_GLOBR_REQ, pf->state); 4320f9d5027SAnirudh Venkataramanan } 4330f9d5027SAnirudh Venkataramanan 4340f9d5027SAnirudh Venkataramanan return; 4350b28b702SAnirudh Venkataramanan } 4360b28b702SAnirudh Venkataramanan 4370b28b702SAnirudh Venkataramanan /* No pending resets to finish processing. Check for new resets */ 4385df7e45dSDave Ertman if (test_bit(__ICE_PFR_REQ, pf->state)) 4390f9d5027SAnirudh Venkataramanan reset_type = ICE_RESET_PFR; 4405df7e45dSDave Ertman if (test_bit(__ICE_CORER_REQ, pf->state)) 4410f9d5027SAnirudh Venkataramanan reset_type = ICE_RESET_CORER; 4425df7e45dSDave Ertman if (test_bit(__ICE_GLOBR_REQ, pf->state)) 4430b28b702SAnirudh Venkataramanan reset_type = ICE_RESET_GLOBR; 4440f9d5027SAnirudh Venkataramanan /* If no valid reset type requested just return */ 4450f9d5027SAnirudh Venkataramanan if (reset_type == ICE_RESET_INVAL) 4460f9d5027SAnirudh Venkataramanan return; 4470b28b702SAnirudh Venkataramanan 4480f9d5027SAnirudh Venkataramanan /* reset if not already down or busy */ 4490b28b702SAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 4500b28b702SAnirudh Venkataramanan !test_bit(__ICE_CFG_BUSY, pf->state)) { 4510b28b702SAnirudh Venkataramanan ice_do_reset(pf, reset_type); 4520b28b702SAnirudh Venkataramanan } 4530b28b702SAnirudh Venkataramanan } 4540b28b702SAnirudh Venkataramanan 4550b28b702SAnirudh Venkataramanan /** 456fcea6f3dSAnirudh Venkataramanan * ice_watchdog_subtask - periodic tasks not using event driven scheduling 457fcea6f3dSAnirudh Venkataramanan * @pf: board private structure 458fcea6f3dSAnirudh Venkataramanan */ 459fcea6f3dSAnirudh Venkataramanan static void ice_watchdog_subtask(struct ice_pf *pf) 460fcea6f3dSAnirudh Venkataramanan { 461fcea6f3dSAnirudh Venkataramanan int i; 462fcea6f3dSAnirudh Venkataramanan 463fcea6f3dSAnirudh Venkataramanan /* if interface is down do nothing */ 464fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state) || 465fcea6f3dSAnirudh Venkataramanan test_bit(__ICE_CFG_BUSY, pf->state)) 466fcea6f3dSAnirudh Venkataramanan return; 467fcea6f3dSAnirudh Venkataramanan 468fcea6f3dSAnirudh Venkataramanan /* make sure we don't do these things too often */ 469fcea6f3dSAnirudh Venkataramanan if (time_before(jiffies, 470fcea6f3dSAnirudh Venkataramanan pf->serv_tmr_prev + pf->serv_tmr_period)) 471fcea6f3dSAnirudh Venkataramanan return; 472fcea6f3dSAnirudh Venkataramanan 473fcea6f3dSAnirudh Venkataramanan pf->serv_tmr_prev = jiffies; 474fcea6f3dSAnirudh Venkataramanan 475fcea6f3dSAnirudh Venkataramanan /* Update the stats for active netdevs so the network stack 476fcea6f3dSAnirudh Venkataramanan * can look at updated numbers whenever it cares to 477fcea6f3dSAnirudh Venkataramanan */ 478fcea6f3dSAnirudh Venkataramanan ice_update_pf_stats(pf); 479fcea6f3dSAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) 480fcea6f3dSAnirudh Venkataramanan if (pf->vsi[i] && pf->vsi[i]->netdev) 481fcea6f3dSAnirudh Venkataramanan ice_update_vsi_stats(pf->vsi[i]); 482fcea6f3dSAnirudh Venkataramanan } 483fcea6f3dSAnirudh Venkataramanan 484fcea6f3dSAnirudh Venkataramanan /** 485cdedef59SAnirudh Venkataramanan * ice_print_link_msg - print link up or down message 486cdedef59SAnirudh Venkataramanan * @vsi: the VSI whose link status is being queried 487cdedef59SAnirudh Venkataramanan * @isup: boolean for if the link is now up or down 488cdedef59SAnirudh Venkataramanan */ 489fcea6f3dSAnirudh Venkataramanan void ice_print_link_msg(struct ice_vsi *vsi, bool isup) 490cdedef59SAnirudh Venkataramanan { 491cdedef59SAnirudh Venkataramanan const char *speed; 492cdedef59SAnirudh Venkataramanan const char *fc; 493cdedef59SAnirudh Venkataramanan 494cdedef59SAnirudh Venkataramanan if (vsi->current_isup == isup) 495cdedef59SAnirudh Venkataramanan return; 496cdedef59SAnirudh Venkataramanan 497cdedef59SAnirudh Venkataramanan vsi->current_isup = isup; 498cdedef59SAnirudh Venkataramanan 499cdedef59SAnirudh Venkataramanan if (!isup) { 500cdedef59SAnirudh Venkataramanan netdev_info(vsi->netdev, "NIC Link is Down\n"); 501cdedef59SAnirudh Venkataramanan return; 502cdedef59SAnirudh Venkataramanan } 503cdedef59SAnirudh Venkataramanan 504cdedef59SAnirudh Venkataramanan switch (vsi->port_info->phy.link_info.link_speed) { 505cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_40GB: 506cdedef59SAnirudh Venkataramanan speed = "40 G"; 507cdedef59SAnirudh Venkataramanan break; 508cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 509cdedef59SAnirudh Venkataramanan speed = "25 G"; 510cdedef59SAnirudh Venkataramanan break; 511cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_20GB: 512cdedef59SAnirudh Venkataramanan speed = "20 G"; 513cdedef59SAnirudh Venkataramanan break; 514cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_10GB: 515cdedef59SAnirudh Venkataramanan speed = "10 G"; 516cdedef59SAnirudh Venkataramanan break; 517cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_5GB: 518cdedef59SAnirudh Venkataramanan speed = "5 G"; 519cdedef59SAnirudh Venkataramanan break; 520cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_2500MB: 521cdedef59SAnirudh Venkataramanan speed = "2.5 G"; 522cdedef59SAnirudh Venkataramanan break; 523cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_1000MB: 524cdedef59SAnirudh Venkataramanan speed = "1 G"; 525cdedef59SAnirudh Venkataramanan break; 526cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100MB: 527cdedef59SAnirudh Venkataramanan speed = "100 M"; 528cdedef59SAnirudh Venkataramanan break; 529cdedef59SAnirudh Venkataramanan default: 530cdedef59SAnirudh Venkataramanan speed = "Unknown"; 531cdedef59SAnirudh Venkataramanan break; 532cdedef59SAnirudh Venkataramanan } 533cdedef59SAnirudh Venkataramanan 534cdedef59SAnirudh Venkataramanan switch (vsi->port_info->fc.current_mode) { 535cdedef59SAnirudh Venkataramanan case ICE_FC_FULL: 536cdedef59SAnirudh Venkataramanan fc = "RX/TX"; 537cdedef59SAnirudh Venkataramanan break; 538cdedef59SAnirudh Venkataramanan case ICE_FC_TX_PAUSE: 539cdedef59SAnirudh Venkataramanan fc = "TX"; 540cdedef59SAnirudh Venkataramanan break; 541cdedef59SAnirudh Venkataramanan case ICE_FC_RX_PAUSE: 542cdedef59SAnirudh Venkataramanan fc = "RX"; 543cdedef59SAnirudh Venkataramanan break; 544cdedef59SAnirudh Venkataramanan default: 545cdedef59SAnirudh Venkataramanan fc = "Unknown"; 546cdedef59SAnirudh Venkataramanan break; 547cdedef59SAnirudh Venkataramanan } 548cdedef59SAnirudh Venkataramanan 549cdedef59SAnirudh Venkataramanan netdev_info(vsi->netdev, "NIC Link is up %sbps, Flow Control: %s\n", 550cdedef59SAnirudh Venkataramanan speed, fc); 551cdedef59SAnirudh Venkataramanan } 552cdedef59SAnirudh Venkataramanan 553cdedef59SAnirudh Venkataramanan /** 5540b28b702SAnirudh Venkataramanan * ice_init_link_events - enable/initialize link events 5550b28b702SAnirudh Venkataramanan * @pi: pointer to the port_info instance 5560b28b702SAnirudh Venkataramanan * 5570b28b702SAnirudh Venkataramanan * Returns -EIO on failure, 0 on success 5580b28b702SAnirudh Venkataramanan */ 5590b28b702SAnirudh Venkataramanan static int ice_init_link_events(struct ice_port_info *pi) 5600b28b702SAnirudh Venkataramanan { 5610b28b702SAnirudh Venkataramanan u16 mask; 5620b28b702SAnirudh Venkataramanan 5630b28b702SAnirudh Venkataramanan mask = ~((u16)(ICE_AQ_LINK_EVENT_UPDOWN | ICE_AQ_LINK_EVENT_MEDIA_NA | 5640b28b702SAnirudh Venkataramanan ICE_AQ_LINK_EVENT_MODULE_QUAL_FAIL)); 5650b28b702SAnirudh Venkataramanan 5660b28b702SAnirudh Venkataramanan if (ice_aq_set_event_mask(pi->hw, pi->lport, mask, NULL)) { 5670b28b702SAnirudh Venkataramanan dev_dbg(ice_hw_to_dev(pi->hw), 5680b28b702SAnirudh Venkataramanan "Failed to set link event mask for port %d\n", 5690b28b702SAnirudh Venkataramanan pi->lport); 5700b28b702SAnirudh Venkataramanan return -EIO; 5710b28b702SAnirudh Venkataramanan } 5720b28b702SAnirudh Venkataramanan 5730b28b702SAnirudh Venkataramanan if (ice_aq_get_link_info(pi, true, NULL, NULL)) { 5740b28b702SAnirudh Venkataramanan dev_dbg(ice_hw_to_dev(pi->hw), 5750b28b702SAnirudh Venkataramanan "Failed to enable link events for port %d\n", 5760b28b702SAnirudh Venkataramanan pi->lport); 5770b28b702SAnirudh Venkataramanan return -EIO; 5780b28b702SAnirudh Venkataramanan } 5790b28b702SAnirudh Venkataramanan 5800b28b702SAnirudh Venkataramanan return 0; 5810b28b702SAnirudh Venkataramanan } 5820b28b702SAnirudh Venkataramanan 5830b28b702SAnirudh Venkataramanan /** 5840b28b702SAnirudh Venkataramanan * ice_vsi_link_event - update the vsi's netdev 5850b28b702SAnirudh Venkataramanan * @vsi: the vsi on which the link event occurred 5860b28b702SAnirudh Venkataramanan * @link_up: whether or not the vsi needs to be set up or down 5870b28b702SAnirudh Venkataramanan */ 5880b28b702SAnirudh Venkataramanan static void ice_vsi_link_event(struct ice_vsi *vsi, bool link_up) 5890b28b702SAnirudh Venkataramanan { 5900b28b702SAnirudh Venkataramanan if (!vsi || test_bit(__ICE_DOWN, vsi->state)) 5910b28b702SAnirudh Venkataramanan return; 5920b28b702SAnirudh Venkataramanan 5930b28b702SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 5940b28b702SAnirudh Venkataramanan if (!vsi->netdev) { 5950b28b702SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, 5960b28b702SAnirudh Venkataramanan "vsi->netdev is not initialized!\n"); 5970b28b702SAnirudh Venkataramanan return; 5980b28b702SAnirudh Venkataramanan } 5990b28b702SAnirudh Venkataramanan if (link_up) { 6000b28b702SAnirudh Venkataramanan netif_carrier_on(vsi->netdev); 6010b28b702SAnirudh Venkataramanan netif_tx_wake_all_queues(vsi->netdev); 6020b28b702SAnirudh Venkataramanan } else { 6030b28b702SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 6040b28b702SAnirudh Venkataramanan netif_tx_stop_all_queues(vsi->netdev); 6050b28b702SAnirudh Venkataramanan } 6060b28b702SAnirudh Venkataramanan } 6070b28b702SAnirudh Venkataramanan } 6080b28b702SAnirudh Venkataramanan 6090b28b702SAnirudh Venkataramanan /** 6100b28b702SAnirudh Venkataramanan * ice_link_event - process the link event 6110b28b702SAnirudh Venkataramanan * @pf: pf that the link event is associated with 6120b28b702SAnirudh Venkataramanan * @pi: port_info for the port that the link event is associated with 6130b28b702SAnirudh Venkataramanan * 6140b28b702SAnirudh Venkataramanan * Returns -EIO if ice_get_link_status() fails 6150b28b702SAnirudh Venkataramanan * Returns 0 on success 6160b28b702SAnirudh Venkataramanan */ 6170b28b702SAnirudh Venkataramanan static int 6180b28b702SAnirudh Venkataramanan ice_link_event(struct ice_pf *pf, struct ice_port_info *pi) 6190b28b702SAnirudh Venkataramanan { 6200b28b702SAnirudh Venkataramanan u8 new_link_speed, old_link_speed; 6210b28b702SAnirudh Venkataramanan struct ice_phy_info *phy_info; 6220b28b702SAnirudh Venkataramanan bool new_link_same_as_old; 6230b28b702SAnirudh Venkataramanan bool new_link, old_link; 6240b28b702SAnirudh Venkataramanan u8 lport; 6250b28b702SAnirudh Venkataramanan u16 v; 6260b28b702SAnirudh Venkataramanan 6270b28b702SAnirudh Venkataramanan phy_info = &pi->phy; 6280b28b702SAnirudh Venkataramanan phy_info->link_info_old = phy_info->link_info; 6290b28b702SAnirudh Venkataramanan /* Force ice_get_link_status() to update link info */ 6300b28b702SAnirudh Venkataramanan phy_info->get_link_info = true; 6310b28b702SAnirudh Venkataramanan 6320b28b702SAnirudh Venkataramanan old_link = (phy_info->link_info_old.link_info & ICE_AQ_LINK_UP); 6330b28b702SAnirudh Venkataramanan old_link_speed = phy_info->link_info_old.link_speed; 6340b28b702SAnirudh Venkataramanan 6350b28b702SAnirudh Venkataramanan lport = pi->lport; 6360b28b702SAnirudh Venkataramanan if (ice_get_link_status(pi, &new_link)) { 6370b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 6380b28b702SAnirudh Venkataramanan "Could not get link status for port %d\n", lport); 6390b28b702SAnirudh Venkataramanan return -EIO; 6400b28b702SAnirudh Venkataramanan } 6410b28b702SAnirudh Venkataramanan 6420b28b702SAnirudh Venkataramanan new_link_speed = phy_info->link_info.link_speed; 6430b28b702SAnirudh Venkataramanan 6440b28b702SAnirudh Venkataramanan new_link_same_as_old = (new_link == old_link && 6450b28b702SAnirudh Venkataramanan new_link_speed == old_link_speed); 6460b28b702SAnirudh Venkataramanan 6470b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) { 6480b28b702SAnirudh Venkataramanan struct ice_vsi *vsi = pf->vsi[v]; 6490b28b702SAnirudh Venkataramanan 6500b28b702SAnirudh Venkataramanan if (!vsi || !vsi->port_info) 6510b28b702SAnirudh Venkataramanan continue; 6520b28b702SAnirudh Venkataramanan 6530b28b702SAnirudh Venkataramanan if (new_link_same_as_old && 6540b28b702SAnirudh Venkataramanan (test_bit(__ICE_DOWN, vsi->state) || 6550b28b702SAnirudh Venkataramanan new_link == netif_carrier_ok(vsi->netdev))) 6560b28b702SAnirudh Venkataramanan continue; 6570b28b702SAnirudh Venkataramanan 6580b28b702SAnirudh Venkataramanan if (vsi->port_info->lport == lport) { 6590b28b702SAnirudh Venkataramanan ice_print_link_msg(vsi, new_link); 6600b28b702SAnirudh Venkataramanan ice_vsi_link_event(vsi, new_link); 6610b28b702SAnirudh Venkataramanan } 6620b28b702SAnirudh Venkataramanan } 6630b28b702SAnirudh Venkataramanan 6640b28b702SAnirudh Venkataramanan return 0; 6650b28b702SAnirudh Venkataramanan } 6660b28b702SAnirudh Venkataramanan 6670b28b702SAnirudh Venkataramanan /** 6680b28b702SAnirudh Venkataramanan * ice_handle_link_event - handle link event via ARQ 6690b28b702SAnirudh Venkataramanan * @pf: pf that the link event is associated with 6700b28b702SAnirudh Venkataramanan * 6710b28b702SAnirudh Venkataramanan * Return -EINVAL if port_info is null 6720b28b702SAnirudh Venkataramanan * Return status on succes 6730b28b702SAnirudh Venkataramanan */ 6740b28b702SAnirudh Venkataramanan static int ice_handle_link_event(struct ice_pf *pf) 6750b28b702SAnirudh Venkataramanan { 6760b28b702SAnirudh Venkataramanan struct ice_port_info *port_info; 6770b28b702SAnirudh Venkataramanan int status; 6780b28b702SAnirudh Venkataramanan 6790b28b702SAnirudh Venkataramanan port_info = pf->hw.port_info; 6800b28b702SAnirudh Venkataramanan if (!port_info) 6810b28b702SAnirudh Venkataramanan return -EINVAL; 6820b28b702SAnirudh Venkataramanan 6830b28b702SAnirudh Venkataramanan status = ice_link_event(pf, port_info); 6840b28b702SAnirudh Venkataramanan if (status) 6850b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 6860b28b702SAnirudh Venkataramanan "Could not process link event, error %d\n", status); 6870b28b702SAnirudh Venkataramanan 6880b28b702SAnirudh Venkataramanan return status; 6890b28b702SAnirudh Venkataramanan } 6900b28b702SAnirudh Venkataramanan 6910b28b702SAnirudh Venkataramanan /** 692940b61afSAnirudh Venkataramanan * __ice_clean_ctrlq - helper function to clean controlq rings 693940b61afSAnirudh Venkataramanan * @pf: ptr to struct ice_pf 694940b61afSAnirudh Venkataramanan * @q_type: specific Control queue type 695940b61afSAnirudh Venkataramanan */ 696940b61afSAnirudh Venkataramanan static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) 697940b61afSAnirudh Venkataramanan { 698940b61afSAnirudh Venkataramanan struct ice_rq_event_info event; 699940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 700940b61afSAnirudh Venkataramanan struct ice_ctl_q_info *cq; 701940b61afSAnirudh Venkataramanan u16 pending, i = 0; 702940b61afSAnirudh Venkataramanan const char *qtype; 703940b61afSAnirudh Venkataramanan u32 oldval, val; 704940b61afSAnirudh Venkataramanan 7050b28b702SAnirudh Venkataramanan /* Do not clean control queue if/when PF reset fails */ 7060b28b702SAnirudh Venkataramanan if (test_bit(__ICE_RESET_FAILED, pf->state)) 7070b28b702SAnirudh Venkataramanan return 0; 7080b28b702SAnirudh Venkataramanan 709940b61afSAnirudh Venkataramanan switch (q_type) { 710940b61afSAnirudh Venkataramanan case ICE_CTL_Q_ADMIN: 711940b61afSAnirudh Venkataramanan cq = &hw->adminq; 712940b61afSAnirudh Venkataramanan qtype = "Admin"; 713940b61afSAnirudh Venkataramanan break; 71475d2b253SAnirudh Venkataramanan case ICE_CTL_Q_MAILBOX: 71575d2b253SAnirudh Venkataramanan cq = &hw->mailboxq; 71675d2b253SAnirudh Venkataramanan qtype = "Mailbox"; 71775d2b253SAnirudh Venkataramanan break; 718940b61afSAnirudh Venkataramanan default: 719940b61afSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown control queue type 0x%x\n", 720940b61afSAnirudh Venkataramanan q_type); 721940b61afSAnirudh Venkataramanan return 0; 722940b61afSAnirudh Venkataramanan } 723940b61afSAnirudh Venkataramanan 724940b61afSAnirudh Venkataramanan /* check for error indications - PF_xx_AxQLEN register layout for 725940b61afSAnirudh Venkataramanan * FW/MBX/SB are identical so just use defines for PF_FW_AxQLEN. 726940b61afSAnirudh Venkataramanan */ 727940b61afSAnirudh Venkataramanan val = rd32(hw, cq->rq.len); 728940b61afSAnirudh Venkataramanan if (val & (PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M | 729940b61afSAnirudh Venkataramanan PF_FW_ARQLEN_ARQCRIT_M)) { 730940b61afSAnirudh Venkataramanan oldval = val; 731940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQVFE_M) 732940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 733940b61afSAnirudh Venkataramanan "%s Receive Queue VF Error detected\n", qtype); 734940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQOVFL_M) { 735940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 736940b61afSAnirudh Venkataramanan "%s Receive Queue Overflow Error detected\n", 737940b61afSAnirudh Venkataramanan qtype); 738940b61afSAnirudh Venkataramanan } 739940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQCRIT_M) 740940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 741940b61afSAnirudh Venkataramanan "%s Receive Queue Critical Error detected\n", 742940b61afSAnirudh Venkataramanan qtype); 743940b61afSAnirudh Venkataramanan val &= ~(PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M | 744940b61afSAnirudh Venkataramanan PF_FW_ARQLEN_ARQCRIT_M); 745940b61afSAnirudh Venkataramanan if (oldval != val) 746940b61afSAnirudh Venkataramanan wr32(hw, cq->rq.len, val); 747940b61afSAnirudh Venkataramanan } 748940b61afSAnirudh Venkataramanan 749940b61afSAnirudh Venkataramanan val = rd32(hw, cq->sq.len); 750940b61afSAnirudh Venkataramanan if (val & (PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M | 751940b61afSAnirudh Venkataramanan PF_FW_ATQLEN_ATQCRIT_M)) { 752940b61afSAnirudh Venkataramanan oldval = val; 753940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQVFE_M) 754940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 755940b61afSAnirudh Venkataramanan "%s Send Queue VF Error detected\n", qtype); 756940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQOVFL_M) { 757940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 758940b61afSAnirudh Venkataramanan "%s Send Queue Overflow Error detected\n", 759940b61afSAnirudh Venkataramanan qtype); 760940b61afSAnirudh Venkataramanan } 761940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQCRIT_M) 762940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 763940b61afSAnirudh Venkataramanan "%s Send Queue Critical Error detected\n", 764940b61afSAnirudh Venkataramanan qtype); 765940b61afSAnirudh Venkataramanan val &= ~(PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M | 766940b61afSAnirudh Venkataramanan PF_FW_ATQLEN_ATQCRIT_M); 767940b61afSAnirudh Venkataramanan if (oldval != val) 768940b61afSAnirudh Venkataramanan wr32(hw, cq->sq.len, val); 769940b61afSAnirudh Venkataramanan } 770940b61afSAnirudh Venkataramanan 771940b61afSAnirudh Venkataramanan event.buf_len = cq->rq_buf_size; 772940b61afSAnirudh Venkataramanan event.msg_buf = devm_kzalloc(&pf->pdev->dev, event.buf_len, 773940b61afSAnirudh Venkataramanan GFP_KERNEL); 774940b61afSAnirudh Venkataramanan if (!event.msg_buf) 775940b61afSAnirudh Venkataramanan return 0; 776940b61afSAnirudh Venkataramanan 777940b61afSAnirudh Venkataramanan do { 778940b61afSAnirudh Venkataramanan enum ice_status ret; 7790b28b702SAnirudh Venkataramanan u16 opcode; 780940b61afSAnirudh Venkataramanan 781940b61afSAnirudh Venkataramanan ret = ice_clean_rq_elem(hw, cq, &event, &pending); 782940b61afSAnirudh Venkataramanan if (ret == ICE_ERR_AQ_NO_WORK) 783940b61afSAnirudh Venkataramanan break; 784940b61afSAnirudh Venkataramanan if (ret) { 785940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 786940b61afSAnirudh Venkataramanan "%s Receive Queue event error %d\n", qtype, 787940b61afSAnirudh Venkataramanan ret); 788940b61afSAnirudh Venkataramanan break; 789940b61afSAnirudh Venkataramanan } 7900b28b702SAnirudh Venkataramanan 7910b28b702SAnirudh Venkataramanan opcode = le16_to_cpu(event.desc.opcode); 7920b28b702SAnirudh Venkataramanan 7930b28b702SAnirudh Venkataramanan switch (opcode) { 7940b28b702SAnirudh Venkataramanan case ice_aqc_opc_get_link_status: 7950b28b702SAnirudh Venkataramanan if (ice_handle_link_event(pf)) 7960b28b702SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 7973968540bSAnirudh Venkataramanan "Could not handle link event\n"); 7980b28b702SAnirudh Venkataramanan break; 7998b97ceb1SHieu Tran case ice_aqc_opc_fw_logging: 8008b97ceb1SHieu Tran ice_output_fw_log(hw, &event.desc, event.msg_buf); 8018b97ceb1SHieu Tran break; 8020b28b702SAnirudh Venkataramanan default: 8030b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 8040b28b702SAnirudh Venkataramanan "%s Receive Queue unknown event 0x%04x ignored\n", 8050b28b702SAnirudh Venkataramanan qtype, opcode); 8060b28b702SAnirudh Venkataramanan break; 8070b28b702SAnirudh Venkataramanan } 808940b61afSAnirudh Venkataramanan } while (pending && (i++ < ICE_DFLT_IRQ_WORK)); 809940b61afSAnirudh Venkataramanan 810940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, event.msg_buf); 811940b61afSAnirudh Venkataramanan 812940b61afSAnirudh Venkataramanan return pending && (i == ICE_DFLT_IRQ_WORK); 813940b61afSAnirudh Venkataramanan } 814940b61afSAnirudh Venkataramanan 815940b61afSAnirudh Venkataramanan /** 8163d6b640eSAnirudh Venkataramanan * ice_ctrlq_pending - check if there is a difference between ntc and ntu 8173d6b640eSAnirudh Venkataramanan * @hw: pointer to hardware info 8183d6b640eSAnirudh Venkataramanan * @cq: control queue information 8193d6b640eSAnirudh Venkataramanan * 8203d6b640eSAnirudh Venkataramanan * returns true if there are pending messages in a queue, false if there aren't 8213d6b640eSAnirudh Venkataramanan */ 8223d6b640eSAnirudh Venkataramanan static bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq) 8233d6b640eSAnirudh Venkataramanan { 8243d6b640eSAnirudh Venkataramanan u16 ntu; 8253d6b640eSAnirudh Venkataramanan 8263d6b640eSAnirudh Venkataramanan ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask); 8273d6b640eSAnirudh Venkataramanan return cq->rq.next_to_clean != ntu; 8283d6b640eSAnirudh Venkataramanan } 8293d6b640eSAnirudh Venkataramanan 8303d6b640eSAnirudh Venkataramanan /** 831940b61afSAnirudh Venkataramanan * ice_clean_adminq_subtask - clean the AdminQ rings 832940b61afSAnirudh Venkataramanan * @pf: board private structure 833940b61afSAnirudh Venkataramanan */ 834940b61afSAnirudh Venkataramanan static void ice_clean_adminq_subtask(struct ice_pf *pf) 835940b61afSAnirudh Venkataramanan { 836940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 837940b61afSAnirudh Venkataramanan 838940b61afSAnirudh Venkataramanan if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) 839940b61afSAnirudh Venkataramanan return; 840940b61afSAnirudh Venkataramanan 841940b61afSAnirudh Venkataramanan if (__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN)) 842940b61afSAnirudh Venkataramanan return; 843940b61afSAnirudh Venkataramanan 844940b61afSAnirudh Venkataramanan clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); 845940b61afSAnirudh Venkataramanan 8463d6b640eSAnirudh Venkataramanan /* There might be a situation where new messages arrive to a control 8473d6b640eSAnirudh Venkataramanan * queue between processing the last message and clearing the 8483d6b640eSAnirudh Venkataramanan * EVENT_PENDING bit. So before exiting, check queue head again (using 8493d6b640eSAnirudh Venkataramanan * ice_ctrlq_pending) and process new messages if any. 8503d6b640eSAnirudh Venkataramanan */ 8513d6b640eSAnirudh Venkataramanan if (ice_ctrlq_pending(hw, &hw->adminq)) 8523d6b640eSAnirudh Venkataramanan __ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN); 853940b61afSAnirudh Venkataramanan 854940b61afSAnirudh Venkataramanan ice_flush(hw); 855940b61afSAnirudh Venkataramanan } 856940b61afSAnirudh Venkataramanan 857940b61afSAnirudh Venkataramanan /** 85875d2b253SAnirudh Venkataramanan * ice_clean_mailboxq_subtask - clean the MailboxQ rings 85975d2b253SAnirudh Venkataramanan * @pf: board private structure 86075d2b253SAnirudh Venkataramanan */ 86175d2b253SAnirudh Venkataramanan static void ice_clean_mailboxq_subtask(struct ice_pf *pf) 86275d2b253SAnirudh Venkataramanan { 86375d2b253SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 86475d2b253SAnirudh Venkataramanan 86575d2b253SAnirudh Venkataramanan if (!test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state)) 86675d2b253SAnirudh Venkataramanan return; 86775d2b253SAnirudh Venkataramanan 86875d2b253SAnirudh Venkataramanan if (__ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX)) 86975d2b253SAnirudh Venkataramanan return; 87075d2b253SAnirudh Venkataramanan 87175d2b253SAnirudh Venkataramanan clear_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state); 87275d2b253SAnirudh Venkataramanan 87375d2b253SAnirudh Venkataramanan if (ice_ctrlq_pending(hw, &hw->mailboxq)) 87475d2b253SAnirudh Venkataramanan __ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX); 87575d2b253SAnirudh Venkataramanan 87675d2b253SAnirudh Venkataramanan ice_flush(hw); 87775d2b253SAnirudh Venkataramanan } 87875d2b253SAnirudh Venkataramanan 87975d2b253SAnirudh Venkataramanan /** 880940b61afSAnirudh Venkataramanan * ice_service_task_schedule - schedule the service task to wake up 881940b61afSAnirudh Venkataramanan * @pf: board private structure 882940b61afSAnirudh Venkataramanan * 883940b61afSAnirudh Venkataramanan * If not already scheduled, this puts the task into the work queue. 884940b61afSAnirudh Venkataramanan */ 885940b61afSAnirudh Venkataramanan static void ice_service_task_schedule(struct ice_pf *pf) 886940b61afSAnirudh Venkataramanan { 8878d81fa55SAkeem G Abodunrin if (!test_bit(__ICE_SERVICE_DIS, pf->state) && 8880f9d5027SAnirudh Venkataramanan !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) && 8890f9d5027SAnirudh Venkataramanan !test_bit(__ICE_NEEDS_RESTART, pf->state)) 890940b61afSAnirudh Venkataramanan queue_work(ice_wq, &pf->serv_task); 891940b61afSAnirudh Venkataramanan } 892940b61afSAnirudh Venkataramanan 893940b61afSAnirudh Venkataramanan /** 894940b61afSAnirudh Venkataramanan * ice_service_task_complete - finish up the service task 895940b61afSAnirudh Venkataramanan * @pf: board private structure 896940b61afSAnirudh Venkataramanan */ 897940b61afSAnirudh Venkataramanan static void ice_service_task_complete(struct ice_pf *pf) 898940b61afSAnirudh Venkataramanan { 899940b61afSAnirudh Venkataramanan WARN_ON(!test_bit(__ICE_SERVICE_SCHED, pf->state)); 900940b61afSAnirudh Venkataramanan 901940b61afSAnirudh Venkataramanan /* force memory (pf->state) to sync before next service task */ 902940b61afSAnirudh Venkataramanan smp_mb__before_atomic(); 903940b61afSAnirudh Venkataramanan clear_bit(__ICE_SERVICE_SCHED, pf->state); 904940b61afSAnirudh Venkataramanan } 905940b61afSAnirudh Venkataramanan 906940b61afSAnirudh Venkataramanan /** 9078d81fa55SAkeem G Abodunrin * ice_service_task_stop - stop service task and cancel works 9088d81fa55SAkeem G Abodunrin * @pf: board private structure 9098d81fa55SAkeem G Abodunrin */ 9108d81fa55SAkeem G Abodunrin static void ice_service_task_stop(struct ice_pf *pf) 9118d81fa55SAkeem G Abodunrin { 9128d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 9138d81fa55SAkeem G Abodunrin 9148d81fa55SAkeem G Abodunrin if (pf->serv_tmr.function) 9158d81fa55SAkeem G Abodunrin del_timer_sync(&pf->serv_tmr); 9168d81fa55SAkeem G Abodunrin if (pf->serv_task.func) 9178d81fa55SAkeem G Abodunrin cancel_work_sync(&pf->serv_task); 9188d81fa55SAkeem G Abodunrin 9198d81fa55SAkeem G Abodunrin clear_bit(__ICE_SERVICE_SCHED, pf->state); 9208d81fa55SAkeem G Abodunrin } 9218d81fa55SAkeem G Abodunrin 9228d81fa55SAkeem G Abodunrin /** 923940b61afSAnirudh Venkataramanan * ice_service_timer - timer callback to schedule service task 924940b61afSAnirudh Venkataramanan * @t: pointer to timer_list 925940b61afSAnirudh Venkataramanan */ 926940b61afSAnirudh Venkataramanan static void ice_service_timer(struct timer_list *t) 927940b61afSAnirudh Venkataramanan { 928940b61afSAnirudh Venkataramanan struct ice_pf *pf = from_timer(pf, t, serv_tmr); 929940b61afSAnirudh Venkataramanan 930940b61afSAnirudh Venkataramanan mod_timer(&pf->serv_tmr, round_jiffies(pf->serv_tmr_period + jiffies)); 931940b61afSAnirudh Venkataramanan ice_service_task_schedule(pf); 932940b61afSAnirudh Venkataramanan } 933940b61afSAnirudh Venkataramanan 934940b61afSAnirudh Venkataramanan /** 935b3969fd7SSudheer Mogilappagari * ice_handle_mdd_event - handle malicious driver detect event 936b3969fd7SSudheer Mogilappagari * @pf: pointer to the PF structure 937b3969fd7SSudheer Mogilappagari * 938b3969fd7SSudheer Mogilappagari * Called from service task. OICR interrupt handler indicates MDD event 939b3969fd7SSudheer Mogilappagari */ 940b3969fd7SSudheer Mogilappagari static void ice_handle_mdd_event(struct ice_pf *pf) 941b3969fd7SSudheer Mogilappagari { 942b3969fd7SSudheer Mogilappagari struct ice_hw *hw = &pf->hw; 943b3969fd7SSudheer Mogilappagari bool mdd_detected = false; 944b3969fd7SSudheer Mogilappagari u32 reg; 945b3969fd7SSudheer Mogilappagari 946b3969fd7SSudheer Mogilappagari if (!test_bit(__ICE_MDD_EVENT_PENDING, pf->state)) 947b3969fd7SSudheer Mogilappagari return; 948b3969fd7SSudheer Mogilappagari 949b3969fd7SSudheer Mogilappagari /* find what triggered the MDD event */ 950b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_TX_PQM); 951b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_TX_PQM_VALID_M) { 952b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >> 953b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_PF_NUM_S; 954b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >> 955b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_VF_NUM_S; 956b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >> 957b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_MAL_TYPE_S; 958b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >> 959b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_QNUM_S); 960b3969fd7SSudheer Mogilappagari 961b3969fd7SSudheer Mogilappagari if (netif_msg_tx_err(pf)) 962b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", 963b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 964b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_TX_PQM, 0xffffffff); 965b3969fd7SSudheer Mogilappagari mdd_detected = true; 966b3969fd7SSudheer Mogilappagari } 967b3969fd7SSudheer Mogilappagari 968b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_TX_TCLAN); 969b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_TX_TCLAN_VALID_M) { 970b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >> 971b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_PF_NUM_S; 972b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >> 973b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_VF_NUM_S; 974b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >> 975b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_MAL_TYPE_S; 976b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >> 977b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_QNUM_S); 978b3969fd7SSudheer Mogilappagari 979b3969fd7SSudheer Mogilappagari if (netif_msg_rx_err(pf)) 980b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", 981b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 982b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff); 983b3969fd7SSudheer Mogilappagari mdd_detected = true; 984b3969fd7SSudheer Mogilappagari } 985b3969fd7SSudheer Mogilappagari 986b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_RX); 987b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_RX_VALID_M) { 988b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >> 989b3969fd7SSudheer Mogilappagari GL_MDET_RX_PF_NUM_S; 990b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >> 991b3969fd7SSudheer Mogilappagari GL_MDET_RX_VF_NUM_S; 992b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >> 993b3969fd7SSudheer Mogilappagari GL_MDET_RX_MAL_TYPE_S; 994b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_RX_QNUM_M) >> 995b3969fd7SSudheer Mogilappagari GL_MDET_RX_QNUM_S); 996b3969fd7SSudheer Mogilappagari 997b3969fd7SSudheer Mogilappagari if (netif_msg_rx_err(pf)) 998b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n", 999b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 1000b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_RX, 0xffffffff); 1001b3969fd7SSudheer Mogilappagari mdd_detected = true; 1002b3969fd7SSudheer Mogilappagari } 1003b3969fd7SSudheer Mogilappagari 1004b3969fd7SSudheer Mogilappagari if (mdd_detected) { 1005b3969fd7SSudheer Mogilappagari bool pf_mdd_detected = false; 1006b3969fd7SSudheer Mogilappagari 1007b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_TX_PQM); 1008b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_TX_PQM_VALID_M) { 1009b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_TX_PQM, 0xFFFF); 1010b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n"); 1011b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1012b3969fd7SSudheer Mogilappagari } 1013b3969fd7SSudheer Mogilappagari 1014b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_TX_TCLAN); 1015b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_TX_TCLAN_VALID_M) { 1016b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF); 1017b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n"); 1018b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1019b3969fd7SSudheer Mogilappagari } 1020b3969fd7SSudheer Mogilappagari 1021b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_RX); 1022b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_RX_VALID_M) { 1023b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_RX, 0xFFFF); 1024b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "RX driver issue detected, PF reset issued\n"); 1025b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1026b3969fd7SSudheer Mogilappagari } 1027b3969fd7SSudheer Mogilappagari /* Queue belongs to the PF initiate a reset */ 1028b3969fd7SSudheer Mogilappagari if (pf_mdd_detected) { 1029b3969fd7SSudheer Mogilappagari set_bit(__ICE_NEEDS_RESTART, pf->state); 1030b3969fd7SSudheer Mogilappagari ice_service_task_schedule(pf); 1031b3969fd7SSudheer Mogilappagari } 1032b3969fd7SSudheer Mogilappagari } 1033b3969fd7SSudheer Mogilappagari 1034b3969fd7SSudheer Mogilappagari /* re-enable MDD interrupt cause */ 1035b3969fd7SSudheer Mogilappagari clear_bit(__ICE_MDD_EVENT_PENDING, pf->state); 1036b3969fd7SSudheer Mogilappagari reg = rd32(hw, PFINT_OICR_ENA); 1037b3969fd7SSudheer Mogilappagari reg |= PFINT_OICR_MAL_DETECT_M; 1038b3969fd7SSudheer Mogilappagari wr32(hw, PFINT_OICR_ENA, reg); 1039b3969fd7SSudheer Mogilappagari ice_flush(hw); 1040b3969fd7SSudheer Mogilappagari } 1041b3969fd7SSudheer Mogilappagari 1042b3969fd7SSudheer Mogilappagari /** 1043940b61afSAnirudh Venkataramanan * ice_service_task - manage and run subtasks 1044940b61afSAnirudh Venkataramanan * @work: pointer to work_struct contained by the PF struct 1045940b61afSAnirudh Venkataramanan */ 1046940b61afSAnirudh Venkataramanan static void ice_service_task(struct work_struct *work) 1047940b61afSAnirudh Venkataramanan { 1048940b61afSAnirudh Venkataramanan struct ice_pf *pf = container_of(work, struct ice_pf, serv_task); 1049940b61afSAnirudh Venkataramanan unsigned long start_time = jiffies; 1050940b61afSAnirudh Venkataramanan 1051940b61afSAnirudh Venkataramanan /* subtasks */ 10520b28b702SAnirudh Venkataramanan 10530b28b702SAnirudh Venkataramanan /* process reset requests first */ 10540b28b702SAnirudh Venkataramanan ice_reset_subtask(pf); 10550b28b702SAnirudh Venkataramanan 10560f9d5027SAnirudh Venkataramanan /* bail if a reset/recovery cycle is pending or rebuild failed */ 10575df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state) || 10580f9d5027SAnirudh Venkataramanan test_bit(__ICE_SUSPENDED, pf->state) || 10590f9d5027SAnirudh Venkataramanan test_bit(__ICE_NEEDS_RESTART, pf->state)) { 10600b28b702SAnirudh Venkataramanan ice_service_task_complete(pf); 10610b28b702SAnirudh Venkataramanan return; 10620b28b702SAnirudh Venkataramanan } 10630b28b702SAnirudh Venkataramanan 1064b3969fd7SSudheer Mogilappagari ice_check_for_hang_subtask(pf); 1065e94d4478SAnirudh Venkataramanan ice_sync_fltr_subtask(pf); 1066b3969fd7SSudheer Mogilappagari ice_handle_mdd_event(pf); 1067fcea6f3dSAnirudh Venkataramanan ice_watchdog_subtask(pf); 1068940b61afSAnirudh Venkataramanan ice_clean_adminq_subtask(pf); 106975d2b253SAnirudh Venkataramanan ice_clean_mailboxq_subtask(pf); 1070940b61afSAnirudh Venkataramanan 1071940b61afSAnirudh Venkataramanan /* Clear __ICE_SERVICE_SCHED flag to allow scheduling next event */ 1072940b61afSAnirudh Venkataramanan ice_service_task_complete(pf); 1073940b61afSAnirudh Venkataramanan 1074940b61afSAnirudh Venkataramanan /* If the tasks have taken longer than one service timer period 1075940b61afSAnirudh Venkataramanan * or there is more work to be done, reset the service timer to 1076940b61afSAnirudh Venkataramanan * schedule the service task now. 1077940b61afSAnirudh Venkataramanan */ 1078940b61afSAnirudh Venkataramanan if (time_after(jiffies, (start_time + pf->serv_tmr_period)) || 1079b3969fd7SSudheer Mogilappagari test_bit(__ICE_MDD_EVENT_PENDING, pf->state) || 108075d2b253SAnirudh Venkataramanan test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state) || 1081940b61afSAnirudh Venkataramanan test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) 1082940b61afSAnirudh Venkataramanan mod_timer(&pf->serv_tmr, jiffies); 1083940b61afSAnirudh Venkataramanan } 1084940b61afSAnirudh Venkataramanan 1085837f08fdSAnirudh Venkataramanan /** 1086f31e4b6fSAnirudh Venkataramanan * ice_set_ctrlq_len - helper function to set controlq length 1087f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw instance 1088f31e4b6fSAnirudh Venkataramanan */ 1089f31e4b6fSAnirudh Venkataramanan static void ice_set_ctrlq_len(struct ice_hw *hw) 1090f31e4b6fSAnirudh Venkataramanan { 1091f31e4b6fSAnirudh Venkataramanan hw->adminq.num_rq_entries = ICE_AQ_LEN; 1092f31e4b6fSAnirudh Venkataramanan hw->adminq.num_sq_entries = ICE_AQ_LEN; 1093f31e4b6fSAnirudh Venkataramanan hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN; 1094f31e4b6fSAnirudh Venkataramanan hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN; 109575d2b253SAnirudh Venkataramanan hw->mailboxq.num_rq_entries = ICE_MBXQ_LEN; 109675d2b253SAnirudh Venkataramanan hw->mailboxq.num_sq_entries = ICE_MBXQ_LEN; 109775d2b253SAnirudh Venkataramanan hw->mailboxq.rq_buf_size = ICE_MBXQ_MAX_BUF_LEN; 109875d2b253SAnirudh Venkataramanan hw->mailboxq.sq_buf_size = ICE_MBXQ_MAX_BUF_LEN; 1099f31e4b6fSAnirudh Venkataramanan } 1100f31e4b6fSAnirudh Venkataramanan 1101f31e4b6fSAnirudh Venkataramanan /** 1102cdedef59SAnirudh Venkataramanan * ice_irq_affinity_notify - Callback for affinity changes 1103cdedef59SAnirudh Venkataramanan * @notify: context as to what irq was changed 1104cdedef59SAnirudh Venkataramanan * @mask: the new affinity mask 1105cdedef59SAnirudh Venkataramanan * 1106cdedef59SAnirudh Venkataramanan * This is a callback function used by the irq_set_affinity_notifier function 1107cdedef59SAnirudh Venkataramanan * so that we may register to receive changes to the irq affinity masks. 1108cdedef59SAnirudh Venkataramanan */ 1109cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_notify(struct irq_affinity_notify *notify, 1110cdedef59SAnirudh Venkataramanan const cpumask_t *mask) 1111cdedef59SAnirudh Venkataramanan { 1112cdedef59SAnirudh Venkataramanan struct ice_q_vector *q_vector = 1113cdedef59SAnirudh Venkataramanan container_of(notify, struct ice_q_vector, affinity_notify); 1114cdedef59SAnirudh Venkataramanan 1115cdedef59SAnirudh Venkataramanan cpumask_copy(&q_vector->affinity_mask, mask); 1116cdedef59SAnirudh Venkataramanan } 1117cdedef59SAnirudh Venkataramanan 1118cdedef59SAnirudh Venkataramanan /** 1119cdedef59SAnirudh Venkataramanan * ice_irq_affinity_release - Callback for affinity notifier release 1120cdedef59SAnirudh Venkataramanan * @ref: internal core kernel usage 1121cdedef59SAnirudh Venkataramanan * 1122cdedef59SAnirudh Venkataramanan * This is a callback function used by the irq_set_affinity_notifier function 1123cdedef59SAnirudh Venkataramanan * to inform the current notification subscriber that they will no longer 1124cdedef59SAnirudh Venkataramanan * receive notifications. 1125cdedef59SAnirudh Venkataramanan */ 1126cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_release(struct kref __always_unused *ref) {} 1127cdedef59SAnirudh Venkataramanan 1128cdedef59SAnirudh Venkataramanan /** 1129cdedef59SAnirudh Venkataramanan * ice_vsi_ena_irq - Enable IRQ for the given VSI 1130cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 1131cdedef59SAnirudh Venkataramanan */ 1132cdedef59SAnirudh Venkataramanan static int ice_vsi_ena_irq(struct ice_vsi *vsi) 1133cdedef59SAnirudh Venkataramanan { 1134cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1135cdedef59SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1136cdedef59SAnirudh Venkataramanan 1137cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 1138cdedef59SAnirudh Venkataramanan int i; 1139cdedef59SAnirudh Venkataramanan 1140cdedef59SAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++) 1141cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]); 1142cdedef59SAnirudh Venkataramanan } 1143cdedef59SAnirudh Venkataramanan 1144cdedef59SAnirudh Venkataramanan ice_flush(hw); 1145cdedef59SAnirudh Venkataramanan return 0; 1146cdedef59SAnirudh Venkataramanan } 1147cdedef59SAnirudh Venkataramanan 1148cdedef59SAnirudh Venkataramanan /** 1149cdedef59SAnirudh Venkataramanan * ice_vsi_req_irq_msix - get MSI-X vectors from the OS for the VSI 1150cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 1151cdedef59SAnirudh Venkataramanan * @basename: name for the vector 1152cdedef59SAnirudh Venkataramanan */ 1153cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) 1154cdedef59SAnirudh Venkataramanan { 1155cdedef59SAnirudh Venkataramanan int q_vectors = vsi->num_q_vectors; 1156cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1157eb0208ecSPreethi Banala int base = vsi->sw_base_vector; 1158cdedef59SAnirudh Venkataramanan int rx_int_idx = 0; 1159cdedef59SAnirudh Venkataramanan int tx_int_idx = 0; 1160cdedef59SAnirudh Venkataramanan int vector, err; 1161cdedef59SAnirudh Venkataramanan int irq_num; 1162cdedef59SAnirudh Venkataramanan 1163cdedef59SAnirudh Venkataramanan for (vector = 0; vector < q_vectors; vector++) { 1164cdedef59SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[vector]; 1165cdedef59SAnirudh Venkataramanan 1166cdedef59SAnirudh Venkataramanan irq_num = pf->msix_entries[base + vector].vector; 1167cdedef59SAnirudh Venkataramanan 1168cdedef59SAnirudh Venkataramanan if (q_vector->tx.ring && q_vector->rx.ring) { 1169cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1170cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "TxRx", rx_int_idx++); 1171cdedef59SAnirudh Venkataramanan tx_int_idx++; 1172cdedef59SAnirudh Venkataramanan } else if (q_vector->rx.ring) { 1173cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1174cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "rx", rx_int_idx++); 1175cdedef59SAnirudh Venkataramanan } else if (q_vector->tx.ring) { 1176cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1177cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "tx", tx_int_idx++); 1178cdedef59SAnirudh Venkataramanan } else { 1179cdedef59SAnirudh Venkataramanan /* skip this unused q_vector */ 1180cdedef59SAnirudh Venkataramanan continue; 1181cdedef59SAnirudh Venkataramanan } 1182cdedef59SAnirudh Venkataramanan err = devm_request_irq(&pf->pdev->dev, 1183cdedef59SAnirudh Venkataramanan pf->msix_entries[base + vector].vector, 1184cdedef59SAnirudh Venkataramanan vsi->irq_handler, 0, q_vector->name, 1185cdedef59SAnirudh Venkataramanan q_vector); 1186cdedef59SAnirudh Venkataramanan if (err) { 1187cdedef59SAnirudh Venkataramanan netdev_err(vsi->netdev, 1188cdedef59SAnirudh Venkataramanan "MSIX request_irq failed, error: %d\n", err); 1189cdedef59SAnirudh Venkataramanan goto free_q_irqs; 1190cdedef59SAnirudh Venkataramanan } 1191cdedef59SAnirudh Venkataramanan 1192cdedef59SAnirudh Venkataramanan /* register for affinity change notifications */ 1193cdedef59SAnirudh Venkataramanan q_vector->affinity_notify.notify = ice_irq_affinity_notify; 1194cdedef59SAnirudh Venkataramanan q_vector->affinity_notify.release = ice_irq_affinity_release; 1195cdedef59SAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify); 1196cdedef59SAnirudh Venkataramanan 1197cdedef59SAnirudh Venkataramanan /* assign the mask for this irq */ 1198cdedef59SAnirudh Venkataramanan irq_set_affinity_hint(irq_num, &q_vector->affinity_mask); 1199cdedef59SAnirudh Venkataramanan } 1200cdedef59SAnirudh Venkataramanan 1201cdedef59SAnirudh Venkataramanan vsi->irqs_ready = true; 1202cdedef59SAnirudh Venkataramanan return 0; 1203cdedef59SAnirudh Venkataramanan 1204cdedef59SAnirudh Venkataramanan free_q_irqs: 1205cdedef59SAnirudh Venkataramanan while (vector) { 1206cdedef59SAnirudh Venkataramanan vector--; 1207cdedef59SAnirudh Venkataramanan irq_num = pf->msix_entries[base + vector].vector, 1208cdedef59SAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 1209cdedef59SAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 1210cdedef59SAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, &vsi->q_vectors[vector]); 1211cdedef59SAnirudh Venkataramanan } 1212cdedef59SAnirudh Venkataramanan return err; 1213cdedef59SAnirudh Venkataramanan } 1214cdedef59SAnirudh Venkataramanan 1215cdedef59SAnirudh Venkataramanan /** 1216940b61afSAnirudh Venkataramanan * ice_ena_misc_vector - enable the non-queue interrupts 1217940b61afSAnirudh Venkataramanan * @pf: board private structure 1218940b61afSAnirudh Venkataramanan */ 1219940b61afSAnirudh Venkataramanan static void ice_ena_misc_vector(struct ice_pf *pf) 1220940b61afSAnirudh Venkataramanan { 1221940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1222940b61afSAnirudh Venkataramanan u32 val; 1223940b61afSAnirudh Venkataramanan 1224940b61afSAnirudh Venkataramanan /* clear things first */ 1225940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, 0); /* disable all */ 1226940b61afSAnirudh Venkataramanan rd32(hw, PFINT_OICR); /* read to clear */ 1227940b61afSAnirudh Venkataramanan 12283bcd7fa3SBruce Allan val = (PFINT_OICR_ECC_ERR_M | 1229940b61afSAnirudh Venkataramanan PFINT_OICR_MAL_DETECT_M | 1230940b61afSAnirudh Venkataramanan PFINT_OICR_GRST_M | 1231940b61afSAnirudh Venkataramanan PFINT_OICR_PCI_EXCEPTION_M | 12323bcd7fa3SBruce Allan PFINT_OICR_HMC_ERR_M | 12333bcd7fa3SBruce Allan PFINT_OICR_PE_CRITERR_M); 1234940b61afSAnirudh Venkataramanan 1235940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, val); 1236940b61afSAnirudh Venkataramanan 1237940b61afSAnirudh Venkataramanan /* SW_ITR_IDX = 0, but don't change INTENA */ 1238eb0208ecSPreethi Banala wr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx), 1239940b61afSAnirudh Venkataramanan GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); 1240940b61afSAnirudh Venkataramanan } 1241940b61afSAnirudh Venkataramanan 1242940b61afSAnirudh Venkataramanan /** 1243940b61afSAnirudh Venkataramanan * ice_misc_intr - misc interrupt handler 1244940b61afSAnirudh Venkataramanan * @irq: interrupt number 1245940b61afSAnirudh Venkataramanan * @data: pointer to a q_vector 1246940b61afSAnirudh Venkataramanan */ 1247940b61afSAnirudh Venkataramanan static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) 1248940b61afSAnirudh Venkataramanan { 1249940b61afSAnirudh Venkataramanan struct ice_pf *pf = (struct ice_pf *)data; 1250940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1251940b61afSAnirudh Venkataramanan irqreturn_t ret = IRQ_NONE; 1252940b61afSAnirudh Venkataramanan u32 oicr, ena_mask; 1253940b61afSAnirudh Venkataramanan 1254940b61afSAnirudh Venkataramanan set_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); 125575d2b253SAnirudh Venkataramanan set_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state); 1256940b61afSAnirudh Venkataramanan 1257940b61afSAnirudh Venkataramanan oicr = rd32(hw, PFINT_OICR); 1258940b61afSAnirudh Venkataramanan ena_mask = rd32(hw, PFINT_OICR_ENA); 1259940b61afSAnirudh Venkataramanan 1260b3969fd7SSudheer Mogilappagari if (oicr & PFINT_OICR_MAL_DETECT_M) { 1261b3969fd7SSudheer Mogilappagari ena_mask &= ~PFINT_OICR_MAL_DETECT_M; 1262b3969fd7SSudheer Mogilappagari set_bit(__ICE_MDD_EVENT_PENDING, pf->state); 1263b3969fd7SSudheer Mogilappagari } 1264b3969fd7SSudheer Mogilappagari 12650b28b702SAnirudh Venkataramanan if (oicr & PFINT_OICR_GRST_M) { 12660b28b702SAnirudh Venkataramanan u32 reset; 1267b3969fd7SSudheer Mogilappagari 12680b28b702SAnirudh Venkataramanan /* we have a reset warning */ 12690b28b702SAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_GRST_M; 12700b28b702SAnirudh Venkataramanan reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >> 12710b28b702SAnirudh Venkataramanan GLGEN_RSTAT_RESET_TYPE_S; 12720b28b702SAnirudh Venkataramanan 12730b28b702SAnirudh Venkataramanan if (reset == ICE_RESET_CORER) 12740b28b702SAnirudh Venkataramanan pf->corer_count++; 12750b28b702SAnirudh Venkataramanan else if (reset == ICE_RESET_GLOBR) 12760b28b702SAnirudh Venkataramanan pf->globr_count++; 1277ca4929b6SBrett Creeley else if (reset == ICE_RESET_EMPR) 12780b28b702SAnirudh Venkataramanan pf->empr_count++; 1279ca4929b6SBrett Creeley else 1280ca4929b6SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid reset type %d\n", 1281ca4929b6SBrett Creeley reset); 12820b28b702SAnirudh Venkataramanan 12830b28b702SAnirudh Venkataramanan /* If a reset cycle isn't already in progress, we set a bit in 12840b28b702SAnirudh Venkataramanan * pf->state so that the service task can start a reset/rebuild. 12850b28b702SAnirudh Venkataramanan * We also make note of which reset happened so that peer 12860b28b702SAnirudh Venkataramanan * devices/drivers can be informed. 12870b28b702SAnirudh Venkataramanan */ 12885df7e45dSDave Ertman if (!test_and_set_bit(__ICE_RESET_OICR_RECV, pf->state)) { 12890b28b702SAnirudh Venkataramanan if (reset == ICE_RESET_CORER) 12900b28b702SAnirudh Venkataramanan set_bit(__ICE_CORER_RECV, pf->state); 12910b28b702SAnirudh Venkataramanan else if (reset == ICE_RESET_GLOBR) 12920b28b702SAnirudh Venkataramanan set_bit(__ICE_GLOBR_RECV, pf->state); 12930b28b702SAnirudh Venkataramanan else 12940b28b702SAnirudh Venkataramanan set_bit(__ICE_EMPR_RECV, pf->state); 12950b28b702SAnirudh Venkataramanan 1296fd2a9817SAnirudh Venkataramanan /* There are couple of different bits at play here. 1297fd2a9817SAnirudh Venkataramanan * hw->reset_ongoing indicates whether the hardware is 1298fd2a9817SAnirudh Venkataramanan * in reset. This is set to true when a reset interrupt 1299fd2a9817SAnirudh Venkataramanan * is received and set back to false after the driver 1300fd2a9817SAnirudh Venkataramanan * has determined that the hardware is out of reset. 1301fd2a9817SAnirudh Venkataramanan * 13025df7e45dSDave Ertman * __ICE_RESET_OICR_RECV in pf->state indicates 1303fd2a9817SAnirudh Venkataramanan * that a post reset rebuild is required before the 1304fd2a9817SAnirudh Venkataramanan * driver is operational again. This is set above. 1305fd2a9817SAnirudh Venkataramanan * 1306fd2a9817SAnirudh Venkataramanan * As this is the start of the reset/rebuild cycle, set 1307fd2a9817SAnirudh Venkataramanan * both to indicate that. 1308fd2a9817SAnirudh Venkataramanan */ 1309fd2a9817SAnirudh Venkataramanan hw->reset_ongoing = true; 13100b28b702SAnirudh Venkataramanan } 13110b28b702SAnirudh Venkataramanan } 13120b28b702SAnirudh Venkataramanan 1313940b61afSAnirudh Venkataramanan if (oicr & PFINT_OICR_HMC_ERR_M) { 1314940b61afSAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_HMC_ERR_M; 1315940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 1316940b61afSAnirudh Venkataramanan "HMC Error interrupt - info 0x%x, data 0x%x\n", 1317940b61afSAnirudh Venkataramanan rd32(hw, PFHMC_ERRORINFO), 1318940b61afSAnirudh Venkataramanan rd32(hw, PFHMC_ERRORDATA)); 1319940b61afSAnirudh Venkataramanan } 1320940b61afSAnirudh Venkataramanan 1321940b61afSAnirudh Venkataramanan /* Report and mask off any remaining unexpected interrupts */ 1322940b61afSAnirudh Venkataramanan oicr &= ena_mask; 1323940b61afSAnirudh Venkataramanan if (oicr) { 1324940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "unhandled interrupt oicr=0x%08x\n", 1325940b61afSAnirudh Venkataramanan oicr); 1326940b61afSAnirudh Venkataramanan /* If a critical error is pending there is no choice but to 1327940b61afSAnirudh Venkataramanan * reset the device. 1328940b61afSAnirudh Venkataramanan */ 1329940b61afSAnirudh Venkataramanan if (oicr & (PFINT_OICR_PE_CRITERR_M | 1330940b61afSAnirudh Venkataramanan PFINT_OICR_PCI_EXCEPTION_M | 13310b28b702SAnirudh Venkataramanan PFINT_OICR_ECC_ERR_M)) { 1332940b61afSAnirudh Venkataramanan set_bit(__ICE_PFR_REQ, pf->state); 13330b28b702SAnirudh Venkataramanan ice_service_task_schedule(pf); 13340b28b702SAnirudh Venkataramanan } 1335940b61afSAnirudh Venkataramanan ena_mask &= ~oicr; 1336940b61afSAnirudh Venkataramanan } 1337940b61afSAnirudh Venkataramanan ret = IRQ_HANDLED; 1338940b61afSAnirudh Venkataramanan 1339940b61afSAnirudh Venkataramanan /* re-enable interrupt causes that are not handled during this pass */ 1340940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, ena_mask); 1341940b61afSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) { 1342940b61afSAnirudh Venkataramanan ice_service_task_schedule(pf); 1343cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, NULL, NULL); 1344940b61afSAnirudh Venkataramanan } 1345940b61afSAnirudh Venkataramanan 1346940b61afSAnirudh Venkataramanan return ret; 1347940b61afSAnirudh Venkataramanan } 1348940b61afSAnirudh Venkataramanan 1349940b61afSAnirudh Venkataramanan /** 1350940b61afSAnirudh Venkataramanan * ice_free_irq_msix_misc - Unroll misc vector setup 1351940b61afSAnirudh Venkataramanan * @pf: board private structure 1352940b61afSAnirudh Venkataramanan */ 1353940b61afSAnirudh Venkataramanan static void ice_free_irq_msix_misc(struct ice_pf *pf) 1354940b61afSAnirudh Venkataramanan { 1355940b61afSAnirudh Venkataramanan /* disable OICR interrupt */ 1356940b61afSAnirudh Venkataramanan wr32(&pf->hw, PFINT_OICR_ENA, 0); 1357940b61afSAnirudh Venkataramanan ice_flush(&pf->hw); 1358940b61afSAnirudh Venkataramanan 1359940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { 1360eb0208ecSPreethi Banala synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector); 1361940b61afSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, 1362eb0208ecSPreethi Banala pf->msix_entries[pf->sw_oicr_idx].vector, pf); 1363940b61afSAnirudh Venkataramanan } 1364940b61afSAnirudh Venkataramanan 1365eb0208ecSPreethi Banala pf->num_avail_sw_msix += 1; 1366eb0208ecSPreethi Banala ice_free_res(pf->sw_irq_tracker, pf->sw_oicr_idx, ICE_RES_MISC_VEC_ID); 1367eb0208ecSPreethi Banala pf->num_avail_hw_msix += 1; 1368eb0208ecSPreethi Banala ice_free_res(pf->hw_irq_tracker, pf->hw_oicr_idx, ICE_RES_MISC_VEC_ID); 1369940b61afSAnirudh Venkataramanan } 1370940b61afSAnirudh Venkataramanan 1371940b61afSAnirudh Venkataramanan /** 1372940b61afSAnirudh Venkataramanan * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events 1373940b61afSAnirudh Venkataramanan * @pf: board private structure 1374940b61afSAnirudh Venkataramanan * 1375940b61afSAnirudh Venkataramanan * This sets up the handler for MSIX 0, which is used to manage the 1376940b61afSAnirudh Venkataramanan * non-queue interrupts, e.g. AdminQ and errors. This is not used 1377940b61afSAnirudh Venkataramanan * when in MSI or Legacy interrupt mode. 1378940b61afSAnirudh Venkataramanan */ 1379940b61afSAnirudh Venkataramanan static int ice_req_irq_msix_misc(struct ice_pf *pf) 1380940b61afSAnirudh Venkataramanan { 1381940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1382940b61afSAnirudh Venkataramanan int oicr_idx, err = 0; 1383940b61afSAnirudh Venkataramanan u8 itr_gran; 1384940b61afSAnirudh Venkataramanan u32 val; 1385940b61afSAnirudh Venkataramanan 1386940b61afSAnirudh Venkataramanan if (!pf->int_name[0]) 1387940b61afSAnirudh Venkataramanan snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", 1388940b61afSAnirudh Venkataramanan dev_driver_string(&pf->pdev->dev), 1389940b61afSAnirudh Venkataramanan dev_name(&pf->pdev->dev)); 1390940b61afSAnirudh Venkataramanan 13910b28b702SAnirudh Venkataramanan /* Do not request IRQ but do enable OICR interrupt since settings are 13920b28b702SAnirudh Venkataramanan * lost during reset. Note that this function is called only during 13930b28b702SAnirudh Venkataramanan * rebuild path and not while reset is in progress. 13940b28b702SAnirudh Venkataramanan */ 13955df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) 13960b28b702SAnirudh Venkataramanan goto skip_req_irq; 13970b28b702SAnirudh Venkataramanan 1398eb0208ecSPreethi Banala /* reserve one vector in sw_irq_tracker for misc interrupts */ 1399eb0208ecSPreethi Banala oicr_idx = ice_get_res(pf, pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1400940b61afSAnirudh Venkataramanan if (oicr_idx < 0) 1401940b61afSAnirudh Venkataramanan return oicr_idx; 1402940b61afSAnirudh Venkataramanan 1403eb0208ecSPreethi Banala pf->num_avail_sw_msix -= 1; 1404eb0208ecSPreethi Banala pf->sw_oicr_idx = oicr_idx; 1405eb0208ecSPreethi Banala 1406eb0208ecSPreethi Banala /* reserve one vector in hw_irq_tracker for misc interrupts */ 1407eb0208ecSPreethi Banala oicr_idx = ice_get_res(pf, pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1408eb0208ecSPreethi Banala if (oicr_idx < 0) { 1409eb0208ecSPreethi Banala ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1410eb0208ecSPreethi Banala pf->num_avail_sw_msix += 1; 1411eb0208ecSPreethi Banala return oicr_idx; 1412eb0208ecSPreethi Banala } 1413eb0208ecSPreethi Banala pf->num_avail_hw_msix -= 1; 1414eb0208ecSPreethi Banala pf->hw_oicr_idx = oicr_idx; 1415940b61afSAnirudh Venkataramanan 1416940b61afSAnirudh Venkataramanan err = devm_request_irq(&pf->pdev->dev, 1417eb0208ecSPreethi Banala pf->msix_entries[pf->sw_oicr_idx].vector, 1418940b61afSAnirudh Venkataramanan ice_misc_intr, 0, pf->int_name, pf); 1419940b61afSAnirudh Venkataramanan if (err) { 1420940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1421940b61afSAnirudh Venkataramanan "devm_request_irq for %s failed: %d\n", 1422940b61afSAnirudh Venkataramanan pf->int_name, err); 1423eb0208ecSPreethi Banala ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1424eb0208ecSPreethi Banala pf->num_avail_sw_msix += 1; 1425eb0208ecSPreethi Banala ice_free_res(pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1426eb0208ecSPreethi Banala pf->num_avail_hw_msix += 1; 1427940b61afSAnirudh Venkataramanan return err; 1428940b61afSAnirudh Venkataramanan } 1429940b61afSAnirudh Venkataramanan 14300b28b702SAnirudh Venkataramanan skip_req_irq: 1431940b61afSAnirudh Venkataramanan ice_ena_misc_vector(pf); 1432940b61afSAnirudh Venkataramanan 1433eb0208ecSPreethi Banala val = ((pf->hw_oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | 14344381147dSAnirudh Venkataramanan PFINT_OICR_CTL_CAUSE_ENA_M); 1435940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_CTL, val); 1436940b61afSAnirudh Venkataramanan 1437940b61afSAnirudh Venkataramanan /* This enables Admin queue Interrupt causes */ 1438eb0208ecSPreethi Banala val = ((pf->hw_oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | 14394381147dSAnirudh Venkataramanan PFINT_FW_CTL_CAUSE_ENA_M); 1440940b61afSAnirudh Venkataramanan wr32(hw, PFINT_FW_CTL, val); 1441940b61afSAnirudh Venkataramanan 144275d2b253SAnirudh Venkataramanan /* This enables Mailbox queue Interrupt causes */ 144375d2b253SAnirudh Venkataramanan val = ((pf->hw_oicr_idx & PFINT_MBX_CTL_MSIX_INDX_M) | 144475d2b253SAnirudh Venkataramanan PFINT_MBX_CTL_CAUSE_ENA_M); 144575d2b253SAnirudh Venkataramanan wr32(hw, PFINT_MBX_CTL, val); 144675d2b253SAnirudh Venkataramanan 14479e4ab4c2SBrett Creeley itr_gran = hw->itr_gran; 1448940b61afSAnirudh Venkataramanan 1449eb0208ecSPreethi Banala wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), 1450940b61afSAnirudh Venkataramanan ITR_TO_REG(ICE_ITR_8K, itr_gran)); 1451940b61afSAnirudh Venkataramanan 1452940b61afSAnirudh Venkataramanan ice_flush(hw); 1453cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, NULL, NULL); 1454940b61afSAnirudh Venkataramanan 1455940b61afSAnirudh Venkataramanan return 0; 1456940b61afSAnirudh Venkataramanan } 1457940b61afSAnirudh Venkataramanan 1458940b61afSAnirudh Venkataramanan /** 1459df0f8479SAnirudh Venkataramanan * ice_napi_del - Remove NAPI handler for the VSI 1460df0f8479SAnirudh Venkataramanan * @vsi: VSI for which NAPI handler is to be removed 14613a858ba3SAnirudh Venkataramanan */ 1462df0f8479SAnirudh Venkataramanan static void ice_napi_del(struct ice_vsi *vsi) 14633a858ba3SAnirudh Venkataramanan { 14643a858ba3SAnirudh Venkataramanan int v_idx; 14653a858ba3SAnirudh Venkataramanan 1466df0f8479SAnirudh Venkataramanan if (!vsi->netdev) 1467df0f8479SAnirudh Venkataramanan return; 1468df0f8479SAnirudh Venkataramanan 14693a858ba3SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1470df0f8479SAnirudh Venkataramanan netif_napi_del(&vsi->q_vectors[v_idx]->napi); 14713a858ba3SAnirudh Venkataramanan } 14723a858ba3SAnirudh Venkataramanan 14733a858ba3SAnirudh Venkataramanan /** 1474df0f8479SAnirudh Venkataramanan * ice_napi_add - register NAPI handler for the VSI 1475df0f8479SAnirudh Venkataramanan * @vsi: VSI for which NAPI handler is to be registered 1476df0f8479SAnirudh Venkataramanan * 1477df0f8479SAnirudh Venkataramanan * This function is only called in the driver's load path. Registering the NAPI 1478df0f8479SAnirudh Venkataramanan * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume, 1479df0f8479SAnirudh Venkataramanan * reset/rebuild, etc.) 1480df0f8479SAnirudh Venkataramanan */ 1481df0f8479SAnirudh Venkataramanan static void ice_napi_add(struct ice_vsi *vsi) 1482df0f8479SAnirudh Venkataramanan { 1483df0f8479SAnirudh Venkataramanan int v_idx; 1484df0f8479SAnirudh Venkataramanan 1485df0f8479SAnirudh Venkataramanan if (!vsi->netdev) 1486df0f8479SAnirudh Venkataramanan return; 1487df0f8479SAnirudh Venkataramanan 1488df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1489df0f8479SAnirudh Venkataramanan netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi, 1490df0f8479SAnirudh Venkataramanan ice_napi_poll, NAPI_POLL_WEIGHT); 1491df0f8479SAnirudh Venkataramanan } 1492df0f8479SAnirudh Venkataramanan 1493df0f8479SAnirudh Venkataramanan /** 1494df0f8479SAnirudh Venkataramanan * ice_cfg_netdev - Allocate, configure and register a netdev 1495df0f8479SAnirudh Venkataramanan * @vsi: the VSI associated with the new netdev 14963a858ba3SAnirudh Venkataramanan * 14973a858ba3SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 14983a858ba3SAnirudh Venkataramanan */ 14993a858ba3SAnirudh Venkataramanan static int ice_cfg_netdev(struct ice_vsi *vsi) 15003a858ba3SAnirudh Venkataramanan { 1501d76a60baSAnirudh Venkataramanan netdev_features_t csumo_features; 1502d76a60baSAnirudh Venkataramanan netdev_features_t vlano_features; 1503d76a60baSAnirudh Venkataramanan netdev_features_t dflt_features; 1504d76a60baSAnirudh Venkataramanan netdev_features_t tso_features; 15053a858ba3SAnirudh Venkataramanan struct ice_netdev_priv *np; 15063a858ba3SAnirudh Venkataramanan struct net_device *netdev; 15073a858ba3SAnirudh Venkataramanan u8 mac_addr[ETH_ALEN]; 1508df0f8479SAnirudh Venkataramanan int err; 15093a858ba3SAnirudh Venkataramanan 15103a858ba3SAnirudh Venkataramanan netdev = alloc_etherdev_mqs(sizeof(struct ice_netdev_priv), 15113a858ba3SAnirudh Venkataramanan vsi->alloc_txq, vsi->alloc_rxq); 15123a858ba3SAnirudh Venkataramanan if (!netdev) 15133a858ba3SAnirudh Venkataramanan return -ENOMEM; 15143a858ba3SAnirudh Venkataramanan 15153a858ba3SAnirudh Venkataramanan vsi->netdev = netdev; 15163a858ba3SAnirudh Venkataramanan np = netdev_priv(netdev); 15173a858ba3SAnirudh Venkataramanan np->vsi = vsi; 15183a858ba3SAnirudh Venkataramanan 1519d76a60baSAnirudh Venkataramanan dflt_features = NETIF_F_SG | 15203a858ba3SAnirudh Venkataramanan NETIF_F_HIGHDMA | 15213a858ba3SAnirudh Venkataramanan NETIF_F_RXHASH; 15223a858ba3SAnirudh Venkataramanan 1523d76a60baSAnirudh Venkataramanan csumo_features = NETIF_F_RXCSUM | 1524d76a60baSAnirudh Venkataramanan NETIF_F_IP_CSUM | 1525d76a60baSAnirudh Venkataramanan NETIF_F_IPV6_CSUM; 1526d76a60baSAnirudh Venkataramanan 1527d76a60baSAnirudh Venkataramanan vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER | 1528d76a60baSAnirudh Venkataramanan NETIF_F_HW_VLAN_CTAG_TX | 1529d76a60baSAnirudh Venkataramanan NETIF_F_HW_VLAN_CTAG_RX; 1530d76a60baSAnirudh Venkataramanan 1531d76a60baSAnirudh Venkataramanan tso_features = NETIF_F_TSO; 1532d76a60baSAnirudh Venkataramanan 1533d76a60baSAnirudh Venkataramanan /* set features that user can change */ 1534d76a60baSAnirudh Venkataramanan netdev->hw_features = dflt_features | csumo_features | 1535d76a60baSAnirudh Venkataramanan vlano_features | tso_features; 1536d76a60baSAnirudh Venkataramanan 15373a858ba3SAnirudh Venkataramanan /* enable features */ 15383a858ba3SAnirudh Venkataramanan netdev->features |= netdev->hw_features; 1539d76a60baSAnirudh Venkataramanan /* encap and VLAN devices inherit default, csumo and tso features */ 1540d76a60baSAnirudh Venkataramanan netdev->hw_enc_features |= dflt_features | csumo_features | 1541d76a60baSAnirudh Venkataramanan tso_features; 1542d76a60baSAnirudh Venkataramanan netdev->vlan_features |= dflt_features | csumo_features | 1543d76a60baSAnirudh Venkataramanan tso_features; 15443a858ba3SAnirudh Venkataramanan 15453a858ba3SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 15463a858ba3SAnirudh Venkataramanan SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev); 15473a858ba3SAnirudh Venkataramanan ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr); 15483a858ba3SAnirudh Venkataramanan 15493a858ba3SAnirudh Venkataramanan ether_addr_copy(netdev->dev_addr, mac_addr); 15503a858ba3SAnirudh Venkataramanan ether_addr_copy(netdev->perm_addr, mac_addr); 15513a858ba3SAnirudh Venkataramanan } 15523a858ba3SAnirudh Venkataramanan 15533a858ba3SAnirudh Venkataramanan netdev->priv_flags |= IFF_UNICAST_FLT; 15543a858ba3SAnirudh Venkataramanan 1555cdedef59SAnirudh Venkataramanan /* assign netdev_ops */ 1556cdedef59SAnirudh Venkataramanan netdev->netdev_ops = &ice_netdev_ops; 1557cdedef59SAnirudh Venkataramanan 15583a858ba3SAnirudh Venkataramanan /* setup watchdog timeout value to be 5 second */ 15593a858ba3SAnirudh Venkataramanan netdev->watchdog_timeo = 5 * HZ; 15603a858ba3SAnirudh Venkataramanan 1561fcea6f3dSAnirudh Venkataramanan ice_set_ethtool_ops(netdev); 1562fcea6f3dSAnirudh Venkataramanan 15633a858ba3SAnirudh Venkataramanan netdev->min_mtu = ETH_MIN_MTU; 15643a858ba3SAnirudh Venkataramanan netdev->max_mtu = ICE_MAX_MTU; 15653a858ba3SAnirudh Venkataramanan 1566df0f8479SAnirudh Venkataramanan err = register_netdev(vsi->netdev); 15673a858ba3SAnirudh Venkataramanan if (err) 15683a858ba3SAnirudh Venkataramanan return err; 15693a858ba3SAnirudh Venkataramanan 1570df0f8479SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 15713a858ba3SAnirudh Venkataramanan 1572df0f8479SAnirudh Venkataramanan /* make sure transmit queues start off as stopped */ 1573df0f8479SAnirudh Venkataramanan netif_tx_stop_all_queues(vsi->netdev); 15743a858ba3SAnirudh Venkataramanan 15753a858ba3SAnirudh Venkataramanan return 0; 15763a858ba3SAnirudh Venkataramanan } 15773a858ba3SAnirudh Venkataramanan 15783a858ba3SAnirudh Venkataramanan /** 1579d76a60baSAnirudh Venkataramanan * ice_fill_rss_lut - Fill the RSS lookup table with default values 1580d76a60baSAnirudh Venkataramanan * @lut: Lookup table 1581d76a60baSAnirudh Venkataramanan * @rss_table_size: Lookup table size 1582d76a60baSAnirudh Venkataramanan * @rss_size: Range of queue number for hashing 1583d76a60baSAnirudh Venkataramanan */ 1584d76a60baSAnirudh Venkataramanan void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size) 1585d76a60baSAnirudh Venkataramanan { 1586d76a60baSAnirudh Venkataramanan u16 i; 1587d76a60baSAnirudh Venkataramanan 1588d76a60baSAnirudh Venkataramanan for (i = 0; i < rss_table_size; i++) 1589d76a60baSAnirudh Venkataramanan lut[i] = i % rss_size; 1590d76a60baSAnirudh Venkataramanan } 1591d76a60baSAnirudh Venkataramanan 1592d76a60baSAnirudh Venkataramanan /** 15930f9d5027SAnirudh Venkataramanan * ice_pf_vsi_setup - Set up a PF VSI 15940f9d5027SAnirudh Venkataramanan * @pf: board private structure 15950f9d5027SAnirudh Venkataramanan * @pi: pointer to the port_info instance 15960f9d5027SAnirudh Venkataramanan * 15970f9d5027SAnirudh Venkataramanan * Returns pointer to the successfully allocated VSI sw struct on success, 15980f9d5027SAnirudh Venkataramanan * otherwise returns NULL on failure. 15990f9d5027SAnirudh Venkataramanan */ 16000f9d5027SAnirudh Venkataramanan static struct ice_vsi * 16010f9d5027SAnirudh Venkataramanan ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi) 16020f9d5027SAnirudh Venkataramanan { 16030f9d5027SAnirudh Venkataramanan return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID); 16040f9d5027SAnirudh Venkataramanan } 16050f9d5027SAnirudh Venkataramanan 16060f9d5027SAnirudh Venkataramanan /** 1607d76a60baSAnirudh Venkataramanan * ice_vlan_rx_add_vid - Add a vlan id filter to HW offload 1608d76a60baSAnirudh Venkataramanan * @netdev: network interface to be adjusted 1609d76a60baSAnirudh Venkataramanan * @proto: unused protocol 1610d76a60baSAnirudh Venkataramanan * @vid: vlan id to be added 1611d76a60baSAnirudh Venkataramanan * 1612d76a60baSAnirudh Venkataramanan * net_device_ops implementation for adding vlan ids 1613d76a60baSAnirudh Venkataramanan */ 1614d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_add_vid(struct net_device *netdev, 1615d76a60baSAnirudh Venkataramanan __always_unused __be16 proto, u16 vid) 1616d76a60baSAnirudh Venkataramanan { 1617d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1618d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 16194f74dcc1SBrett Creeley int ret; 1620d76a60baSAnirudh Venkataramanan 1621d76a60baSAnirudh Venkataramanan if (vid >= VLAN_N_VID) { 1622d76a60baSAnirudh Venkataramanan netdev_err(netdev, "VLAN id requested %d is out of range %d\n", 1623d76a60baSAnirudh Venkataramanan vid, VLAN_N_VID); 1624d76a60baSAnirudh Venkataramanan return -EINVAL; 1625d76a60baSAnirudh Venkataramanan } 1626d76a60baSAnirudh Venkataramanan 1627d76a60baSAnirudh Venkataramanan if (vsi->info.pvid) 1628d76a60baSAnirudh Venkataramanan return -EINVAL; 1629d76a60baSAnirudh Venkataramanan 16304f74dcc1SBrett Creeley /* Enable VLAN pruning when VLAN 0 is added */ 16314f74dcc1SBrett Creeley if (unlikely(!vid)) { 16324f74dcc1SBrett Creeley ret = ice_cfg_vlan_pruning(vsi, true); 16334f74dcc1SBrett Creeley if (ret) 16344f74dcc1SBrett Creeley return ret; 16354f74dcc1SBrett Creeley } 16364f74dcc1SBrett Creeley 1637d76a60baSAnirudh Venkataramanan /* Add all VLAN ids including 0 to the switch filter. VLAN id 0 is 1638d76a60baSAnirudh Venkataramanan * needed to continue allowing all untagged packets since VLAN prune 1639d76a60baSAnirudh Venkataramanan * list is applied to all packets by the switch 1640d76a60baSAnirudh Venkataramanan */ 1641d76a60baSAnirudh Venkataramanan ret = ice_vsi_add_vlan(vsi, vid); 1642d76a60baSAnirudh Venkataramanan 1643d76a60baSAnirudh Venkataramanan if (!ret) 1644d76a60baSAnirudh Venkataramanan set_bit(vid, vsi->active_vlans); 1645d76a60baSAnirudh Venkataramanan 1646d76a60baSAnirudh Venkataramanan return ret; 1647d76a60baSAnirudh Venkataramanan } 1648d76a60baSAnirudh Venkataramanan 1649d76a60baSAnirudh Venkataramanan /** 1650d76a60baSAnirudh Venkataramanan * ice_vlan_rx_kill_vid - Remove a vlan id filter from HW offload 1651d76a60baSAnirudh Venkataramanan * @netdev: network interface to be adjusted 1652d76a60baSAnirudh Venkataramanan * @proto: unused protocol 1653d76a60baSAnirudh Venkataramanan * @vid: vlan id to be removed 1654d76a60baSAnirudh Venkataramanan * 1655d76a60baSAnirudh Venkataramanan * net_device_ops implementation for removing vlan ids 1656d76a60baSAnirudh Venkataramanan */ 1657d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_kill_vid(struct net_device *netdev, 1658d76a60baSAnirudh Venkataramanan __always_unused __be16 proto, u16 vid) 1659d76a60baSAnirudh Venkataramanan { 1660d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1661d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 16624f74dcc1SBrett Creeley int status; 1663d76a60baSAnirudh Venkataramanan 1664d76a60baSAnirudh Venkataramanan if (vsi->info.pvid) 1665d76a60baSAnirudh Venkataramanan return -EINVAL; 1666d76a60baSAnirudh Venkataramanan 16674f74dcc1SBrett Creeley /* Make sure ice_vsi_kill_vlan is successful before updating VLAN 16684f74dcc1SBrett Creeley * information 1669d76a60baSAnirudh Venkataramanan */ 16704f74dcc1SBrett Creeley status = ice_vsi_kill_vlan(vsi, vid); 16714f74dcc1SBrett Creeley if (status) 16724f74dcc1SBrett Creeley return status; 1673d76a60baSAnirudh Venkataramanan 1674d76a60baSAnirudh Venkataramanan clear_bit(vid, vsi->active_vlans); 1675d76a60baSAnirudh Venkataramanan 16764f74dcc1SBrett Creeley /* Disable VLAN pruning when VLAN 0 is removed */ 16774f74dcc1SBrett Creeley if (unlikely(!vid)) 16784f74dcc1SBrett Creeley status = ice_cfg_vlan_pruning(vsi, false); 16794f74dcc1SBrett Creeley 16804f74dcc1SBrett Creeley return status; 1681d76a60baSAnirudh Venkataramanan } 1682d76a60baSAnirudh Venkataramanan 1683d76a60baSAnirudh Venkataramanan /** 16843a858ba3SAnirudh Venkataramanan * ice_setup_pf_sw - Setup the HW switch on startup or after reset 16853a858ba3SAnirudh Venkataramanan * @pf: board private structure 16863a858ba3SAnirudh Venkataramanan * 16873a858ba3SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 16883a858ba3SAnirudh Venkataramanan */ 16893a858ba3SAnirudh Venkataramanan static int ice_setup_pf_sw(struct ice_pf *pf) 16903a858ba3SAnirudh Venkataramanan { 16919daf8208SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 16929daf8208SAnirudh Venkataramanan u8 broadcast[ETH_ALEN]; 16933a858ba3SAnirudh Venkataramanan struct ice_vsi *vsi; 16943a858ba3SAnirudh Venkataramanan int status = 0; 16953a858ba3SAnirudh Venkataramanan 16965df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) 16970f9d5027SAnirudh Venkataramanan return -EBUSY; 16980f9d5027SAnirudh Venkataramanan 16990f9d5027SAnirudh Venkataramanan vsi = ice_pf_vsi_setup(pf, pf->hw.port_info); 17003a858ba3SAnirudh Venkataramanan if (!vsi) { 17013a858ba3SAnirudh Venkataramanan status = -ENOMEM; 17020f9d5027SAnirudh Venkataramanan goto unroll_vsi_setup; 17030b28b702SAnirudh Venkataramanan } 17043a858ba3SAnirudh Venkataramanan 1705df0f8479SAnirudh Venkataramanan status = ice_cfg_netdev(vsi); 1706df0f8479SAnirudh Venkataramanan if (status) { 1707df0f8479SAnirudh Venkataramanan status = -ENODEV; 1708df0f8479SAnirudh Venkataramanan goto unroll_vsi_setup; 1709df0f8479SAnirudh Venkataramanan } 1710df0f8479SAnirudh Venkataramanan 1711df0f8479SAnirudh Venkataramanan /* registering the NAPI handler requires both the queues and 1712df0f8479SAnirudh Venkataramanan * netdev to be created, which are done in ice_pf_vsi_setup() 1713df0f8479SAnirudh Venkataramanan * and ice_cfg_netdev() respectively 1714df0f8479SAnirudh Venkataramanan */ 1715df0f8479SAnirudh Venkataramanan ice_napi_add(vsi); 1716df0f8479SAnirudh Venkataramanan 17170f9d5027SAnirudh Venkataramanan /* To add a MAC filter, first add the MAC to a list and then 17180f9d5027SAnirudh Venkataramanan * pass the list to ice_add_mac. 17199daf8208SAnirudh Venkataramanan */ 17200f9d5027SAnirudh Venkataramanan 17210f9d5027SAnirudh Venkataramanan /* Add a unicast MAC filter so the VSI can get its packets */ 17229daf8208SAnirudh Venkataramanan status = ice_add_mac_to_list(vsi, &tmp_add_list, 17239daf8208SAnirudh Venkataramanan vsi->port_info->mac.perm_addr); 17249daf8208SAnirudh Venkataramanan if (status) 1725df0f8479SAnirudh Venkataramanan goto unroll_napi_add; 17269daf8208SAnirudh Venkataramanan 17279daf8208SAnirudh Venkataramanan /* VSI needs to receive broadcast traffic, so add the broadcast 17280f9d5027SAnirudh Venkataramanan * MAC address to the list as well. 17299daf8208SAnirudh Venkataramanan */ 17309daf8208SAnirudh Venkataramanan eth_broadcast_addr(broadcast); 17319daf8208SAnirudh Venkataramanan status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast); 17329daf8208SAnirudh Venkataramanan if (status) 17330f9d5027SAnirudh Venkataramanan goto free_mac_list; 17349daf8208SAnirudh Venkataramanan 17359daf8208SAnirudh Venkataramanan /* program MAC filters for entries in tmp_add_list */ 17369daf8208SAnirudh Venkataramanan status = ice_add_mac(&pf->hw, &tmp_add_list); 17379daf8208SAnirudh Venkataramanan if (status) { 17389daf8208SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Could not add MAC filters\n"); 17399daf8208SAnirudh Venkataramanan status = -ENOMEM; 17400f9d5027SAnirudh Venkataramanan goto free_mac_list; 17419daf8208SAnirudh Venkataramanan } 17429daf8208SAnirudh Venkataramanan 17439daf8208SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 17449daf8208SAnirudh Venkataramanan return status; 17459daf8208SAnirudh Venkataramanan 17460f9d5027SAnirudh Venkataramanan free_mac_list: 17479daf8208SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 17489daf8208SAnirudh Venkataramanan 1749df0f8479SAnirudh Venkataramanan unroll_napi_add: 17503a858ba3SAnirudh Venkataramanan if (vsi) { 1751df0f8479SAnirudh Venkataramanan ice_napi_del(vsi); 17523a858ba3SAnirudh Venkataramanan if (vsi->netdev) { 1753df0f8479SAnirudh Venkataramanan if (vsi->netdev->reg_state == NETREG_REGISTERED) 1754df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 17553a858ba3SAnirudh Venkataramanan free_netdev(vsi->netdev); 17563a858ba3SAnirudh Venkataramanan vsi->netdev = NULL; 17573a858ba3SAnirudh Venkataramanan } 1758df0f8479SAnirudh Venkataramanan } 17599daf8208SAnirudh Venkataramanan 1760df0f8479SAnirudh Venkataramanan unroll_vsi_setup: 1761df0f8479SAnirudh Venkataramanan if (vsi) { 1762df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 17633a858ba3SAnirudh Venkataramanan ice_vsi_delete(vsi); 17643a858ba3SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 17653a858ba3SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 17663a858ba3SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 17673a858ba3SAnirudh Venkataramanan ice_vsi_clear(vsi); 17683a858ba3SAnirudh Venkataramanan } 17693a858ba3SAnirudh Venkataramanan return status; 17703a858ba3SAnirudh Venkataramanan } 17713a858ba3SAnirudh Venkataramanan 17723a858ba3SAnirudh Venkataramanan /** 1773940b61afSAnirudh Venkataramanan * ice_determine_q_usage - Calculate queue distribution 1774940b61afSAnirudh Venkataramanan * @pf: board private structure 1775940b61afSAnirudh Venkataramanan * 1776940b61afSAnirudh Venkataramanan * Return -ENOMEM if we don't get enough queues for all ports 1777940b61afSAnirudh Venkataramanan */ 1778940b61afSAnirudh Venkataramanan static void ice_determine_q_usage(struct ice_pf *pf) 1779940b61afSAnirudh Venkataramanan { 1780940b61afSAnirudh Venkataramanan u16 q_left_tx, q_left_rx; 1781940b61afSAnirudh Venkataramanan 1782940b61afSAnirudh Venkataramanan q_left_tx = pf->hw.func_caps.common_cap.num_txq; 1783940b61afSAnirudh Venkataramanan q_left_rx = pf->hw.func_caps.common_cap.num_rxq; 1784940b61afSAnirudh Venkataramanan 17855513b920SAnirudh Venkataramanan pf->num_lan_tx = min_t(int, q_left_tx, num_online_cpus()); 1786d76a60baSAnirudh Venkataramanan 1787d76a60baSAnirudh Venkataramanan /* only 1 rx queue unless RSS is enabled */ 1788d76a60baSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 1789940b61afSAnirudh Venkataramanan pf->num_lan_rx = 1; 1790d76a60baSAnirudh Venkataramanan else 1791d76a60baSAnirudh Venkataramanan pf->num_lan_rx = min_t(int, q_left_rx, num_online_cpus()); 1792940b61afSAnirudh Venkataramanan 1793940b61afSAnirudh Venkataramanan pf->q_left_tx = q_left_tx - pf->num_lan_tx; 1794940b61afSAnirudh Venkataramanan pf->q_left_rx = q_left_rx - pf->num_lan_rx; 1795940b61afSAnirudh Venkataramanan } 1796940b61afSAnirudh Venkataramanan 1797940b61afSAnirudh Venkataramanan /** 1798940b61afSAnirudh Venkataramanan * ice_deinit_pf - Unrolls initialziations done by ice_init_pf 1799940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 1800940b61afSAnirudh Venkataramanan */ 1801940b61afSAnirudh Venkataramanan static void ice_deinit_pf(struct ice_pf *pf) 1802940b61afSAnirudh Venkataramanan { 18038d81fa55SAkeem G Abodunrin ice_service_task_stop(pf); 1804940b61afSAnirudh Venkataramanan mutex_destroy(&pf->sw_mutex); 1805940b61afSAnirudh Venkataramanan mutex_destroy(&pf->avail_q_mutex); 1806940b61afSAnirudh Venkataramanan } 1807940b61afSAnirudh Venkataramanan 1808940b61afSAnirudh Venkataramanan /** 1809940b61afSAnirudh Venkataramanan * ice_init_pf - Initialize general software structures (struct ice_pf) 1810940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 1811940b61afSAnirudh Venkataramanan */ 1812940b61afSAnirudh Venkataramanan static void ice_init_pf(struct ice_pf *pf) 1813940b61afSAnirudh Venkataramanan { 1814940b61afSAnirudh Venkataramanan bitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS); 1815940b61afSAnirudh Venkataramanan set_bit(ICE_FLAG_MSIX_ENA, pf->flags); 181675d2b253SAnirudh Venkataramanan #ifdef CONFIG_PCI_IOV 181775d2b253SAnirudh Venkataramanan if (pf->hw.func_caps.common_cap.sr_iov_1_1) { 181875d2b253SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 181975d2b253SAnirudh Venkataramanan 182075d2b253SAnirudh Venkataramanan set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags); 182175d2b253SAnirudh Venkataramanan pf->num_vfs_supported = min_t(int, hw->func_caps.num_allocd_vfs, 182275d2b253SAnirudh Venkataramanan ICE_MAX_VF_COUNT); 182375d2b253SAnirudh Venkataramanan } 182475d2b253SAnirudh Venkataramanan #endif /* CONFIG_PCI_IOV */ 1825940b61afSAnirudh Venkataramanan 1826940b61afSAnirudh Venkataramanan mutex_init(&pf->sw_mutex); 1827940b61afSAnirudh Venkataramanan mutex_init(&pf->avail_q_mutex); 1828940b61afSAnirudh Venkataramanan 1829940b61afSAnirudh Venkataramanan /* Clear avail_[t|r]x_qs bitmaps (set all to avail) */ 1830940b61afSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 1831940b61afSAnirudh Venkataramanan bitmap_zero(pf->avail_txqs, ICE_MAX_TXQS); 1832940b61afSAnirudh Venkataramanan bitmap_zero(pf->avail_rxqs, ICE_MAX_RXQS); 1833940b61afSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 1834940b61afSAnirudh Venkataramanan 1835d76a60baSAnirudh Venkataramanan if (pf->hw.func_caps.common_cap.rss_table_size) 1836d76a60baSAnirudh Venkataramanan set_bit(ICE_FLAG_RSS_ENA, pf->flags); 1837d76a60baSAnirudh Venkataramanan 1838940b61afSAnirudh Venkataramanan /* setup service timer and periodic service task */ 1839940b61afSAnirudh Venkataramanan timer_setup(&pf->serv_tmr, ice_service_timer, 0); 1840940b61afSAnirudh Venkataramanan pf->serv_tmr_period = HZ; 1841940b61afSAnirudh Venkataramanan INIT_WORK(&pf->serv_task, ice_service_task); 1842940b61afSAnirudh Venkataramanan clear_bit(__ICE_SERVICE_SCHED, pf->state); 1843940b61afSAnirudh Venkataramanan } 1844940b61afSAnirudh Venkataramanan 1845940b61afSAnirudh Venkataramanan /** 1846940b61afSAnirudh Venkataramanan * ice_ena_msix_range - Request a range of MSIX vectors from the OS 1847940b61afSAnirudh Venkataramanan * @pf: board private structure 1848940b61afSAnirudh Venkataramanan * 1849940b61afSAnirudh Venkataramanan * compute the number of MSIX vectors required (v_budget) and request from 1850940b61afSAnirudh Venkataramanan * the OS. Return the number of vectors reserved or negative on failure 1851940b61afSAnirudh Venkataramanan */ 1852940b61afSAnirudh Venkataramanan static int ice_ena_msix_range(struct ice_pf *pf) 1853940b61afSAnirudh Venkataramanan { 1854940b61afSAnirudh Venkataramanan int v_left, v_actual, v_budget = 0; 1855940b61afSAnirudh Venkataramanan int needed, err, i; 1856940b61afSAnirudh Venkataramanan 1857940b61afSAnirudh Venkataramanan v_left = pf->hw.func_caps.common_cap.num_msix_vectors; 1858940b61afSAnirudh Venkataramanan 1859940b61afSAnirudh Venkataramanan /* reserve one vector for miscellaneous handler */ 1860940b61afSAnirudh Venkataramanan needed = 1; 1861940b61afSAnirudh Venkataramanan v_budget += needed; 1862940b61afSAnirudh Venkataramanan v_left -= needed; 1863940b61afSAnirudh Venkataramanan 1864940b61afSAnirudh Venkataramanan /* reserve vectors for LAN traffic */ 1865940b61afSAnirudh Venkataramanan pf->num_lan_msix = min_t(int, num_online_cpus(), v_left); 1866940b61afSAnirudh Venkataramanan v_budget += pf->num_lan_msix; 1867eb0208ecSPreethi Banala v_left -= pf->num_lan_msix; 1868940b61afSAnirudh Venkataramanan 1869940b61afSAnirudh Venkataramanan pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget, 1870940b61afSAnirudh Venkataramanan sizeof(struct msix_entry), GFP_KERNEL); 1871940b61afSAnirudh Venkataramanan 1872940b61afSAnirudh Venkataramanan if (!pf->msix_entries) { 1873940b61afSAnirudh Venkataramanan err = -ENOMEM; 1874940b61afSAnirudh Venkataramanan goto exit_err; 1875940b61afSAnirudh Venkataramanan } 1876940b61afSAnirudh Venkataramanan 1877940b61afSAnirudh Venkataramanan for (i = 0; i < v_budget; i++) 1878940b61afSAnirudh Venkataramanan pf->msix_entries[i].entry = i; 1879940b61afSAnirudh Venkataramanan 1880940b61afSAnirudh Venkataramanan /* actually reserve the vectors */ 1881940b61afSAnirudh Venkataramanan v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries, 1882940b61afSAnirudh Venkataramanan ICE_MIN_MSIX, v_budget); 1883940b61afSAnirudh Venkataramanan 1884940b61afSAnirudh Venkataramanan if (v_actual < 0) { 1885940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "unable to reserve MSI-X vectors\n"); 1886940b61afSAnirudh Venkataramanan err = v_actual; 1887940b61afSAnirudh Venkataramanan goto msix_err; 1888940b61afSAnirudh Venkataramanan } 1889940b61afSAnirudh Venkataramanan 1890940b61afSAnirudh Venkataramanan if (v_actual < v_budget) { 1891940b61afSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 1892940b61afSAnirudh Venkataramanan "not enough vectors. requested = %d, obtained = %d\n", 1893940b61afSAnirudh Venkataramanan v_budget, v_actual); 1894940b61afSAnirudh Venkataramanan if (v_actual >= (pf->num_lan_msix + 1)) { 1895eb0208ecSPreethi Banala pf->num_avail_sw_msix = v_actual - 1896eb0208ecSPreethi Banala (pf->num_lan_msix + 1); 1897940b61afSAnirudh Venkataramanan } else if (v_actual >= 2) { 1898940b61afSAnirudh Venkataramanan pf->num_lan_msix = 1; 1899eb0208ecSPreethi Banala pf->num_avail_sw_msix = v_actual - 2; 1900940b61afSAnirudh Venkataramanan } else { 1901940b61afSAnirudh Venkataramanan pci_disable_msix(pf->pdev); 1902940b61afSAnirudh Venkataramanan err = -ERANGE; 1903940b61afSAnirudh Venkataramanan goto msix_err; 1904940b61afSAnirudh Venkataramanan } 1905940b61afSAnirudh Venkataramanan } 1906940b61afSAnirudh Venkataramanan 1907940b61afSAnirudh Venkataramanan return v_actual; 1908940b61afSAnirudh Venkataramanan 1909940b61afSAnirudh Venkataramanan msix_err: 1910940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->msix_entries); 1911940b61afSAnirudh Venkataramanan goto exit_err; 1912940b61afSAnirudh Venkataramanan 1913940b61afSAnirudh Venkataramanan exit_err: 1914940b61afSAnirudh Venkataramanan pf->num_lan_msix = 0; 1915940b61afSAnirudh Venkataramanan clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); 1916940b61afSAnirudh Venkataramanan return err; 1917940b61afSAnirudh Venkataramanan } 1918940b61afSAnirudh Venkataramanan 1919940b61afSAnirudh Venkataramanan /** 1920940b61afSAnirudh Venkataramanan * ice_dis_msix - Disable MSI-X interrupt setup in OS 1921940b61afSAnirudh Venkataramanan * @pf: board private structure 1922940b61afSAnirudh Venkataramanan */ 1923940b61afSAnirudh Venkataramanan static void ice_dis_msix(struct ice_pf *pf) 1924940b61afSAnirudh Venkataramanan { 1925940b61afSAnirudh Venkataramanan pci_disable_msix(pf->pdev); 1926940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->msix_entries); 1927940b61afSAnirudh Venkataramanan pf->msix_entries = NULL; 1928940b61afSAnirudh Venkataramanan clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); 1929940b61afSAnirudh Venkataramanan } 1930940b61afSAnirudh Venkataramanan 1931940b61afSAnirudh Venkataramanan /** 1932eb0208ecSPreethi Banala * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme 1933eb0208ecSPreethi Banala * @pf: board private structure 1934eb0208ecSPreethi Banala */ 1935eb0208ecSPreethi Banala static void ice_clear_interrupt_scheme(struct ice_pf *pf) 1936eb0208ecSPreethi Banala { 1937eb0208ecSPreethi Banala if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 1938eb0208ecSPreethi Banala ice_dis_msix(pf); 1939eb0208ecSPreethi Banala 1940eb0208ecSPreethi Banala if (pf->sw_irq_tracker) { 1941eb0208ecSPreethi Banala devm_kfree(&pf->pdev->dev, pf->sw_irq_tracker); 1942eb0208ecSPreethi Banala pf->sw_irq_tracker = NULL; 1943eb0208ecSPreethi Banala } 1944eb0208ecSPreethi Banala 1945eb0208ecSPreethi Banala if (pf->hw_irq_tracker) { 1946eb0208ecSPreethi Banala devm_kfree(&pf->pdev->dev, pf->hw_irq_tracker); 1947eb0208ecSPreethi Banala pf->hw_irq_tracker = NULL; 1948eb0208ecSPreethi Banala } 1949eb0208ecSPreethi Banala } 1950eb0208ecSPreethi Banala 1951eb0208ecSPreethi Banala /** 1952940b61afSAnirudh Venkataramanan * ice_init_interrupt_scheme - Determine proper interrupt scheme 1953940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 1954940b61afSAnirudh Venkataramanan */ 1955940b61afSAnirudh Venkataramanan static int ice_init_interrupt_scheme(struct ice_pf *pf) 1956940b61afSAnirudh Venkataramanan { 1957eb0208ecSPreethi Banala int vectors = 0, hw_vectors = 0; 1958940b61afSAnirudh Venkataramanan ssize_t size; 1959940b61afSAnirudh Venkataramanan 1960940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 1961940b61afSAnirudh Venkataramanan vectors = ice_ena_msix_range(pf); 1962940b61afSAnirudh Venkataramanan else 1963940b61afSAnirudh Venkataramanan return -ENODEV; 1964940b61afSAnirudh Venkataramanan 1965940b61afSAnirudh Venkataramanan if (vectors < 0) 1966940b61afSAnirudh Venkataramanan return vectors; 1967940b61afSAnirudh Venkataramanan 1968940b61afSAnirudh Venkataramanan /* set up vector assignment tracking */ 1969940b61afSAnirudh Venkataramanan size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors); 1970940b61afSAnirudh Venkataramanan 1971eb0208ecSPreethi Banala pf->sw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); 1972eb0208ecSPreethi Banala if (!pf->sw_irq_tracker) { 1973940b61afSAnirudh Venkataramanan ice_dis_msix(pf); 1974940b61afSAnirudh Venkataramanan return -ENOMEM; 1975940b61afSAnirudh Venkataramanan } 1976940b61afSAnirudh Venkataramanan 1977eb0208ecSPreethi Banala /* populate SW interrupts pool with number of OS granted IRQs. */ 1978eb0208ecSPreethi Banala pf->num_avail_sw_msix = vectors; 1979eb0208ecSPreethi Banala pf->sw_irq_tracker->num_entries = vectors; 1980eb0208ecSPreethi Banala 1981eb0208ecSPreethi Banala /* set up HW vector assignment tracking */ 1982eb0208ecSPreethi Banala hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors; 1983eb0208ecSPreethi Banala size = sizeof(struct ice_res_tracker) + (sizeof(u16) * hw_vectors); 1984eb0208ecSPreethi Banala 1985eb0208ecSPreethi Banala pf->hw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); 1986eb0208ecSPreethi Banala if (!pf->hw_irq_tracker) { 1987eb0208ecSPreethi Banala ice_clear_interrupt_scheme(pf); 1988eb0208ecSPreethi Banala return -ENOMEM; 1989eb0208ecSPreethi Banala } 1990eb0208ecSPreethi Banala 1991eb0208ecSPreethi Banala /* populate HW interrupts pool with number of HW supported irqs. */ 1992eb0208ecSPreethi Banala pf->num_avail_hw_msix = hw_vectors; 1993eb0208ecSPreethi Banala pf->hw_irq_tracker->num_entries = hw_vectors; 1994940b61afSAnirudh Venkataramanan 1995940b61afSAnirudh Venkataramanan return 0; 1996940b61afSAnirudh Venkataramanan } 1997940b61afSAnirudh Venkataramanan 1998940b61afSAnirudh Venkataramanan /** 1999837f08fdSAnirudh Venkataramanan * ice_probe - Device initialization routine 2000837f08fdSAnirudh Venkataramanan * @pdev: PCI device information struct 2001837f08fdSAnirudh Venkataramanan * @ent: entry in ice_pci_tbl 2002837f08fdSAnirudh Venkataramanan * 2003837f08fdSAnirudh Venkataramanan * Returns 0 on success, negative on failure 2004837f08fdSAnirudh Venkataramanan */ 2005837f08fdSAnirudh Venkataramanan static int ice_probe(struct pci_dev *pdev, 2006837f08fdSAnirudh Venkataramanan const struct pci_device_id __always_unused *ent) 2007837f08fdSAnirudh Venkataramanan { 2008837f08fdSAnirudh Venkataramanan struct ice_pf *pf; 2009837f08fdSAnirudh Venkataramanan struct ice_hw *hw; 2010837f08fdSAnirudh Venkataramanan int err; 2011837f08fdSAnirudh Venkataramanan 2012837f08fdSAnirudh Venkataramanan /* this driver uses devres, see Documentation/driver-model/devres.txt */ 2013837f08fdSAnirudh Venkataramanan err = pcim_enable_device(pdev); 2014837f08fdSAnirudh Venkataramanan if (err) 2015837f08fdSAnirudh Venkataramanan return err; 2016837f08fdSAnirudh Venkataramanan 2017837f08fdSAnirudh Venkataramanan err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev)); 2018837f08fdSAnirudh Venkataramanan if (err) { 20193968540bSAnirudh Venkataramanan dev_err(&pdev->dev, "BAR0 I/O map error %d\n", err); 2020837f08fdSAnirudh Venkataramanan return err; 2021837f08fdSAnirudh Venkataramanan } 2022837f08fdSAnirudh Venkataramanan 2023837f08fdSAnirudh Venkataramanan pf = devm_kzalloc(&pdev->dev, sizeof(*pf), GFP_KERNEL); 2024837f08fdSAnirudh Venkataramanan if (!pf) 2025837f08fdSAnirudh Venkataramanan return -ENOMEM; 2026837f08fdSAnirudh Venkataramanan 2027837f08fdSAnirudh Venkataramanan /* set up for high or low dma */ 2028837f08fdSAnirudh Venkataramanan err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 2029837f08fdSAnirudh Venkataramanan if (err) 2030837f08fdSAnirudh Venkataramanan err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 2031837f08fdSAnirudh Venkataramanan if (err) { 2032837f08fdSAnirudh Venkataramanan dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err); 2033837f08fdSAnirudh Venkataramanan return err; 2034837f08fdSAnirudh Venkataramanan } 2035837f08fdSAnirudh Venkataramanan 2036837f08fdSAnirudh Venkataramanan pci_enable_pcie_error_reporting(pdev); 2037837f08fdSAnirudh Venkataramanan pci_set_master(pdev); 2038837f08fdSAnirudh Venkataramanan 2039837f08fdSAnirudh Venkataramanan pf->pdev = pdev; 2040837f08fdSAnirudh Venkataramanan pci_set_drvdata(pdev, pf); 2041837f08fdSAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 20428d81fa55SAkeem G Abodunrin /* Disable service task until DOWN bit is cleared */ 20438d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 2044837f08fdSAnirudh Venkataramanan 2045837f08fdSAnirudh Venkataramanan hw = &pf->hw; 2046837f08fdSAnirudh Venkataramanan hw->hw_addr = pcim_iomap_table(pdev)[ICE_BAR0]; 2047837f08fdSAnirudh Venkataramanan hw->back = pf; 2048837f08fdSAnirudh Venkataramanan hw->vendor_id = pdev->vendor; 2049837f08fdSAnirudh Venkataramanan hw->device_id = pdev->device; 2050837f08fdSAnirudh Venkataramanan pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); 2051837f08fdSAnirudh Venkataramanan hw->subsystem_vendor_id = pdev->subsystem_vendor; 2052837f08fdSAnirudh Venkataramanan hw->subsystem_device_id = pdev->subsystem_device; 2053837f08fdSAnirudh Venkataramanan hw->bus.device = PCI_SLOT(pdev->devfn); 2054837f08fdSAnirudh Venkataramanan hw->bus.func = PCI_FUNC(pdev->devfn); 2055f31e4b6fSAnirudh Venkataramanan ice_set_ctrlq_len(hw); 2056f31e4b6fSAnirudh Venkataramanan 2057837f08fdSAnirudh Venkataramanan pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M); 2058837f08fdSAnirudh Venkataramanan 20597ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 20607ec59eeaSAnirudh Venkataramanan if (debug < -1) 20617ec59eeaSAnirudh Venkataramanan hw->debug_mask = debug; 20627ec59eeaSAnirudh Venkataramanan #endif 20637ec59eeaSAnirudh Venkataramanan 2064f31e4b6fSAnirudh Venkataramanan err = ice_init_hw(hw); 2065f31e4b6fSAnirudh Venkataramanan if (err) { 2066f31e4b6fSAnirudh Venkataramanan dev_err(&pdev->dev, "ice_init_hw failed: %d\n", err); 2067f31e4b6fSAnirudh Venkataramanan err = -EIO; 2068f31e4b6fSAnirudh Venkataramanan goto err_exit_unroll; 2069f31e4b6fSAnirudh Venkataramanan } 2070f31e4b6fSAnirudh Venkataramanan 2071f31e4b6fSAnirudh Venkataramanan dev_info(&pdev->dev, "firmware %d.%d.%05d api %d.%d\n", 2072f31e4b6fSAnirudh Venkataramanan hw->fw_maj_ver, hw->fw_min_ver, hw->fw_build, 2073f31e4b6fSAnirudh Venkataramanan hw->api_maj_ver, hw->api_min_ver); 2074f31e4b6fSAnirudh Venkataramanan 2075940b61afSAnirudh Venkataramanan ice_init_pf(pf); 2076940b61afSAnirudh Venkataramanan 2077940b61afSAnirudh Venkataramanan ice_determine_q_usage(pf); 2078940b61afSAnirudh Venkataramanan 2079940b61afSAnirudh Venkataramanan pf->num_alloc_vsi = min_t(u16, ICE_MAX_VSI_ALLOC, 2080940b61afSAnirudh Venkataramanan hw->func_caps.guaranteed_num_vsi); 2081940b61afSAnirudh Venkataramanan if (!pf->num_alloc_vsi) { 2082940b61afSAnirudh Venkataramanan err = -EIO; 2083940b61afSAnirudh Venkataramanan goto err_init_pf_unroll; 2084940b61afSAnirudh Venkataramanan } 2085940b61afSAnirudh Venkataramanan 2086940b61afSAnirudh Venkataramanan pf->vsi = devm_kcalloc(&pdev->dev, pf->num_alloc_vsi, 2087940b61afSAnirudh Venkataramanan sizeof(struct ice_vsi *), GFP_KERNEL); 2088940b61afSAnirudh Venkataramanan if (!pf->vsi) { 2089940b61afSAnirudh Venkataramanan err = -ENOMEM; 2090940b61afSAnirudh Venkataramanan goto err_init_pf_unroll; 2091940b61afSAnirudh Venkataramanan } 2092940b61afSAnirudh Venkataramanan 2093940b61afSAnirudh Venkataramanan err = ice_init_interrupt_scheme(pf); 2094940b61afSAnirudh Venkataramanan if (err) { 2095940b61afSAnirudh Venkataramanan dev_err(&pdev->dev, 2096940b61afSAnirudh Venkataramanan "ice_init_interrupt_scheme failed: %d\n", err); 2097940b61afSAnirudh Venkataramanan err = -EIO; 2098940b61afSAnirudh Venkataramanan goto err_init_interrupt_unroll; 2099940b61afSAnirudh Venkataramanan } 2100940b61afSAnirudh Venkataramanan 21018d81fa55SAkeem G Abodunrin /* Driver is mostly up */ 21028d81fa55SAkeem G Abodunrin clear_bit(__ICE_DOWN, pf->state); 21038d81fa55SAkeem G Abodunrin 2104940b61afSAnirudh Venkataramanan /* In case of MSIX we are going to setup the misc vector right here 2105940b61afSAnirudh Venkataramanan * to handle admin queue events etc. In case of legacy and MSI 2106940b61afSAnirudh Venkataramanan * the misc functionality and queue processing is combined in 2107940b61afSAnirudh Venkataramanan * the same vector and that gets setup at open. 2108940b61afSAnirudh Venkataramanan */ 2109940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 2110940b61afSAnirudh Venkataramanan err = ice_req_irq_msix_misc(pf); 2111940b61afSAnirudh Venkataramanan if (err) { 2112940b61afSAnirudh Venkataramanan dev_err(&pdev->dev, 2113940b61afSAnirudh Venkataramanan "setup of misc vector failed: %d\n", err); 2114940b61afSAnirudh Venkataramanan goto err_init_interrupt_unroll; 2115940b61afSAnirudh Venkataramanan } 2116940b61afSAnirudh Venkataramanan } 2117940b61afSAnirudh Venkataramanan 2118940b61afSAnirudh Venkataramanan /* create switch struct for the switch element created by FW on boot */ 2119940b61afSAnirudh Venkataramanan pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(struct ice_sw), 2120940b61afSAnirudh Venkataramanan GFP_KERNEL); 2121940b61afSAnirudh Venkataramanan if (!pf->first_sw) { 2122940b61afSAnirudh Venkataramanan err = -ENOMEM; 2123940b61afSAnirudh Venkataramanan goto err_msix_misc_unroll; 2124940b61afSAnirudh Venkataramanan } 2125940b61afSAnirudh Venkataramanan 2126b1edc14aSMd Fahad Iqbal Polash if (hw->evb_veb) 2127940b61afSAnirudh Venkataramanan pf->first_sw->bridge_mode = BRIDGE_MODE_VEB; 2128b1edc14aSMd Fahad Iqbal Polash else 2129b1edc14aSMd Fahad Iqbal Polash pf->first_sw->bridge_mode = BRIDGE_MODE_VEPA; 2130b1edc14aSMd Fahad Iqbal Polash 2131940b61afSAnirudh Venkataramanan pf->first_sw->pf = pf; 2132940b61afSAnirudh Venkataramanan 2133940b61afSAnirudh Venkataramanan /* record the sw_id available for later use */ 2134940b61afSAnirudh Venkataramanan pf->first_sw->sw_id = hw->port_info->sw_id; 2135940b61afSAnirudh Venkataramanan 21363a858ba3SAnirudh Venkataramanan err = ice_setup_pf_sw(pf); 21373a858ba3SAnirudh Venkataramanan if (err) { 21383a858ba3SAnirudh Venkataramanan dev_err(&pdev->dev, 21393a858ba3SAnirudh Venkataramanan "probe failed due to setup pf switch:%d\n", err); 21403a858ba3SAnirudh Venkataramanan goto err_alloc_sw_unroll; 21413a858ba3SAnirudh Venkataramanan } 21429daf8208SAnirudh Venkataramanan 21438d81fa55SAkeem G Abodunrin clear_bit(__ICE_SERVICE_DIS, pf->state); 21449daf8208SAnirudh Venkataramanan 21459daf8208SAnirudh Venkataramanan /* since everything is good, start the service timer */ 21469daf8208SAnirudh Venkataramanan mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); 21479daf8208SAnirudh Venkataramanan 21480b28b702SAnirudh Venkataramanan err = ice_init_link_events(pf->hw.port_info); 21490b28b702SAnirudh Venkataramanan if (err) { 21500b28b702SAnirudh Venkataramanan dev_err(&pdev->dev, "ice_init_link_events failed: %d\n", err); 21510b28b702SAnirudh Venkataramanan goto err_alloc_sw_unroll; 21520b28b702SAnirudh Venkataramanan } 21530b28b702SAnirudh Venkataramanan 2154837f08fdSAnirudh Venkataramanan return 0; 2155f31e4b6fSAnirudh Venkataramanan 21563a858ba3SAnirudh Venkataramanan err_alloc_sw_unroll: 21578d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 21583a858ba3SAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 21593a858ba3SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->first_sw); 2160940b61afSAnirudh Venkataramanan err_msix_misc_unroll: 2161940b61afSAnirudh Venkataramanan ice_free_irq_msix_misc(pf); 2162940b61afSAnirudh Venkataramanan err_init_interrupt_unroll: 2163940b61afSAnirudh Venkataramanan ice_clear_interrupt_scheme(pf); 2164940b61afSAnirudh Venkataramanan devm_kfree(&pdev->dev, pf->vsi); 2165940b61afSAnirudh Venkataramanan err_init_pf_unroll: 2166940b61afSAnirudh Venkataramanan ice_deinit_pf(pf); 2167940b61afSAnirudh Venkataramanan ice_deinit_hw(hw); 2168f31e4b6fSAnirudh Venkataramanan err_exit_unroll: 2169f31e4b6fSAnirudh Venkataramanan pci_disable_pcie_error_reporting(pdev); 2170f31e4b6fSAnirudh Venkataramanan return err; 2171837f08fdSAnirudh Venkataramanan } 2172837f08fdSAnirudh Venkataramanan 2173837f08fdSAnirudh Venkataramanan /** 2174837f08fdSAnirudh Venkataramanan * ice_remove - Device removal routine 2175837f08fdSAnirudh Venkataramanan * @pdev: PCI device information struct 2176837f08fdSAnirudh Venkataramanan */ 2177837f08fdSAnirudh Venkataramanan static void ice_remove(struct pci_dev *pdev) 2178837f08fdSAnirudh Venkataramanan { 2179837f08fdSAnirudh Venkataramanan struct ice_pf *pf = pci_get_drvdata(pdev); 218081b23589SDave Ertman int i; 2181837f08fdSAnirudh Venkataramanan 2182837f08fdSAnirudh Venkataramanan if (!pf) 2183837f08fdSAnirudh Venkataramanan return; 2184837f08fdSAnirudh Venkataramanan 2185837f08fdSAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 21868d81fa55SAkeem G Abodunrin ice_service_task_stop(pf); 2187f31e4b6fSAnirudh Venkataramanan 21880f9d5027SAnirudh Venkataramanan ice_vsi_release_all(pf); 2189940b61afSAnirudh Venkataramanan ice_free_irq_msix_misc(pf); 219081b23589SDave Ertman ice_for_each_vsi(pf, i) { 219181b23589SDave Ertman if (!pf->vsi[i]) 219281b23589SDave Ertman continue; 219381b23589SDave Ertman ice_vsi_free_q_vectors(pf->vsi[i]); 219481b23589SDave Ertman } 2195940b61afSAnirudh Venkataramanan ice_clear_interrupt_scheme(pf); 2196940b61afSAnirudh Venkataramanan ice_deinit_pf(pf); 2197f31e4b6fSAnirudh Venkataramanan ice_deinit_hw(&pf->hw); 2198837f08fdSAnirudh Venkataramanan pci_disable_pcie_error_reporting(pdev); 2199837f08fdSAnirudh Venkataramanan } 2200837f08fdSAnirudh Venkataramanan 2201837f08fdSAnirudh Venkataramanan /* ice_pci_tbl - PCI Device ID Table 2202837f08fdSAnirudh Venkataramanan * 2203837f08fdSAnirudh Venkataramanan * Wildcard entries (PCI_ANY_ID) should come last 2204837f08fdSAnirudh Venkataramanan * Last entry must be all 0s 2205837f08fdSAnirudh Venkataramanan * 2206837f08fdSAnirudh Venkataramanan * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, 2207837f08fdSAnirudh Venkataramanan * Class, Class Mask, private data (not used) } 2208837f08fdSAnirudh Venkataramanan */ 2209837f08fdSAnirudh Venkataramanan static const struct pci_device_id ice_pci_tbl[] = { 2210837f08fdSAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_BACKPLANE), 0 }, 2211837f08fdSAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_QSFP), 0 }, 2212837f08fdSAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_SFP), 0 }, 2213837f08fdSAnirudh Venkataramanan /* required last entry */ 2214837f08fdSAnirudh Venkataramanan { 0, } 2215837f08fdSAnirudh Venkataramanan }; 2216837f08fdSAnirudh Venkataramanan MODULE_DEVICE_TABLE(pci, ice_pci_tbl); 2217837f08fdSAnirudh Venkataramanan 2218837f08fdSAnirudh Venkataramanan static struct pci_driver ice_driver = { 2219837f08fdSAnirudh Venkataramanan .name = KBUILD_MODNAME, 2220837f08fdSAnirudh Venkataramanan .id_table = ice_pci_tbl, 2221837f08fdSAnirudh Venkataramanan .probe = ice_probe, 2222837f08fdSAnirudh Venkataramanan .remove = ice_remove, 2223837f08fdSAnirudh Venkataramanan }; 2224837f08fdSAnirudh Venkataramanan 2225837f08fdSAnirudh Venkataramanan /** 2226837f08fdSAnirudh Venkataramanan * ice_module_init - Driver registration routine 2227837f08fdSAnirudh Venkataramanan * 2228837f08fdSAnirudh Venkataramanan * ice_module_init is the first routine called when the driver is 2229837f08fdSAnirudh Venkataramanan * loaded. All it does is register with the PCI subsystem. 2230837f08fdSAnirudh Venkataramanan */ 2231837f08fdSAnirudh Venkataramanan static int __init ice_module_init(void) 2232837f08fdSAnirudh Venkataramanan { 2233837f08fdSAnirudh Venkataramanan int status; 2234837f08fdSAnirudh Venkataramanan 2235837f08fdSAnirudh Venkataramanan pr_info("%s - version %s\n", ice_driver_string, ice_drv_ver); 2236837f08fdSAnirudh Venkataramanan pr_info("%s\n", ice_copyright); 2237837f08fdSAnirudh Venkataramanan 22380f9d5027SAnirudh Venkataramanan ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME); 2239940b61afSAnirudh Venkataramanan if (!ice_wq) { 2240940b61afSAnirudh Venkataramanan pr_err("Failed to create workqueue\n"); 2241940b61afSAnirudh Venkataramanan return -ENOMEM; 2242940b61afSAnirudh Venkataramanan } 2243940b61afSAnirudh Venkataramanan 2244837f08fdSAnirudh Venkataramanan status = pci_register_driver(&ice_driver); 2245940b61afSAnirudh Venkataramanan if (status) { 2246837f08fdSAnirudh Venkataramanan pr_err("failed to register pci driver, err %d\n", status); 2247940b61afSAnirudh Venkataramanan destroy_workqueue(ice_wq); 2248940b61afSAnirudh Venkataramanan } 2249837f08fdSAnirudh Venkataramanan 2250837f08fdSAnirudh Venkataramanan return status; 2251837f08fdSAnirudh Venkataramanan } 2252837f08fdSAnirudh Venkataramanan module_init(ice_module_init); 2253837f08fdSAnirudh Venkataramanan 2254837f08fdSAnirudh Venkataramanan /** 2255837f08fdSAnirudh Venkataramanan * ice_module_exit - Driver exit cleanup routine 2256837f08fdSAnirudh Venkataramanan * 2257837f08fdSAnirudh Venkataramanan * ice_module_exit is called just before the driver is removed 2258837f08fdSAnirudh Venkataramanan * from memory. 2259837f08fdSAnirudh Venkataramanan */ 2260837f08fdSAnirudh Venkataramanan static void __exit ice_module_exit(void) 2261837f08fdSAnirudh Venkataramanan { 2262837f08fdSAnirudh Venkataramanan pci_unregister_driver(&ice_driver); 2263940b61afSAnirudh Venkataramanan destroy_workqueue(ice_wq); 2264837f08fdSAnirudh Venkataramanan pr_info("module unloaded\n"); 2265837f08fdSAnirudh Venkataramanan } 2266837f08fdSAnirudh Venkataramanan module_exit(ice_module_exit); 22673a858ba3SAnirudh Venkataramanan 22683a858ba3SAnirudh Venkataramanan /** 2269e94d4478SAnirudh Venkataramanan * ice_set_mac_address - NDO callback to set mac address 2270e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 2271e94d4478SAnirudh Venkataramanan * @pi: pointer to an address structure 2272e94d4478SAnirudh Venkataramanan * 2273e94d4478SAnirudh Venkataramanan * Returns 0 on success, negative on failure 2274e94d4478SAnirudh Venkataramanan */ 2275e94d4478SAnirudh Venkataramanan static int ice_set_mac_address(struct net_device *netdev, void *pi) 2276e94d4478SAnirudh Venkataramanan { 2277e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2278e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2279e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2280e94d4478SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2281e94d4478SAnirudh Venkataramanan struct sockaddr *addr = pi; 2282e94d4478SAnirudh Venkataramanan enum ice_status status; 2283e94d4478SAnirudh Venkataramanan LIST_HEAD(a_mac_list); 2284e94d4478SAnirudh Venkataramanan LIST_HEAD(r_mac_list); 2285e94d4478SAnirudh Venkataramanan u8 flags = 0; 2286e94d4478SAnirudh Venkataramanan int err; 2287e94d4478SAnirudh Venkataramanan u8 *mac; 2288e94d4478SAnirudh Venkataramanan 2289e94d4478SAnirudh Venkataramanan mac = (u8 *)addr->sa_data; 2290e94d4478SAnirudh Venkataramanan 2291e94d4478SAnirudh Venkataramanan if (!is_valid_ether_addr(mac)) 2292e94d4478SAnirudh Venkataramanan return -EADDRNOTAVAIL; 2293e94d4478SAnirudh Venkataramanan 2294e94d4478SAnirudh Venkataramanan if (ether_addr_equal(netdev->dev_addr, mac)) { 2295e94d4478SAnirudh Venkataramanan netdev_warn(netdev, "already using mac %pM\n", mac); 2296e94d4478SAnirudh Venkataramanan return 0; 2297e94d4478SAnirudh Venkataramanan } 2298e94d4478SAnirudh Venkataramanan 2299e94d4478SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state) || 23005df7e45dSDave Ertman ice_is_reset_in_progress(pf->state)) { 2301e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. device not ready\n", 2302e94d4478SAnirudh Venkataramanan mac); 2303e94d4478SAnirudh Venkataramanan return -EBUSY; 2304e94d4478SAnirudh Venkataramanan } 2305e94d4478SAnirudh Venkataramanan 2306e94d4478SAnirudh Venkataramanan /* When we change the mac address we also have to change the mac address 2307e94d4478SAnirudh Venkataramanan * based filter rules that were created previously for the old mac 2308e94d4478SAnirudh Venkataramanan * address. So first, we remove the old filter rule using ice_remove_mac 2309e94d4478SAnirudh Venkataramanan * and then create a new filter rule using ice_add_mac. Note that for 2310e94d4478SAnirudh Venkataramanan * both these operations, we first need to form a "list" of mac 2311e94d4478SAnirudh Venkataramanan * addresses (even though in this case, we have only 1 mac address to be 2312e94d4478SAnirudh Venkataramanan * added/removed) and this done using ice_add_mac_to_list. Depending on 2313e94d4478SAnirudh Venkataramanan * the ensuing operation this "list" of mac addresses is either to be 2314e94d4478SAnirudh Venkataramanan * added or removed from the filter. 2315e94d4478SAnirudh Venkataramanan */ 2316e94d4478SAnirudh Venkataramanan err = ice_add_mac_to_list(vsi, &r_mac_list, netdev->dev_addr); 2317e94d4478SAnirudh Venkataramanan if (err) { 2318e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2319e94d4478SAnirudh Venkataramanan goto free_lists; 2320e94d4478SAnirudh Venkataramanan } 2321e94d4478SAnirudh Venkataramanan 2322e94d4478SAnirudh Venkataramanan status = ice_remove_mac(hw, &r_mac_list); 2323e94d4478SAnirudh Venkataramanan if (status) { 2324e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2325e94d4478SAnirudh Venkataramanan goto free_lists; 2326e94d4478SAnirudh Venkataramanan } 2327e94d4478SAnirudh Venkataramanan 2328e94d4478SAnirudh Venkataramanan err = ice_add_mac_to_list(vsi, &a_mac_list, mac); 2329e94d4478SAnirudh Venkataramanan if (err) { 2330e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2331e94d4478SAnirudh Venkataramanan goto free_lists; 2332e94d4478SAnirudh Venkataramanan } 2333e94d4478SAnirudh Venkataramanan 2334e94d4478SAnirudh Venkataramanan status = ice_add_mac(hw, &a_mac_list); 2335e94d4478SAnirudh Venkataramanan if (status) { 2336e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2337e94d4478SAnirudh Venkataramanan goto free_lists; 2338e94d4478SAnirudh Venkataramanan } 2339e94d4478SAnirudh Venkataramanan 2340e94d4478SAnirudh Venkataramanan free_lists: 2341e94d4478SAnirudh Venkataramanan /* free list entries */ 2342e94d4478SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &r_mac_list); 2343e94d4478SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &a_mac_list); 2344e94d4478SAnirudh Venkataramanan 2345e94d4478SAnirudh Venkataramanan if (err) { 2346e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. filter update failed\n", 2347e94d4478SAnirudh Venkataramanan mac); 2348e94d4478SAnirudh Venkataramanan return err; 2349e94d4478SAnirudh Venkataramanan } 2350e94d4478SAnirudh Venkataramanan 2351e94d4478SAnirudh Venkataramanan /* change the netdev's mac address */ 2352e94d4478SAnirudh Venkataramanan memcpy(netdev->dev_addr, mac, netdev->addr_len); 2353e94d4478SAnirudh Venkataramanan netdev_dbg(vsi->netdev, "updated mac address to %pM\n", 2354e94d4478SAnirudh Venkataramanan netdev->dev_addr); 2355e94d4478SAnirudh Venkataramanan 2356e94d4478SAnirudh Venkataramanan /* write new mac address to the firmware */ 2357e94d4478SAnirudh Venkataramanan flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL; 2358e94d4478SAnirudh Venkataramanan status = ice_aq_manage_mac_write(hw, mac, flags, NULL); 2359e94d4478SAnirudh Venkataramanan if (status) { 2360e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. write to firmware failed.\n", 2361e94d4478SAnirudh Venkataramanan mac); 2362e94d4478SAnirudh Venkataramanan } 2363e94d4478SAnirudh Venkataramanan return 0; 2364e94d4478SAnirudh Venkataramanan } 2365e94d4478SAnirudh Venkataramanan 2366e94d4478SAnirudh Venkataramanan /** 2367e94d4478SAnirudh Venkataramanan * ice_set_rx_mode - NDO callback to set the netdev filters 2368e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 2369e94d4478SAnirudh Venkataramanan */ 2370e94d4478SAnirudh Venkataramanan static void ice_set_rx_mode(struct net_device *netdev) 2371e94d4478SAnirudh Venkataramanan { 2372e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2373e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2374e94d4478SAnirudh Venkataramanan 2375e94d4478SAnirudh Venkataramanan if (!vsi) 2376e94d4478SAnirudh Venkataramanan return; 2377e94d4478SAnirudh Venkataramanan 2378e94d4478SAnirudh Venkataramanan /* Set the flags to synchronize filters 2379e94d4478SAnirudh Venkataramanan * ndo_set_rx_mode may be triggered even without a change in netdev 2380e94d4478SAnirudh Venkataramanan * flags 2381e94d4478SAnirudh Venkataramanan */ 2382e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 2383e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 2384e94d4478SAnirudh Venkataramanan set_bit(ICE_FLAG_FLTR_SYNC, vsi->back->flags); 2385e94d4478SAnirudh Venkataramanan 2386e94d4478SAnirudh Venkataramanan /* schedule our worker thread which will take care of 2387e94d4478SAnirudh Venkataramanan * applying the new filter changes 2388e94d4478SAnirudh Venkataramanan */ 2389e94d4478SAnirudh Venkataramanan ice_service_task_schedule(vsi->back); 2390e94d4478SAnirudh Venkataramanan } 2391e94d4478SAnirudh Venkataramanan 2392e94d4478SAnirudh Venkataramanan /** 2393e94d4478SAnirudh Venkataramanan * ice_fdb_add - add an entry to the hardware database 2394e94d4478SAnirudh Venkataramanan * @ndm: the input from the stack 2395e94d4478SAnirudh Venkataramanan * @tb: pointer to array of nladdr (unused) 2396e94d4478SAnirudh Venkataramanan * @dev: the net device pointer 2397e94d4478SAnirudh Venkataramanan * @addr: the MAC address entry being added 2398e94d4478SAnirudh Venkataramanan * @vid: VLAN id 2399e94d4478SAnirudh Venkataramanan * @flags: instructions from stack about fdb operation 2400e94d4478SAnirudh Venkataramanan */ 2401e94d4478SAnirudh Venkataramanan static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[], 2402e94d4478SAnirudh Venkataramanan struct net_device *dev, const unsigned char *addr, 2403e94d4478SAnirudh Venkataramanan u16 vid, u16 flags) 2404e94d4478SAnirudh Venkataramanan { 2405e94d4478SAnirudh Venkataramanan int err; 2406e94d4478SAnirudh Venkataramanan 2407e94d4478SAnirudh Venkataramanan if (vid) { 2408e94d4478SAnirudh Venkataramanan netdev_err(dev, "VLANs aren't supported yet for dev_uc|mc_add()\n"); 2409e94d4478SAnirudh Venkataramanan return -EINVAL; 2410e94d4478SAnirudh Venkataramanan } 2411e94d4478SAnirudh Venkataramanan if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { 2412e94d4478SAnirudh Venkataramanan netdev_err(dev, "FDB only supports static addresses\n"); 2413e94d4478SAnirudh Venkataramanan return -EINVAL; 2414e94d4478SAnirudh Venkataramanan } 2415e94d4478SAnirudh Venkataramanan 2416e94d4478SAnirudh Venkataramanan if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) 2417e94d4478SAnirudh Venkataramanan err = dev_uc_add_excl(dev, addr); 2418e94d4478SAnirudh Venkataramanan else if (is_multicast_ether_addr(addr)) 2419e94d4478SAnirudh Venkataramanan err = dev_mc_add_excl(dev, addr); 2420e94d4478SAnirudh Venkataramanan else 2421e94d4478SAnirudh Venkataramanan err = -EINVAL; 2422e94d4478SAnirudh Venkataramanan 2423e94d4478SAnirudh Venkataramanan /* Only return duplicate errors if NLM_F_EXCL is set */ 2424e94d4478SAnirudh Venkataramanan if (err == -EEXIST && !(flags & NLM_F_EXCL)) 2425e94d4478SAnirudh Venkataramanan err = 0; 2426e94d4478SAnirudh Venkataramanan 2427e94d4478SAnirudh Venkataramanan return err; 2428e94d4478SAnirudh Venkataramanan } 2429e94d4478SAnirudh Venkataramanan 2430e94d4478SAnirudh Venkataramanan /** 2431e94d4478SAnirudh Venkataramanan * ice_fdb_del - delete an entry from the hardware database 2432e94d4478SAnirudh Venkataramanan * @ndm: the input from the stack 2433e94d4478SAnirudh Venkataramanan * @tb: pointer to array of nladdr (unused) 2434e94d4478SAnirudh Venkataramanan * @dev: the net device pointer 2435e94d4478SAnirudh Venkataramanan * @addr: the MAC address entry being added 2436e94d4478SAnirudh Venkataramanan * @vid: VLAN id 2437e94d4478SAnirudh Venkataramanan */ 2438e94d4478SAnirudh Venkataramanan static int ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[], 2439e94d4478SAnirudh Venkataramanan struct net_device *dev, const unsigned char *addr, 2440e94d4478SAnirudh Venkataramanan __always_unused u16 vid) 2441e94d4478SAnirudh Venkataramanan { 2442e94d4478SAnirudh Venkataramanan int err; 2443e94d4478SAnirudh Venkataramanan 2444e94d4478SAnirudh Venkataramanan if (ndm->ndm_state & NUD_PERMANENT) { 2445e94d4478SAnirudh Venkataramanan netdev_err(dev, "FDB only supports static addresses\n"); 2446e94d4478SAnirudh Venkataramanan return -EINVAL; 2447e94d4478SAnirudh Venkataramanan } 2448e94d4478SAnirudh Venkataramanan 2449e94d4478SAnirudh Venkataramanan if (is_unicast_ether_addr(addr)) 2450e94d4478SAnirudh Venkataramanan err = dev_uc_del(dev, addr); 2451e94d4478SAnirudh Venkataramanan else if (is_multicast_ether_addr(addr)) 2452e94d4478SAnirudh Venkataramanan err = dev_mc_del(dev, addr); 2453e94d4478SAnirudh Venkataramanan else 2454e94d4478SAnirudh Venkataramanan err = -EINVAL; 2455e94d4478SAnirudh Venkataramanan 2456e94d4478SAnirudh Venkataramanan return err; 2457e94d4478SAnirudh Venkataramanan } 2458e94d4478SAnirudh Venkataramanan 2459e94d4478SAnirudh Venkataramanan /** 2460d76a60baSAnirudh Venkataramanan * ice_set_features - set the netdev feature flags 2461d76a60baSAnirudh Venkataramanan * @netdev: ptr to the netdev being adjusted 2462d76a60baSAnirudh Venkataramanan * @features: the feature set that the stack is suggesting 2463d76a60baSAnirudh Venkataramanan */ 2464d76a60baSAnirudh Venkataramanan static int ice_set_features(struct net_device *netdev, 2465d76a60baSAnirudh Venkataramanan netdev_features_t features) 2466d76a60baSAnirudh Venkataramanan { 2467d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2468d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2469d76a60baSAnirudh Venkataramanan int ret = 0; 2470d76a60baSAnirudh Venkataramanan 2471492af0abSMd Fahad Iqbal Polash if (features & NETIF_F_RXHASH && !(netdev->features & NETIF_F_RXHASH)) 2472492af0abSMd Fahad Iqbal Polash ret = ice_vsi_manage_rss_lut(vsi, true); 2473492af0abSMd Fahad Iqbal Polash else if (!(features & NETIF_F_RXHASH) && 2474492af0abSMd Fahad Iqbal Polash netdev->features & NETIF_F_RXHASH) 2475492af0abSMd Fahad Iqbal Polash ret = ice_vsi_manage_rss_lut(vsi, false); 2476492af0abSMd Fahad Iqbal Polash 2477d76a60baSAnirudh Venkataramanan if ((features & NETIF_F_HW_VLAN_CTAG_RX) && 2478d76a60baSAnirudh Venkataramanan !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) 2479d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, true); 2480d76a60baSAnirudh Venkataramanan else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && 2481d76a60baSAnirudh Venkataramanan (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) 2482d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, false); 2483d76a60baSAnirudh Venkataramanan else if ((features & NETIF_F_HW_VLAN_CTAG_TX) && 2484d76a60baSAnirudh Venkataramanan !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) 2485d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2486d76a60baSAnirudh Venkataramanan else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) && 2487d76a60baSAnirudh Venkataramanan (netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) 2488d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2489d76a60baSAnirudh Venkataramanan 2490d76a60baSAnirudh Venkataramanan return ret; 2491d76a60baSAnirudh Venkataramanan } 2492d76a60baSAnirudh Venkataramanan 2493d76a60baSAnirudh Venkataramanan /** 2494d76a60baSAnirudh Venkataramanan * ice_vsi_vlan_setup - Setup vlan offload properties on a VSI 2495d76a60baSAnirudh Venkataramanan * @vsi: VSI to setup vlan properties for 2496d76a60baSAnirudh Venkataramanan */ 2497d76a60baSAnirudh Venkataramanan static int ice_vsi_vlan_setup(struct ice_vsi *vsi) 2498d76a60baSAnirudh Venkataramanan { 2499d76a60baSAnirudh Venkataramanan int ret = 0; 2500d76a60baSAnirudh Venkataramanan 2501d76a60baSAnirudh Venkataramanan if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) 2502d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, true); 2503d76a60baSAnirudh Venkataramanan if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX) 2504d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2505d76a60baSAnirudh Venkataramanan 2506d76a60baSAnirudh Venkataramanan return ret; 2507d76a60baSAnirudh Venkataramanan } 2508d76a60baSAnirudh Venkataramanan 2509d76a60baSAnirudh Venkataramanan /** 2510d76a60baSAnirudh Venkataramanan * ice_restore_vlan - Reinstate VLANs when vsi/netdev comes back up 2511d76a60baSAnirudh Venkataramanan * @vsi: the VSI being brought back up 2512d76a60baSAnirudh Venkataramanan */ 2513d76a60baSAnirudh Venkataramanan static int ice_restore_vlan(struct ice_vsi *vsi) 2514d76a60baSAnirudh Venkataramanan { 2515d76a60baSAnirudh Venkataramanan int err; 2516d76a60baSAnirudh Venkataramanan u16 vid; 2517d76a60baSAnirudh Venkataramanan 2518d76a60baSAnirudh Venkataramanan if (!vsi->netdev) 2519d76a60baSAnirudh Venkataramanan return -EINVAL; 2520d76a60baSAnirudh Venkataramanan 2521d76a60baSAnirudh Venkataramanan err = ice_vsi_vlan_setup(vsi); 2522d76a60baSAnirudh Venkataramanan if (err) 2523d76a60baSAnirudh Venkataramanan return err; 2524d76a60baSAnirudh Venkataramanan 2525d76a60baSAnirudh Venkataramanan for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID) { 2526d76a60baSAnirudh Venkataramanan err = ice_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q), vid); 2527d76a60baSAnirudh Venkataramanan if (err) 2528d76a60baSAnirudh Venkataramanan break; 2529d76a60baSAnirudh Venkataramanan } 2530d76a60baSAnirudh Venkataramanan 2531d76a60baSAnirudh Venkataramanan return err; 2532d76a60baSAnirudh Venkataramanan } 2533d76a60baSAnirudh Venkataramanan 2534d76a60baSAnirudh Venkataramanan /** 2535cdedef59SAnirudh Venkataramanan * ice_vsi_cfg - Setup the VSI 2536cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 2537cdedef59SAnirudh Venkataramanan * 2538cdedef59SAnirudh Venkataramanan * Return 0 on success and negative value on error 2539cdedef59SAnirudh Venkataramanan */ 2540cdedef59SAnirudh Venkataramanan static int ice_vsi_cfg(struct ice_vsi *vsi) 2541cdedef59SAnirudh Venkataramanan { 2542cdedef59SAnirudh Venkataramanan int err; 2543cdedef59SAnirudh Venkataramanan 2544c7f2c42bSAnirudh Venkataramanan if (vsi->netdev) { 2545e94d4478SAnirudh Venkataramanan ice_set_rx_mode(vsi->netdev); 2546d76a60baSAnirudh Venkataramanan err = ice_restore_vlan(vsi); 2547d76a60baSAnirudh Venkataramanan if (err) 2548d76a60baSAnirudh Venkataramanan return err; 2549c7f2c42bSAnirudh Venkataramanan } 2550d76a60baSAnirudh Venkataramanan 2551cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg_txqs(vsi); 2552cdedef59SAnirudh Venkataramanan if (!err) 2553cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg_rxqs(vsi); 2554cdedef59SAnirudh Venkataramanan 2555cdedef59SAnirudh Venkataramanan return err; 2556cdedef59SAnirudh Venkataramanan } 2557cdedef59SAnirudh Venkataramanan 2558cdedef59SAnirudh Venkataramanan /** 25592b245cb2SAnirudh Venkataramanan * ice_napi_enable_all - Enable NAPI for all q_vectors in the VSI 25602b245cb2SAnirudh Venkataramanan * @vsi: the VSI being configured 25612b245cb2SAnirudh Venkataramanan */ 25622b245cb2SAnirudh Venkataramanan static void ice_napi_enable_all(struct ice_vsi *vsi) 25632b245cb2SAnirudh Venkataramanan { 25642b245cb2SAnirudh Venkataramanan int q_idx; 25652b245cb2SAnirudh Venkataramanan 25662b245cb2SAnirudh Venkataramanan if (!vsi->netdev) 25672b245cb2SAnirudh Venkataramanan return; 25682b245cb2SAnirudh Venkataramanan 25692b245cb2SAnirudh Venkataramanan for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) 25702b245cb2SAnirudh Venkataramanan napi_enable(&vsi->q_vectors[q_idx]->napi); 25712b245cb2SAnirudh Venkataramanan } 25722b245cb2SAnirudh Venkataramanan 25732b245cb2SAnirudh Venkataramanan /** 2574cdedef59SAnirudh Venkataramanan * ice_up_complete - Finish the last steps of bringing up a connection 2575cdedef59SAnirudh Venkataramanan * @vsi: The VSI being configured 2576cdedef59SAnirudh Venkataramanan * 2577cdedef59SAnirudh Venkataramanan * Return 0 on success and negative value on error 2578cdedef59SAnirudh Venkataramanan */ 2579cdedef59SAnirudh Venkataramanan static int ice_up_complete(struct ice_vsi *vsi) 2580cdedef59SAnirudh Venkataramanan { 2581cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2582cdedef59SAnirudh Venkataramanan int err; 2583cdedef59SAnirudh Venkataramanan 2584cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 2585cdedef59SAnirudh Venkataramanan ice_vsi_cfg_msix(vsi); 2586cdedef59SAnirudh Venkataramanan else 2587cdedef59SAnirudh Venkataramanan return -ENOTSUPP; 2588cdedef59SAnirudh Venkataramanan 2589cdedef59SAnirudh Venkataramanan /* Enable only Rx rings, Tx rings were enabled by the FW when the 2590cdedef59SAnirudh Venkataramanan * Tx queue group list was configured and the context bits were 2591cdedef59SAnirudh Venkataramanan * programmed using ice_vsi_cfg_txqs 2592cdedef59SAnirudh Venkataramanan */ 2593cdedef59SAnirudh Venkataramanan err = ice_vsi_start_rx_rings(vsi); 2594cdedef59SAnirudh Venkataramanan if (err) 2595cdedef59SAnirudh Venkataramanan return err; 2596cdedef59SAnirudh Venkataramanan 2597cdedef59SAnirudh Venkataramanan clear_bit(__ICE_DOWN, vsi->state); 25982b245cb2SAnirudh Venkataramanan ice_napi_enable_all(vsi); 2599cdedef59SAnirudh Venkataramanan ice_vsi_ena_irq(vsi); 2600cdedef59SAnirudh Venkataramanan 2601cdedef59SAnirudh Venkataramanan if (vsi->port_info && 2602cdedef59SAnirudh Venkataramanan (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) && 2603cdedef59SAnirudh Venkataramanan vsi->netdev) { 2604cdedef59SAnirudh Venkataramanan ice_print_link_msg(vsi, true); 2605cdedef59SAnirudh Venkataramanan netif_tx_start_all_queues(vsi->netdev); 2606cdedef59SAnirudh Venkataramanan netif_carrier_on(vsi->netdev); 2607cdedef59SAnirudh Venkataramanan } 2608cdedef59SAnirudh Venkataramanan 2609cdedef59SAnirudh Venkataramanan ice_service_task_schedule(pf); 2610cdedef59SAnirudh Venkataramanan 2611cdedef59SAnirudh Venkataramanan return err; 2612cdedef59SAnirudh Venkataramanan } 2613cdedef59SAnirudh Venkataramanan 2614cdedef59SAnirudh Venkataramanan /** 2615fcea6f3dSAnirudh Venkataramanan * ice_up - Bring the connection back up after being down 2616fcea6f3dSAnirudh Venkataramanan * @vsi: VSI being configured 2617fcea6f3dSAnirudh Venkataramanan */ 2618fcea6f3dSAnirudh Venkataramanan int ice_up(struct ice_vsi *vsi) 2619fcea6f3dSAnirudh Venkataramanan { 2620fcea6f3dSAnirudh Venkataramanan int err; 2621fcea6f3dSAnirudh Venkataramanan 2622fcea6f3dSAnirudh Venkataramanan err = ice_vsi_cfg(vsi); 2623fcea6f3dSAnirudh Venkataramanan if (!err) 2624fcea6f3dSAnirudh Venkataramanan err = ice_up_complete(vsi); 2625fcea6f3dSAnirudh Venkataramanan 2626fcea6f3dSAnirudh Venkataramanan return err; 2627fcea6f3dSAnirudh Venkataramanan } 2628fcea6f3dSAnirudh Venkataramanan 2629fcea6f3dSAnirudh Venkataramanan /** 2630fcea6f3dSAnirudh Venkataramanan * ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring 2631fcea6f3dSAnirudh Venkataramanan * @ring: Tx or Rx ring to read stats from 2632fcea6f3dSAnirudh Venkataramanan * @pkts: packets stats counter 2633fcea6f3dSAnirudh Venkataramanan * @bytes: bytes stats counter 2634fcea6f3dSAnirudh Venkataramanan * 2635fcea6f3dSAnirudh Venkataramanan * This function fetches stats from the ring considering the atomic operations 2636fcea6f3dSAnirudh Venkataramanan * that needs to be performed to read u64 values in 32 bit machine. 2637fcea6f3dSAnirudh Venkataramanan */ 2638fcea6f3dSAnirudh Venkataramanan static void ice_fetch_u64_stats_per_ring(struct ice_ring *ring, u64 *pkts, 2639fcea6f3dSAnirudh Venkataramanan u64 *bytes) 2640fcea6f3dSAnirudh Venkataramanan { 2641fcea6f3dSAnirudh Venkataramanan unsigned int start; 2642fcea6f3dSAnirudh Venkataramanan *pkts = 0; 2643fcea6f3dSAnirudh Venkataramanan *bytes = 0; 2644fcea6f3dSAnirudh Venkataramanan 2645fcea6f3dSAnirudh Venkataramanan if (!ring) 2646fcea6f3dSAnirudh Venkataramanan return; 2647fcea6f3dSAnirudh Venkataramanan do { 2648fcea6f3dSAnirudh Venkataramanan start = u64_stats_fetch_begin_irq(&ring->syncp); 2649fcea6f3dSAnirudh Venkataramanan *pkts = ring->stats.pkts; 2650fcea6f3dSAnirudh Venkataramanan *bytes = ring->stats.bytes; 2651fcea6f3dSAnirudh Venkataramanan } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 2652fcea6f3dSAnirudh Venkataramanan } 2653fcea6f3dSAnirudh Venkataramanan 2654fcea6f3dSAnirudh Venkataramanan /** 2655fcea6f3dSAnirudh Venkataramanan * ice_update_vsi_ring_stats - Update VSI stats counters 2656fcea6f3dSAnirudh Venkataramanan * @vsi: the VSI to be updated 2657fcea6f3dSAnirudh Venkataramanan */ 2658fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) 2659fcea6f3dSAnirudh Venkataramanan { 2660fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats; 2661fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 2662fcea6f3dSAnirudh Venkataramanan u64 pkts, bytes; 2663fcea6f3dSAnirudh Venkataramanan int i; 2664fcea6f3dSAnirudh Venkataramanan 2665fcea6f3dSAnirudh Venkataramanan /* reset netdev stats */ 2666fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_packets = 0; 2667fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_bytes = 0; 2668fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_packets = 0; 2669fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_bytes = 0; 2670fcea6f3dSAnirudh Venkataramanan 2671fcea6f3dSAnirudh Venkataramanan /* reset non-netdev (extended) stats */ 2672fcea6f3dSAnirudh Venkataramanan vsi->tx_restart = 0; 2673fcea6f3dSAnirudh Venkataramanan vsi->tx_busy = 0; 2674fcea6f3dSAnirudh Venkataramanan vsi->tx_linearize = 0; 2675fcea6f3dSAnirudh Venkataramanan vsi->rx_buf_failed = 0; 2676fcea6f3dSAnirudh Venkataramanan vsi->rx_page_failed = 0; 2677fcea6f3dSAnirudh Venkataramanan 2678fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 2679fcea6f3dSAnirudh Venkataramanan 2680fcea6f3dSAnirudh Venkataramanan /* update Tx rings counters */ 2681fcea6f3dSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 2682fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[i]); 2683fcea6f3dSAnirudh Venkataramanan ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes); 2684fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_packets += pkts; 2685fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_bytes += bytes; 2686fcea6f3dSAnirudh Venkataramanan vsi->tx_restart += ring->tx_stats.restart_q; 2687fcea6f3dSAnirudh Venkataramanan vsi->tx_busy += ring->tx_stats.tx_busy; 2688fcea6f3dSAnirudh Venkataramanan vsi->tx_linearize += ring->tx_stats.tx_linearize; 2689fcea6f3dSAnirudh Venkataramanan } 2690fcea6f3dSAnirudh Venkataramanan 2691fcea6f3dSAnirudh Venkataramanan /* update Rx rings counters */ 2692fcea6f3dSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 2693fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[i]); 2694fcea6f3dSAnirudh Venkataramanan ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes); 2695fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_packets += pkts; 2696fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_bytes += bytes; 2697fcea6f3dSAnirudh Venkataramanan vsi->rx_buf_failed += ring->rx_stats.alloc_buf_failed; 2698fcea6f3dSAnirudh Venkataramanan vsi->rx_page_failed += ring->rx_stats.alloc_page_failed; 2699fcea6f3dSAnirudh Venkataramanan } 2700fcea6f3dSAnirudh Venkataramanan 2701fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 2702fcea6f3dSAnirudh Venkataramanan } 2703fcea6f3dSAnirudh Venkataramanan 2704fcea6f3dSAnirudh Venkataramanan /** 2705fcea6f3dSAnirudh Venkataramanan * ice_update_vsi_stats - Update VSI stats counters 2706fcea6f3dSAnirudh Venkataramanan * @vsi: the VSI to be updated 2707fcea6f3dSAnirudh Venkataramanan */ 2708fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi) 2709fcea6f3dSAnirudh Venkataramanan { 2710fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *cur_ns = &vsi->net_stats; 2711fcea6f3dSAnirudh Venkataramanan struct ice_eth_stats *cur_es = &vsi->eth_stats; 2712fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2713fcea6f3dSAnirudh Venkataramanan 2714fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state) || 2715fcea6f3dSAnirudh Venkataramanan test_bit(__ICE_CFG_BUSY, pf->state)) 2716fcea6f3dSAnirudh Venkataramanan return; 2717fcea6f3dSAnirudh Venkataramanan 2718fcea6f3dSAnirudh Venkataramanan /* get stats as recorded by Tx/Rx rings */ 2719fcea6f3dSAnirudh Venkataramanan ice_update_vsi_ring_stats(vsi); 2720fcea6f3dSAnirudh Venkataramanan 2721fcea6f3dSAnirudh Venkataramanan /* get VSI stats as recorded by the hardware */ 2722fcea6f3dSAnirudh Venkataramanan ice_update_eth_stats(vsi); 2723fcea6f3dSAnirudh Venkataramanan 2724fcea6f3dSAnirudh Venkataramanan cur_ns->tx_errors = cur_es->tx_errors; 2725fcea6f3dSAnirudh Venkataramanan cur_ns->rx_dropped = cur_es->rx_discards; 2726fcea6f3dSAnirudh Venkataramanan cur_ns->tx_dropped = cur_es->tx_discards; 2727fcea6f3dSAnirudh Venkataramanan cur_ns->multicast = cur_es->rx_multicast; 2728fcea6f3dSAnirudh Venkataramanan 2729fcea6f3dSAnirudh Venkataramanan /* update some more netdev stats if this is main VSI */ 2730fcea6f3dSAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 2731fcea6f3dSAnirudh Venkataramanan cur_ns->rx_crc_errors = pf->stats.crc_errors; 2732fcea6f3dSAnirudh Venkataramanan cur_ns->rx_errors = pf->stats.crc_errors + 2733fcea6f3dSAnirudh Venkataramanan pf->stats.illegal_bytes; 2734fcea6f3dSAnirudh Venkataramanan cur_ns->rx_length_errors = pf->stats.rx_len_errors; 2735fcea6f3dSAnirudh Venkataramanan } 2736fcea6f3dSAnirudh Venkataramanan } 2737fcea6f3dSAnirudh Venkataramanan 2738fcea6f3dSAnirudh Venkataramanan /** 2739fcea6f3dSAnirudh Venkataramanan * ice_update_pf_stats - Update PF port stats counters 2740fcea6f3dSAnirudh Venkataramanan * @pf: PF whose stats needs to be updated 2741fcea6f3dSAnirudh Venkataramanan */ 2742fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf) 2743fcea6f3dSAnirudh Venkataramanan { 2744fcea6f3dSAnirudh Venkataramanan struct ice_hw_port_stats *prev_ps, *cur_ps; 2745fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2746fcea6f3dSAnirudh Venkataramanan u8 pf_id; 2747fcea6f3dSAnirudh Venkataramanan 2748fcea6f3dSAnirudh Venkataramanan prev_ps = &pf->stats_prev; 2749fcea6f3dSAnirudh Venkataramanan cur_ps = &pf->stats; 2750fcea6f3dSAnirudh Venkataramanan pf_id = hw->pf_id; 2751fcea6f3dSAnirudh Venkataramanan 2752fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_GORCH(pf_id), GLPRT_GORCL(pf_id), 2753fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_bytes, 2754fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_bytes); 2755fcea6f3dSAnirudh Venkataramanan 2756fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_UPRCH(pf_id), GLPRT_UPRCL(pf_id), 2757fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_unicast, 2758fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_unicast); 2759fcea6f3dSAnirudh Venkataramanan 2760fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_MPRCH(pf_id), GLPRT_MPRCL(pf_id), 2761fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_multicast, 2762fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_multicast); 2763fcea6f3dSAnirudh Venkataramanan 2764fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_BPRCH(pf_id), GLPRT_BPRCL(pf_id), 2765fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_broadcast, 2766fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_broadcast); 2767fcea6f3dSAnirudh Venkataramanan 2768fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_GOTCH(pf_id), GLPRT_GOTCL(pf_id), 2769fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_bytes, 2770fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_bytes); 2771fcea6f3dSAnirudh Venkataramanan 2772fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_UPTCH(pf_id), GLPRT_UPTCL(pf_id), 2773fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_unicast, 2774fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_unicast); 2775fcea6f3dSAnirudh Venkataramanan 2776fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_MPTCH(pf_id), GLPRT_MPTCL(pf_id), 2777fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_multicast, 2778fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_multicast); 2779fcea6f3dSAnirudh Venkataramanan 2780fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_BPTCH(pf_id), GLPRT_BPTCL(pf_id), 2781fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_broadcast, 2782fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_broadcast); 2783fcea6f3dSAnirudh Venkataramanan 2784fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_TDOLD(pf_id), pf->stat_prev_loaded, 2785fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_dropped_link_down, 2786fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_dropped_link_down); 2787fcea6f3dSAnirudh Venkataramanan 2788fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC64H(pf_id), GLPRT_PRC64L(pf_id), 2789fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_64, 2790fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_64); 2791fcea6f3dSAnirudh Venkataramanan 2792fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC127H(pf_id), GLPRT_PRC127L(pf_id), 2793fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_127, 2794fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_127); 2795fcea6f3dSAnirudh Venkataramanan 2796fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC255H(pf_id), GLPRT_PRC255L(pf_id), 2797fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_255, 2798fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_255); 2799fcea6f3dSAnirudh Venkataramanan 2800fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC511H(pf_id), GLPRT_PRC511L(pf_id), 2801fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_511, 2802fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_511); 2803fcea6f3dSAnirudh Venkataramanan 2804fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC1023H(pf_id), 2805fcea6f3dSAnirudh Venkataramanan GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded, 2806fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_1023, &cur_ps->rx_size_1023); 2807fcea6f3dSAnirudh Venkataramanan 2808fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC1522H(pf_id), 2809fcea6f3dSAnirudh Venkataramanan GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded, 2810fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_1522, &cur_ps->rx_size_1522); 2811fcea6f3dSAnirudh Venkataramanan 2812fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC9522H(pf_id), 2813fcea6f3dSAnirudh Venkataramanan GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded, 2814fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_big, &cur_ps->rx_size_big); 2815fcea6f3dSAnirudh Venkataramanan 2816fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC64H(pf_id), GLPRT_PTC64L(pf_id), 2817fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_64, 2818fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_64); 2819fcea6f3dSAnirudh Venkataramanan 2820fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC127H(pf_id), GLPRT_PTC127L(pf_id), 2821fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_127, 2822fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_127); 2823fcea6f3dSAnirudh Venkataramanan 2824fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC255H(pf_id), GLPRT_PTC255L(pf_id), 2825fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_255, 2826fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_255); 2827fcea6f3dSAnirudh Venkataramanan 2828fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC511H(pf_id), GLPRT_PTC511L(pf_id), 2829fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_511, 2830fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_511); 2831fcea6f3dSAnirudh Venkataramanan 2832fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC1023H(pf_id), 2833fcea6f3dSAnirudh Venkataramanan GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded, 2834fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_1023, &cur_ps->tx_size_1023); 2835fcea6f3dSAnirudh Venkataramanan 2836fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC1522H(pf_id), 2837fcea6f3dSAnirudh Venkataramanan GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded, 2838fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_1522, &cur_ps->tx_size_1522); 2839fcea6f3dSAnirudh Venkataramanan 2840fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC9522H(pf_id), 2841fcea6f3dSAnirudh Venkataramanan GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded, 2842fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_big, &cur_ps->tx_size_big); 2843fcea6f3dSAnirudh Venkataramanan 2844fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXONRXC(pf_id), pf->stat_prev_loaded, 2845fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xon_rx, &cur_ps->link_xon_rx); 2846fcea6f3dSAnirudh Venkataramanan 2847fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXOFFRXC(pf_id), pf->stat_prev_loaded, 2848fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xoff_rx, &cur_ps->link_xoff_rx); 2849fcea6f3dSAnirudh Venkataramanan 2850fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXONTXC(pf_id), pf->stat_prev_loaded, 2851fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xon_tx, &cur_ps->link_xon_tx); 2852fcea6f3dSAnirudh Venkataramanan 2853fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXOFFTXC(pf_id), pf->stat_prev_loaded, 2854fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xoff_tx, &cur_ps->link_xoff_tx); 2855fcea6f3dSAnirudh Venkataramanan 2856fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_CRCERRS(pf_id), pf->stat_prev_loaded, 2857fcea6f3dSAnirudh Venkataramanan &prev_ps->crc_errors, &cur_ps->crc_errors); 2858fcea6f3dSAnirudh Venkataramanan 2859fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_ILLERRC(pf_id), pf->stat_prev_loaded, 2860fcea6f3dSAnirudh Venkataramanan &prev_ps->illegal_bytes, &cur_ps->illegal_bytes); 2861fcea6f3dSAnirudh Venkataramanan 2862fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_MLFC(pf_id), pf->stat_prev_loaded, 2863fcea6f3dSAnirudh Venkataramanan &prev_ps->mac_local_faults, 2864fcea6f3dSAnirudh Venkataramanan &cur_ps->mac_local_faults); 2865fcea6f3dSAnirudh Venkataramanan 2866fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_MRFC(pf_id), pf->stat_prev_loaded, 2867fcea6f3dSAnirudh Venkataramanan &prev_ps->mac_remote_faults, 2868fcea6f3dSAnirudh Venkataramanan &cur_ps->mac_remote_faults); 2869fcea6f3dSAnirudh Venkataramanan 2870fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RLEC(pf_id), pf->stat_prev_loaded, 2871fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_len_errors, &cur_ps->rx_len_errors); 2872fcea6f3dSAnirudh Venkataramanan 2873fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RUC(pf_id), pf->stat_prev_loaded, 2874fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_undersize, &cur_ps->rx_undersize); 2875fcea6f3dSAnirudh Venkataramanan 2876fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RFC(pf_id), pf->stat_prev_loaded, 2877fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_fragments, &cur_ps->rx_fragments); 2878fcea6f3dSAnirudh Venkataramanan 2879fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_ROC(pf_id), pf->stat_prev_loaded, 2880fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_oversize, &cur_ps->rx_oversize); 2881fcea6f3dSAnirudh Venkataramanan 2882fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RJC(pf_id), pf->stat_prev_loaded, 2883fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_jabber, &cur_ps->rx_jabber); 2884fcea6f3dSAnirudh Venkataramanan 2885fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded = true; 2886fcea6f3dSAnirudh Venkataramanan } 2887fcea6f3dSAnirudh Venkataramanan 2888fcea6f3dSAnirudh Venkataramanan /** 2889fcea6f3dSAnirudh Venkataramanan * ice_get_stats64 - get statistics for network device structure 2890fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2891fcea6f3dSAnirudh Venkataramanan * @stats: main device statistics structure 2892fcea6f3dSAnirudh Venkataramanan */ 2893fcea6f3dSAnirudh Venkataramanan static 2894fcea6f3dSAnirudh Venkataramanan void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) 2895fcea6f3dSAnirudh Venkataramanan { 2896fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2897fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *vsi_stats; 2898fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2899fcea6f3dSAnirudh Venkataramanan 2900fcea6f3dSAnirudh Venkataramanan vsi_stats = &vsi->net_stats; 2901fcea6f3dSAnirudh Venkataramanan 2902fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state) || !vsi->num_txq || !vsi->num_rxq) 2903fcea6f3dSAnirudh Venkataramanan return; 2904fcea6f3dSAnirudh Venkataramanan /* netdev packet/byte stats come from ring counter. These are obtained 2905fcea6f3dSAnirudh Venkataramanan * by summing up ring counters (done by ice_update_vsi_ring_stats). 2906fcea6f3dSAnirudh Venkataramanan */ 2907fcea6f3dSAnirudh Venkataramanan ice_update_vsi_ring_stats(vsi); 2908fcea6f3dSAnirudh Venkataramanan stats->tx_packets = vsi_stats->tx_packets; 2909fcea6f3dSAnirudh Venkataramanan stats->tx_bytes = vsi_stats->tx_bytes; 2910fcea6f3dSAnirudh Venkataramanan stats->rx_packets = vsi_stats->rx_packets; 2911fcea6f3dSAnirudh Venkataramanan stats->rx_bytes = vsi_stats->rx_bytes; 2912fcea6f3dSAnirudh Venkataramanan 2913fcea6f3dSAnirudh Venkataramanan /* The rest of the stats can be read from the hardware but instead we 2914fcea6f3dSAnirudh Venkataramanan * just return values that the watchdog task has already obtained from 2915fcea6f3dSAnirudh Venkataramanan * the hardware. 2916fcea6f3dSAnirudh Venkataramanan */ 2917fcea6f3dSAnirudh Venkataramanan stats->multicast = vsi_stats->multicast; 2918fcea6f3dSAnirudh Venkataramanan stats->tx_errors = vsi_stats->tx_errors; 2919fcea6f3dSAnirudh Venkataramanan stats->tx_dropped = vsi_stats->tx_dropped; 2920fcea6f3dSAnirudh Venkataramanan stats->rx_errors = vsi_stats->rx_errors; 2921fcea6f3dSAnirudh Venkataramanan stats->rx_dropped = vsi_stats->rx_dropped; 2922fcea6f3dSAnirudh Venkataramanan stats->rx_crc_errors = vsi_stats->rx_crc_errors; 2923fcea6f3dSAnirudh Venkataramanan stats->rx_length_errors = vsi_stats->rx_length_errors; 2924fcea6f3dSAnirudh Venkataramanan } 2925fcea6f3dSAnirudh Venkataramanan 2926fcea6f3dSAnirudh Venkataramanan /** 29272b245cb2SAnirudh Venkataramanan * ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI 29282b245cb2SAnirudh Venkataramanan * @vsi: VSI having NAPI disabled 29292b245cb2SAnirudh Venkataramanan */ 29302b245cb2SAnirudh Venkataramanan static void ice_napi_disable_all(struct ice_vsi *vsi) 29312b245cb2SAnirudh Venkataramanan { 29322b245cb2SAnirudh Venkataramanan int q_idx; 29332b245cb2SAnirudh Venkataramanan 29342b245cb2SAnirudh Venkataramanan if (!vsi->netdev) 29352b245cb2SAnirudh Venkataramanan return; 29362b245cb2SAnirudh Venkataramanan 29372b245cb2SAnirudh Venkataramanan for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) 29382b245cb2SAnirudh Venkataramanan napi_disable(&vsi->q_vectors[q_idx]->napi); 29392b245cb2SAnirudh Venkataramanan } 29402b245cb2SAnirudh Venkataramanan 29412b245cb2SAnirudh Venkataramanan /** 2942cdedef59SAnirudh Venkataramanan * ice_down - Shutdown the connection 2943cdedef59SAnirudh Venkataramanan * @vsi: The VSI being stopped 2944cdedef59SAnirudh Venkataramanan */ 2945fcea6f3dSAnirudh Venkataramanan int ice_down(struct ice_vsi *vsi) 2946cdedef59SAnirudh Venkataramanan { 294772adf242SAnirudh Venkataramanan int i, tx_err, rx_err; 2948cdedef59SAnirudh Venkataramanan 2949cdedef59SAnirudh Venkataramanan /* Caller of this function is expected to set the 2950cdedef59SAnirudh Venkataramanan * vsi->state __ICE_DOWN bit 2951cdedef59SAnirudh Venkataramanan */ 2952cdedef59SAnirudh Venkataramanan if (vsi->netdev) { 2953cdedef59SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 2954cdedef59SAnirudh Venkataramanan netif_tx_disable(vsi->netdev); 2955cdedef59SAnirudh Venkataramanan } 2956cdedef59SAnirudh Venkataramanan 2957cdedef59SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 295872adf242SAnirudh Venkataramanan tx_err = ice_vsi_stop_tx_rings(vsi); 295972adf242SAnirudh Venkataramanan if (tx_err) 296072adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 296172adf242SAnirudh Venkataramanan "Failed stop Tx rings, VSI %d error %d\n", 296272adf242SAnirudh Venkataramanan vsi->vsi_num, tx_err); 296372adf242SAnirudh Venkataramanan 296472adf242SAnirudh Venkataramanan rx_err = ice_vsi_stop_rx_rings(vsi); 296572adf242SAnirudh Venkataramanan if (rx_err) 296672adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 296772adf242SAnirudh Venkataramanan "Failed stop Rx rings, VSI %d error %d\n", 296872adf242SAnirudh Venkataramanan vsi->vsi_num, rx_err); 296972adf242SAnirudh Venkataramanan 29702b245cb2SAnirudh Venkataramanan ice_napi_disable_all(vsi); 2971cdedef59SAnirudh Venkataramanan 2972cdedef59SAnirudh Venkataramanan ice_for_each_txq(vsi, i) 2973cdedef59SAnirudh Venkataramanan ice_clean_tx_ring(vsi->tx_rings[i]); 2974cdedef59SAnirudh Venkataramanan 2975cdedef59SAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 2976cdedef59SAnirudh Venkataramanan ice_clean_rx_ring(vsi->rx_rings[i]); 2977cdedef59SAnirudh Venkataramanan 297872adf242SAnirudh Venkataramanan if (tx_err || rx_err) { 297972adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 298072adf242SAnirudh Venkataramanan "Failed to close VSI 0x%04X on switch 0x%04X\n", 2981cdedef59SAnirudh Venkataramanan vsi->vsi_num, vsi->vsw->sw_id); 298272adf242SAnirudh Venkataramanan return -EIO; 298372adf242SAnirudh Venkataramanan } 298472adf242SAnirudh Venkataramanan 298572adf242SAnirudh Venkataramanan return 0; 2986cdedef59SAnirudh Venkataramanan } 2987cdedef59SAnirudh Venkataramanan 2988cdedef59SAnirudh Venkataramanan /** 2989cdedef59SAnirudh Venkataramanan * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources 2990cdedef59SAnirudh Venkataramanan * @vsi: VSI having resources allocated 2991cdedef59SAnirudh Venkataramanan * 2992cdedef59SAnirudh Venkataramanan * Return 0 on success, negative on failure 2993cdedef59SAnirudh Venkataramanan */ 2994cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi) 2995cdedef59SAnirudh Venkataramanan { 2996dab0588fSJesse Brandeburg int i, err = 0; 2997cdedef59SAnirudh Venkataramanan 2998cdedef59SAnirudh Venkataramanan if (!vsi->num_txq) { 2999cdedef59SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Tx queues\n", 3000cdedef59SAnirudh Venkataramanan vsi->vsi_num); 3001cdedef59SAnirudh Venkataramanan return -EINVAL; 3002cdedef59SAnirudh Venkataramanan } 3003cdedef59SAnirudh Venkataramanan 3004cdedef59SAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 300572adf242SAnirudh Venkataramanan vsi->tx_rings[i]->netdev = vsi->netdev; 3006cdedef59SAnirudh Venkataramanan err = ice_setup_tx_ring(vsi->tx_rings[i]); 3007cdedef59SAnirudh Venkataramanan if (err) 3008cdedef59SAnirudh Venkataramanan break; 3009cdedef59SAnirudh Venkataramanan } 3010cdedef59SAnirudh Venkataramanan 3011cdedef59SAnirudh Venkataramanan return err; 3012cdedef59SAnirudh Venkataramanan } 3013cdedef59SAnirudh Venkataramanan 3014cdedef59SAnirudh Venkataramanan /** 3015cdedef59SAnirudh Venkataramanan * ice_vsi_setup_rx_rings - Allocate VSI Rx queue resources 3016cdedef59SAnirudh Venkataramanan * @vsi: VSI having resources allocated 3017cdedef59SAnirudh Venkataramanan * 3018cdedef59SAnirudh Venkataramanan * Return 0 on success, negative on failure 3019cdedef59SAnirudh Venkataramanan */ 3020cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi) 3021cdedef59SAnirudh Venkataramanan { 3022dab0588fSJesse Brandeburg int i, err = 0; 3023cdedef59SAnirudh Venkataramanan 3024cdedef59SAnirudh Venkataramanan if (!vsi->num_rxq) { 3025cdedef59SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Rx queues\n", 3026cdedef59SAnirudh Venkataramanan vsi->vsi_num); 3027cdedef59SAnirudh Venkataramanan return -EINVAL; 3028cdedef59SAnirudh Venkataramanan } 3029cdedef59SAnirudh Venkataramanan 3030cdedef59SAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 303172adf242SAnirudh Venkataramanan vsi->rx_rings[i]->netdev = vsi->netdev; 3032cdedef59SAnirudh Venkataramanan err = ice_setup_rx_ring(vsi->rx_rings[i]); 3033cdedef59SAnirudh Venkataramanan if (err) 3034cdedef59SAnirudh Venkataramanan break; 3035cdedef59SAnirudh Venkataramanan } 3036cdedef59SAnirudh Venkataramanan 3037cdedef59SAnirudh Venkataramanan return err; 3038cdedef59SAnirudh Venkataramanan } 3039cdedef59SAnirudh Venkataramanan 3040cdedef59SAnirudh Venkataramanan /** 3041cdedef59SAnirudh Venkataramanan * ice_vsi_req_irq - Request IRQ from the OS 3042cdedef59SAnirudh Venkataramanan * @vsi: The VSI IRQ is being requested for 3043cdedef59SAnirudh Venkataramanan * @basename: name for the vector 3044cdedef59SAnirudh Venkataramanan * 3045cdedef59SAnirudh Venkataramanan * Return 0 on success and a negative value on error 3046cdedef59SAnirudh Venkataramanan */ 3047cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq(struct ice_vsi *vsi, char *basename) 3048cdedef59SAnirudh Venkataramanan { 3049cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3050cdedef59SAnirudh Venkataramanan int err = -EINVAL; 3051cdedef59SAnirudh Venkataramanan 3052cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 3053cdedef59SAnirudh Venkataramanan err = ice_vsi_req_irq_msix(vsi, basename); 3054cdedef59SAnirudh Venkataramanan 3055cdedef59SAnirudh Venkataramanan return err; 3056cdedef59SAnirudh Venkataramanan } 3057cdedef59SAnirudh Venkataramanan 3058cdedef59SAnirudh Venkataramanan /** 3059cdedef59SAnirudh Venkataramanan * ice_vsi_open - Called when a network interface is made active 3060cdedef59SAnirudh Venkataramanan * @vsi: the VSI to open 3061cdedef59SAnirudh Venkataramanan * 3062cdedef59SAnirudh Venkataramanan * Initialization of the VSI 3063cdedef59SAnirudh Venkataramanan * 3064cdedef59SAnirudh Venkataramanan * Returns 0 on success, negative value on error 3065cdedef59SAnirudh Venkataramanan */ 3066cdedef59SAnirudh Venkataramanan static int ice_vsi_open(struct ice_vsi *vsi) 3067cdedef59SAnirudh Venkataramanan { 3068cdedef59SAnirudh Venkataramanan char int_name[ICE_INT_NAME_STR_LEN]; 3069cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3070cdedef59SAnirudh Venkataramanan int err; 3071cdedef59SAnirudh Venkataramanan 3072cdedef59SAnirudh Venkataramanan /* allocate descriptors */ 3073cdedef59SAnirudh Venkataramanan err = ice_vsi_setup_tx_rings(vsi); 3074cdedef59SAnirudh Venkataramanan if (err) 3075cdedef59SAnirudh Venkataramanan goto err_setup_tx; 3076cdedef59SAnirudh Venkataramanan 3077cdedef59SAnirudh Venkataramanan err = ice_vsi_setup_rx_rings(vsi); 3078cdedef59SAnirudh Venkataramanan if (err) 3079cdedef59SAnirudh Venkataramanan goto err_setup_rx; 3080cdedef59SAnirudh Venkataramanan 3081cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg(vsi); 3082cdedef59SAnirudh Venkataramanan if (err) 3083cdedef59SAnirudh Venkataramanan goto err_setup_rx; 3084cdedef59SAnirudh Venkataramanan 3085cdedef59SAnirudh Venkataramanan snprintf(int_name, sizeof(int_name) - 1, "%s-%s", 3086cdedef59SAnirudh Venkataramanan dev_driver_string(&pf->pdev->dev), vsi->netdev->name); 3087cdedef59SAnirudh Venkataramanan err = ice_vsi_req_irq(vsi, int_name); 3088cdedef59SAnirudh Venkataramanan if (err) 3089cdedef59SAnirudh Venkataramanan goto err_setup_rx; 3090cdedef59SAnirudh Venkataramanan 3091cdedef59SAnirudh Venkataramanan /* Notify the stack of the actual queue counts. */ 3092cdedef59SAnirudh Venkataramanan err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq); 3093cdedef59SAnirudh Venkataramanan if (err) 3094cdedef59SAnirudh Venkataramanan goto err_set_qs; 3095cdedef59SAnirudh Venkataramanan 3096cdedef59SAnirudh Venkataramanan err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq); 3097cdedef59SAnirudh Venkataramanan if (err) 3098cdedef59SAnirudh Venkataramanan goto err_set_qs; 3099cdedef59SAnirudh Venkataramanan 3100cdedef59SAnirudh Venkataramanan err = ice_up_complete(vsi); 3101cdedef59SAnirudh Venkataramanan if (err) 3102cdedef59SAnirudh Venkataramanan goto err_up_complete; 3103cdedef59SAnirudh Venkataramanan 3104cdedef59SAnirudh Venkataramanan return 0; 3105cdedef59SAnirudh Venkataramanan 3106cdedef59SAnirudh Venkataramanan err_up_complete: 3107cdedef59SAnirudh Venkataramanan ice_down(vsi); 3108cdedef59SAnirudh Venkataramanan err_set_qs: 3109cdedef59SAnirudh Venkataramanan ice_vsi_free_irq(vsi); 3110cdedef59SAnirudh Venkataramanan err_setup_rx: 3111cdedef59SAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 3112cdedef59SAnirudh Venkataramanan err_setup_tx: 3113cdedef59SAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 3114cdedef59SAnirudh Venkataramanan 3115cdedef59SAnirudh Venkataramanan return err; 3116cdedef59SAnirudh Venkataramanan } 3117cdedef59SAnirudh Venkataramanan 3118cdedef59SAnirudh Venkataramanan /** 31190f9d5027SAnirudh Venkataramanan * ice_vsi_release_all - Delete all VSIs 31200f9d5027SAnirudh Venkataramanan * @pf: PF from which all VSIs are being removed 31210f9d5027SAnirudh Venkataramanan */ 31220f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf) 31230f9d5027SAnirudh Venkataramanan { 31240f9d5027SAnirudh Venkataramanan int err, i; 31250f9d5027SAnirudh Venkataramanan 31260f9d5027SAnirudh Venkataramanan if (!pf->vsi) 31270f9d5027SAnirudh Venkataramanan return; 31280f9d5027SAnirudh Venkataramanan 31290f9d5027SAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) { 31300f9d5027SAnirudh Venkataramanan if (!pf->vsi[i]) 31310f9d5027SAnirudh Venkataramanan continue; 31320f9d5027SAnirudh Venkataramanan 31330f9d5027SAnirudh Venkataramanan err = ice_vsi_release(pf->vsi[i]); 31340f9d5027SAnirudh Venkataramanan if (err) 31350f9d5027SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 31360f9d5027SAnirudh Venkataramanan "Failed to release pf->vsi[%d], err %d, vsi_num = %d\n", 31370f9d5027SAnirudh Venkataramanan i, err, pf->vsi[i]->vsi_num); 31380f9d5027SAnirudh Venkataramanan } 31390f9d5027SAnirudh Venkataramanan } 31400f9d5027SAnirudh Venkataramanan 31410f9d5027SAnirudh Venkataramanan /** 31420b28b702SAnirudh Venkataramanan * ice_dis_vsi - pause a VSI 31430b28b702SAnirudh Venkataramanan * @vsi: the VSI being paused 31440b28b702SAnirudh Venkataramanan */ 31450b28b702SAnirudh Venkataramanan static void ice_dis_vsi(struct ice_vsi *vsi) 31460b28b702SAnirudh Venkataramanan { 31470b28b702SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state)) 31480b28b702SAnirudh Venkataramanan return; 31490b28b702SAnirudh Venkataramanan 31500b28b702SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, vsi->state); 31510b28b702SAnirudh Venkataramanan 31520b28b702SAnirudh Venkataramanan if (vsi->netdev && netif_running(vsi->netdev) && 31530f9d5027SAnirudh Venkataramanan vsi->type == ICE_VSI_PF) { 31540f9d5027SAnirudh Venkataramanan rtnl_lock(); 31550b28b702SAnirudh Venkataramanan vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); 31560f9d5027SAnirudh Venkataramanan rtnl_unlock(); 31570f9d5027SAnirudh Venkataramanan } else { 31580b28b702SAnirudh Venkataramanan ice_vsi_close(vsi); 31590b28b702SAnirudh Venkataramanan } 31600f9d5027SAnirudh Venkataramanan } 31610b28b702SAnirudh Venkataramanan 31620b28b702SAnirudh Venkataramanan /** 31630b28b702SAnirudh Venkataramanan * ice_ena_vsi - resume a VSI 31640b28b702SAnirudh Venkataramanan * @vsi: the VSI being resume 31650b28b702SAnirudh Venkataramanan */ 31660f9d5027SAnirudh Venkataramanan static int ice_ena_vsi(struct ice_vsi *vsi) 31670b28b702SAnirudh Venkataramanan { 31680f9d5027SAnirudh Venkataramanan int err = 0; 31690b28b702SAnirudh Venkataramanan 31700f9d5027SAnirudh Venkataramanan if (test_and_clear_bit(__ICE_NEEDS_RESTART, vsi->state)) 31710f9d5027SAnirudh Venkataramanan if (vsi->netdev && netif_running(vsi->netdev)) { 31720f9d5027SAnirudh Venkataramanan rtnl_lock(); 31730f9d5027SAnirudh Venkataramanan err = vsi->netdev->netdev_ops->ndo_open(vsi->netdev); 31740f9d5027SAnirudh Venkataramanan rtnl_unlock(); 31750f9d5027SAnirudh Venkataramanan } 31760f9d5027SAnirudh Venkataramanan 31770f9d5027SAnirudh Venkataramanan return err; 31780b28b702SAnirudh Venkataramanan } 31790b28b702SAnirudh Venkataramanan 31800b28b702SAnirudh Venkataramanan /** 31810b28b702SAnirudh Venkataramanan * ice_pf_dis_all_vsi - Pause all VSIs on a PF 31820b28b702SAnirudh Venkataramanan * @pf: the PF 31830b28b702SAnirudh Venkataramanan */ 31840b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf) 31850b28b702SAnirudh Venkataramanan { 31860b28b702SAnirudh Venkataramanan int v; 31870b28b702SAnirudh Venkataramanan 31880b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) 31890b28b702SAnirudh Venkataramanan if (pf->vsi[v]) 31900b28b702SAnirudh Venkataramanan ice_dis_vsi(pf->vsi[v]); 31910b28b702SAnirudh Venkataramanan } 31920b28b702SAnirudh Venkataramanan 31930b28b702SAnirudh Venkataramanan /** 31940b28b702SAnirudh Venkataramanan * ice_pf_ena_all_vsi - Resume all VSIs on a PF 31950b28b702SAnirudh Venkataramanan * @pf: the PF 31960b28b702SAnirudh Venkataramanan */ 31970f9d5027SAnirudh Venkataramanan static int ice_pf_ena_all_vsi(struct ice_pf *pf) 31980b28b702SAnirudh Venkataramanan { 31990b28b702SAnirudh Venkataramanan int v; 32000b28b702SAnirudh Venkataramanan 32010b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) 32020b28b702SAnirudh Venkataramanan if (pf->vsi[v]) 32030f9d5027SAnirudh Venkataramanan if (ice_ena_vsi(pf->vsi[v])) 32040f9d5027SAnirudh Venkataramanan return -EIO; 32050f9d5027SAnirudh Venkataramanan 32060f9d5027SAnirudh Venkataramanan return 0; 32070f9d5027SAnirudh Venkataramanan } 32080f9d5027SAnirudh Venkataramanan 32090f9d5027SAnirudh Venkataramanan /** 32100f9d5027SAnirudh Venkataramanan * ice_vsi_rebuild_all - rebuild all VSIs in pf 32110f9d5027SAnirudh Venkataramanan * @pf: the PF 32120f9d5027SAnirudh Venkataramanan */ 32130f9d5027SAnirudh Venkataramanan static int ice_vsi_rebuild_all(struct ice_pf *pf) 32140f9d5027SAnirudh Venkataramanan { 32150f9d5027SAnirudh Venkataramanan int i; 32160f9d5027SAnirudh Venkataramanan 32170f9d5027SAnirudh Venkataramanan /* loop through pf->vsi array and reinit the VSI if found */ 32180f9d5027SAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) { 32190f9d5027SAnirudh Venkataramanan int err; 32200f9d5027SAnirudh Venkataramanan 32210f9d5027SAnirudh Venkataramanan if (!pf->vsi[i]) 32220f9d5027SAnirudh Venkataramanan continue; 32230f9d5027SAnirudh Venkataramanan 32240f9d5027SAnirudh Venkataramanan err = ice_vsi_rebuild(pf->vsi[i]); 32250f9d5027SAnirudh Venkataramanan if (err) { 32260f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 32270f9d5027SAnirudh Venkataramanan "VSI at index %d rebuild failed\n", 32280f9d5027SAnirudh Venkataramanan pf->vsi[i]->idx); 32290f9d5027SAnirudh Venkataramanan return err; 32300f9d5027SAnirudh Venkataramanan } 32310f9d5027SAnirudh Venkataramanan 32320f9d5027SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 32330f9d5027SAnirudh Venkataramanan "VSI at index %d rebuilt. vsi_num = 0x%x\n", 32340f9d5027SAnirudh Venkataramanan pf->vsi[i]->idx, pf->vsi[i]->vsi_num); 32350f9d5027SAnirudh Venkataramanan } 32360f9d5027SAnirudh Venkataramanan 32370f9d5027SAnirudh Venkataramanan return 0; 32380b28b702SAnirudh Venkataramanan } 32390b28b702SAnirudh Venkataramanan 32400b28b702SAnirudh Venkataramanan /** 3241334cb062SAnirudh Venkataramanan * ice_vsi_replay_all - replay all VSIs configuration in the PF 3242334cb062SAnirudh Venkataramanan * @pf: the PF 3243334cb062SAnirudh Venkataramanan */ 3244334cb062SAnirudh Venkataramanan static int ice_vsi_replay_all(struct ice_pf *pf) 3245334cb062SAnirudh Venkataramanan { 3246334cb062SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3247334cb062SAnirudh Venkataramanan enum ice_status ret; 3248334cb062SAnirudh Venkataramanan int i; 3249334cb062SAnirudh Venkataramanan 3250334cb062SAnirudh Venkataramanan /* loop through pf->vsi array and replay the VSI if found */ 3251334cb062SAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) { 3252334cb062SAnirudh Venkataramanan if (!pf->vsi[i]) 3253334cb062SAnirudh Venkataramanan continue; 3254334cb062SAnirudh Venkataramanan 3255334cb062SAnirudh Venkataramanan ret = ice_replay_vsi(hw, pf->vsi[i]->idx); 3256334cb062SAnirudh Venkataramanan if (ret) { 3257334cb062SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3258334cb062SAnirudh Venkataramanan "VSI at index %d replay failed %d\n", 3259334cb062SAnirudh Venkataramanan pf->vsi[i]->idx, ret); 3260334cb062SAnirudh Venkataramanan return -EIO; 3261334cb062SAnirudh Venkataramanan } 3262334cb062SAnirudh Venkataramanan 3263334cb062SAnirudh Venkataramanan /* Re-map HW VSI number, using VSI handle that has been 3264334cb062SAnirudh Venkataramanan * previously validated in ice_replay_vsi() call above 3265334cb062SAnirudh Venkataramanan */ 3266334cb062SAnirudh Venkataramanan pf->vsi[i]->vsi_num = ice_get_hw_vsi_num(hw, pf->vsi[i]->idx); 3267334cb062SAnirudh Venkataramanan 3268334cb062SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 3269334cb062SAnirudh Venkataramanan "VSI at index %d filter replayed successfully - vsi_num %i\n", 3270334cb062SAnirudh Venkataramanan pf->vsi[i]->idx, pf->vsi[i]->vsi_num); 3271334cb062SAnirudh Venkataramanan } 3272334cb062SAnirudh Venkataramanan 3273334cb062SAnirudh Venkataramanan /* Clean up replay filter after successful re-configuration */ 3274334cb062SAnirudh Venkataramanan ice_replay_post(hw); 3275334cb062SAnirudh Venkataramanan return 0; 3276334cb062SAnirudh Venkataramanan } 3277334cb062SAnirudh Venkataramanan 3278334cb062SAnirudh Venkataramanan /** 32790b28b702SAnirudh Venkataramanan * ice_rebuild - rebuild after reset 32800b28b702SAnirudh Venkataramanan * @pf: pf to rebuild 32810b28b702SAnirudh Venkataramanan */ 32820b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf) 32830b28b702SAnirudh Venkataramanan { 32840b28b702SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 32850b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 32860b28b702SAnirudh Venkataramanan enum ice_status ret; 32870b28b702SAnirudh Venkataramanan int err; 32880b28b702SAnirudh Venkataramanan 32890b28b702SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state)) 32900b28b702SAnirudh Venkataramanan goto clear_recovery; 32910b28b702SAnirudh Venkataramanan 32920b28b702SAnirudh Venkataramanan dev_dbg(dev, "rebuilding pf\n"); 32930b28b702SAnirudh Venkataramanan 32940b28b702SAnirudh Venkataramanan ret = ice_init_all_ctrlq(hw); 32950b28b702SAnirudh Venkataramanan if (ret) { 32960b28b702SAnirudh Venkataramanan dev_err(dev, "control queues init failed %d\n", ret); 32970f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 32980b28b702SAnirudh Venkataramanan } 32990b28b702SAnirudh Venkataramanan 33000b28b702SAnirudh Venkataramanan ret = ice_clear_pf_cfg(hw); 33010b28b702SAnirudh Venkataramanan if (ret) { 33020b28b702SAnirudh Venkataramanan dev_err(dev, "clear PF configuration failed %d\n", ret); 33030f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 33040b28b702SAnirudh Venkataramanan } 33050b28b702SAnirudh Venkataramanan 33060b28b702SAnirudh Venkataramanan ice_clear_pxe_mode(hw); 33070b28b702SAnirudh Venkataramanan 33080b28b702SAnirudh Venkataramanan ret = ice_get_caps(hw); 33090b28b702SAnirudh Venkataramanan if (ret) { 33100b28b702SAnirudh Venkataramanan dev_err(dev, "ice_get_caps failed %d\n", ret); 33110f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 33120b28b702SAnirudh Venkataramanan } 33130b28b702SAnirudh Venkataramanan 33140f9d5027SAnirudh Venkataramanan err = ice_sched_init_port(hw->port_info); 33150f9d5027SAnirudh Venkataramanan if (err) 33160f9d5027SAnirudh Venkataramanan goto err_sched_init_port; 33170f9d5027SAnirudh Venkataramanan 3318eb0208ecSPreethi Banala /* reset search_hint of irq_trackers to 0 since interrupts are 3319eb0208ecSPreethi Banala * reclaimed and could be allocated from beginning during VSI rebuild 3320eb0208ecSPreethi Banala */ 3321eb0208ecSPreethi Banala pf->sw_irq_tracker->search_hint = 0; 3322eb0208ecSPreethi Banala pf->hw_irq_tracker->search_hint = 0; 3323eb0208ecSPreethi Banala 33240f9d5027SAnirudh Venkataramanan err = ice_vsi_rebuild_all(pf); 33250b28b702SAnirudh Venkataramanan if (err) { 33260f9d5027SAnirudh Venkataramanan dev_err(dev, "ice_vsi_rebuild_all failed\n"); 33270f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 33280f9d5027SAnirudh Venkataramanan } 33290f9d5027SAnirudh Venkataramanan 33305755143dSDave Ertman err = ice_update_link_info(hw->port_info); 33315755143dSDave Ertman if (err) 33325755143dSDave Ertman dev_err(&pf->pdev->dev, "Get link status error %d\n", err); 33335755143dSDave Ertman 3334334cb062SAnirudh Venkataramanan /* Replay all VSIs Configuration, including filters after reset */ 3335334cb062SAnirudh Venkataramanan if (ice_vsi_replay_all(pf)) { 33360f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3337334cb062SAnirudh Venkataramanan "error replaying VSI configurations with switch filter rules\n"); 33380f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 33390b28b702SAnirudh Venkataramanan } 33400b28b702SAnirudh Venkataramanan 33410b28b702SAnirudh Venkataramanan /* start misc vector */ 33420b28b702SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 33430b28b702SAnirudh Venkataramanan err = ice_req_irq_msix_misc(pf); 33440b28b702SAnirudh Venkataramanan if (err) { 33450b28b702SAnirudh Venkataramanan dev_err(dev, "misc vector setup failed: %d\n", err); 33460f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 33470b28b702SAnirudh Venkataramanan } 33480b28b702SAnirudh Venkataramanan } 33490b28b702SAnirudh Venkataramanan 33500b28b702SAnirudh Venkataramanan /* restart the VSIs that were rebuilt and running before the reset */ 33510f9d5027SAnirudh Venkataramanan err = ice_pf_ena_all_vsi(pf); 33520f9d5027SAnirudh Venkataramanan if (err) { 33530f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "error enabling VSIs\n"); 33540f9d5027SAnirudh Venkataramanan /* no need to disable VSIs in tear down path in ice_rebuild() 33550f9d5027SAnirudh Venkataramanan * since its already taken care in ice_vsi_open() 33560f9d5027SAnirudh Venkataramanan */ 33570f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 33580f9d5027SAnirudh Venkataramanan } 33590b28b702SAnirudh Venkataramanan 33600f9d5027SAnirudh Venkataramanan /* if we get here, reset flow is successful */ 33610f9d5027SAnirudh Venkataramanan clear_bit(__ICE_RESET_FAILED, pf->state); 33620b28b702SAnirudh Venkataramanan return; 33630b28b702SAnirudh Venkataramanan 33640f9d5027SAnirudh Venkataramanan err_vsi_rebuild: 33650f9d5027SAnirudh Venkataramanan ice_vsi_release_all(pf); 33660f9d5027SAnirudh Venkataramanan err_sched_init_port: 33670f9d5027SAnirudh Venkataramanan ice_sched_cleanup_all(hw); 33680f9d5027SAnirudh Venkataramanan err_init_ctrlq: 33690b28b702SAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 33700b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 33710b28b702SAnirudh Venkataramanan clear_recovery: 33720f9d5027SAnirudh Venkataramanan /* set this bit in PF state to control service task scheduling */ 33730f9d5027SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, pf->state); 33740f9d5027SAnirudh Venkataramanan dev_err(dev, "Rebuild failed, unload and reload driver\n"); 33750b28b702SAnirudh Venkataramanan } 33760b28b702SAnirudh Venkataramanan 33770b28b702SAnirudh Venkataramanan /** 3378e94d4478SAnirudh Venkataramanan * ice_change_mtu - NDO callback to change the MTU 3379e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 3380e94d4478SAnirudh Venkataramanan * @new_mtu: new value for maximum frame size 3381e94d4478SAnirudh Venkataramanan * 3382e94d4478SAnirudh Venkataramanan * Returns 0 on success, negative on failure 3383e94d4478SAnirudh Venkataramanan */ 3384e94d4478SAnirudh Venkataramanan static int ice_change_mtu(struct net_device *netdev, int new_mtu) 3385e94d4478SAnirudh Venkataramanan { 3386e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3387e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3388e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3389e94d4478SAnirudh Venkataramanan u8 count = 0; 3390e94d4478SAnirudh Venkataramanan 3391e94d4478SAnirudh Venkataramanan if (new_mtu == netdev->mtu) { 33923968540bSAnirudh Venkataramanan netdev_warn(netdev, "mtu is already %u\n", netdev->mtu); 3393e94d4478SAnirudh Venkataramanan return 0; 3394e94d4478SAnirudh Venkataramanan } 3395e94d4478SAnirudh Venkataramanan 3396e94d4478SAnirudh Venkataramanan if (new_mtu < netdev->min_mtu) { 3397e94d4478SAnirudh Venkataramanan netdev_err(netdev, "new mtu invalid. min_mtu is %d\n", 3398e94d4478SAnirudh Venkataramanan netdev->min_mtu); 3399e94d4478SAnirudh Venkataramanan return -EINVAL; 3400e94d4478SAnirudh Venkataramanan } else if (new_mtu > netdev->max_mtu) { 3401e94d4478SAnirudh Venkataramanan netdev_err(netdev, "new mtu invalid. max_mtu is %d\n", 3402e94d4478SAnirudh Venkataramanan netdev->min_mtu); 3403e94d4478SAnirudh Venkataramanan return -EINVAL; 3404e94d4478SAnirudh Venkataramanan } 3405e94d4478SAnirudh Venkataramanan /* if a reset is in progress, wait for some time for it to complete */ 3406e94d4478SAnirudh Venkataramanan do { 34075df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) { 3408e94d4478SAnirudh Venkataramanan count++; 3409e94d4478SAnirudh Venkataramanan usleep_range(1000, 2000); 3410e94d4478SAnirudh Venkataramanan } else { 3411e94d4478SAnirudh Venkataramanan break; 3412e94d4478SAnirudh Venkataramanan } 3413e94d4478SAnirudh Venkataramanan 3414e94d4478SAnirudh Venkataramanan } while (count < 100); 3415e94d4478SAnirudh Venkataramanan 3416e94d4478SAnirudh Venkataramanan if (count == 100) { 3417e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't change mtu. Device is busy\n"); 3418e94d4478SAnirudh Venkataramanan return -EBUSY; 3419e94d4478SAnirudh Venkataramanan } 3420e94d4478SAnirudh Venkataramanan 3421e94d4478SAnirudh Venkataramanan netdev->mtu = new_mtu; 3422e94d4478SAnirudh Venkataramanan 3423e94d4478SAnirudh Venkataramanan /* if VSI is up, bring it down and then back up */ 3424e94d4478SAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 3425e94d4478SAnirudh Venkataramanan int err; 3426e94d4478SAnirudh Venkataramanan 3427e94d4478SAnirudh Venkataramanan err = ice_down(vsi); 3428e94d4478SAnirudh Venkataramanan if (err) { 3429e94d4478SAnirudh Venkataramanan netdev_err(netdev, "change mtu if_up err %d\n", err); 3430e94d4478SAnirudh Venkataramanan return err; 3431e94d4478SAnirudh Venkataramanan } 3432e94d4478SAnirudh Venkataramanan 3433e94d4478SAnirudh Venkataramanan err = ice_up(vsi); 3434e94d4478SAnirudh Venkataramanan if (err) { 3435e94d4478SAnirudh Venkataramanan netdev_err(netdev, "change mtu if_up err %d\n", err); 3436e94d4478SAnirudh Venkataramanan return err; 3437e94d4478SAnirudh Venkataramanan } 3438e94d4478SAnirudh Venkataramanan } 3439e94d4478SAnirudh Venkataramanan 3440e94d4478SAnirudh Venkataramanan netdev_dbg(netdev, "changed mtu to %d\n", new_mtu); 3441e94d4478SAnirudh Venkataramanan return 0; 3442e94d4478SAnirudh Venkataramanan } 3443e94d4478SAnirudh Venkataramanan 3444e94d4478SAnirudh Venkataramanan /** 3445d76a60baSAnirudh Venkataramanan * ice_set_rss - Set RSS keys and lut 3446d76a60baSAnirudh Venkataramanan * @vsi: Pointer to VSI structure 3447d76a60baSAnirudh Venkataramanan * @seed: RSS hash seed 3448d76a60baSAnirudh Venkataramanan * @lut: Lookup table 3449d76a60baSAnirudh Venkataramanan * @lut_size: Lookup table size 3450d76a60baSAnirudh Venkataramanan * 3451d76a60baSAnirudh Venkataramanan * Returns 0 on success, negative on failure 3452d76a60baSAnirudh Venkataramanan */ 3453d76a60baSAnirudh Venkataramanan int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) 3454d76a60baSAnirudh Venkataramanan { 3455d76a60baSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3456d76a60baSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3457d76a60baSAnirudh Venkataramanan enum ice_status status; 3458d76a60baSAnirudh Venkataramanan 3459d76a60baSAnirudh Venkataramanan if (seed) { 3460d76a60baSAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *buf = 3461d76a60baSAnirudh Venkataramanan (struct ice_aqc_get_set_rss_keys *)seed; 3462d76a60baSAnirudh Venkataramanan 34634fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(hw, vsi->idx, buf); 3464d76a60baSAnirudh Venkataramanan 3465d76a60baSAnirudh Venkataramanan if (status) { 3466d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3467d76a60baSAnirudh Venkataramanan "Cannot set RSS key, err %d aq_err %d\n", 3468d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3469d76a60baSAnirudh Venkataramanan return -EIO; 3470d76a60baSAnirudh Venkataramanan } 3471d76a60baSAnirudh Venkataramanan } 3472d76a60baSAnirudh Venkataramanan 3473d76a60baSAnirudh Venkataramanan if (lut) { 34744fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type, 34754fb33f31SAnirudh Venkataramanan lut, lut_size); 3476d76a60baSAnirudh Venkataramanan if (status) { 3477d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3478d76a60baSAnirudh Venkataramanan "Cannot set RSS lut, err %d aq_err %d\n", 3479d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3480d76a60baSAnirudh Venkataramanan return -EIO; 3481d76a60baSAnirudh Venkataramanan } 3482d76a60baSAnirudh Venkataramanan } 3483d76a60baSAnirudh Venkataramanan 3484d76a60baSAnirudh Venkataramanan return 0; 3485d76a60baSAnirudh Venkataramanan } 3486d76a60baSAnirudh Venkataramanan 3487d76a60baSAnirudh Venkataramanan /** 3488d76a60baSAnirudh Venkataramanan * ice_get_rss - Get RSS keys and lut 3489d76a60baSAnirudh Venkataramanan * @vsi: Pointer to VSI structure 3490d76a60baSAnirudh Venkataramanan * @seed: Buffer to store the keys 3491d76a60baSAnirudh Venkataramanan * @lut: Buffer to store the lookup table entries 3492d76a60baSAnirudh Venkataramanan * @lut_size: Size of buffer to store the lookup table entries 3493d76a60baSAnirudh Venkataramanan * 3494d76a60baSAnirudh Venkataramanan * Returns 0 on success, negative on failure 3495d76a60baSAnirudh Venkataramanan */ 3496d76a60baSAnirudh Venkataramanan int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) 3497d76a60baSAnirudh Venkataramanan { 3498d76a60baSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3499d76a60baSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3500d76a60baSAnirudh Venkataramanan enum ice_status status; 3501d76a60baSAnirudh Venkataramanan 3502d76a60baSAnirudh Venkataramanan if (seed) { 3503d76a60baSAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *buf = 3504d76a60baSAnirudh Venkataramanan (struct ice_aqc_get_set_rss_keys *)seed; 3505d76a60baSAnirudh Venkataramanan 35064fb33f31SAnirudh Venkataramanan status = ice_aq_get_rss_key(hw, vsi->idx, buf); 3507d76a60baSAnirudh Venkataramanan if (status) { 3508d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3509d76a60baSAnirudh Venkataramanan "Cannot get RSS key, err %d aq_err %d\n", 3510d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3511d76a60baSAnirudh Venkataramanan return -EIO; 3512d76a60baSAnirudh Venkataramanan } 3513d76a60baSAnirudh Venkataramanan } 3514d76a60baSAnirudh Venkataramanan 3515d76a60baSAnirudh Venkataramanan if (lut) { 35164fb33f31SAnirudh Venkataramanan status = ice_aq_get_rss_lut(hw, vsi->idx, vsi->rss_lut_type, 35174fb33f31SAnirudh Venkataramanan lut, lut_size); 3518d76a60baSAnirudh Venkataramanan if (status) { 3519d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3520d76a60baSAnirudh Venkataramanan "Cannot get RSS lut, err %d aq_err %d\n", 3521d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3522d76a60baSAnirudh Venkataramanan return -EIO; 3523d76a60baSAnirudh Venkataramanan } 3524d76a60baSAnirudh Venkataramanan } 3525d76a60baSAnirudh Venkataramanan 3526d76a60baSAnirudh Venkataramanan return 0; 3527d76a60baSAnirudh Venkataramanan } 3528d76a60baSAnirudh Venkataramanan 3529d76a60baSAnirudh Venkataramanan /** 3530b1edc14aSMd Fahad Iqbal Polash * ice_bridge_getlink - Get the hardware bridge mode 3531b1edc14aSMd Fahad Iqbal Polash * @skb: skb buff 3532b1edc14aSMd Fahad Iqbal Polash * @pid: process id 3533b1edc14aSMd Fahad Iqbal Polash * @seq: RTNL message seq 3534b1edc14aSMd Fahad Iqbal Polash * @dev: the netdev being configured 3535b1edc14aSMd Fahad Iqbal Polash * @filter_mask: filter mask passed in 3536b1edc14aSMd Fahad Iqbal Polash * @nlflags: netlink flags passed in 3537b1edc14aSMd Fahad Iqbal Polash * 3538b1edc14aSMd Fahad Iqbal Polash * Return the bridge mode (VEB/VEPA) 3539b1edc14aSMd Fahad Iqbal Polash */ 3540b1edc14aSMd Fahad Iqbal Polash static int 3541b1edc14aSMd Fahad Iqbal Polash ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 3542b1edc14aSMd Fahad Iqbal Polash struct net_device *dev, u32 filter_mask, int nlflags) 3543b1edc14aSMd Fahad Iqbal Polash { 3544b1edc14aSMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(dev); 3545b1edc14aSMd Fahad Iqbal Polash struct ice_vsi *vsi = np->vsi; 3546b1edc14aSMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 3547b1edc14aSMd Fahad Iqbal Polash u16 bmode; 3548b1edc14aSMd Fahad Iqbal Polash 3549b1edc14aSMd Fahad Iqbal Polash bmode = pf->first_sw->bridge_mode; 3550b1edc14aSMd Fahad Iqbal Polash 3551b1edc14aSMd Fahad Iqbal Polash return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags, 3552b1edc14aSMd Fahad Iqbal Polash filter_mask, NULL); 3553b1edc14aSMd Fahad Iqbal Polash } 3554b1edc14aSMd Fahad Iqbal Polash 3555b1edc14aSMd Fahad Iqbal Polash /** 3556b1edc14aSMd Fahad Iqbal Polash * ice_vsi_update_bridge_mode - Update VSI for switching bridge mode (VEB/VEPA) 3557b1edc14aSMd Fahad Iqbal Polash * @vsi: Pointer to VSI structure 3558b1edc14aSMd Fahad Iqbal Polash * @bmode: Hardware bridge mode (VEB/VEPA) 3559b1edc14aSMd Fahad Iqbal Polash * 3560b1edc14aSMd Fahad Iqbal Polash * Returns 0 on success, negative on failure 3561b1edc14aSMd Fahad Iqbal Polash */ 3562b1edc14aSMd Fahad Iqbal Polash static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode) 3563b1edc14aSMd Fahad Iqbal Polash { 3564b1edc14aSMd Fahad Iqbal Polash struct device *dev = &vsi->back->pdev->dev; 3565b1edc14aSMd Fahad Iqbal Polash struct ice_aqc_vsi_props *vsi_props; 3566b1edc14aSMd Fahad Iqbal Polash struct ice_hw *hw = &vsi->back->hw; 3567b1edc14aSMd Fahad Iqbal Polash struct ice_vsi_ctx ctxt = { 0 }; 3568b1edc14aSMd Fahad Iqbal Polash enum ice_status status; 3569b1edc14aSMd Fahad Iqbal Polash 3570b1edc14aSMd Fahad Iqbal Polash vsi_props = &vsi->info; 3571b1edc14aSMd Fahad Iqbal Polash ctxt.info = vsi->info; 3572b1edc14aSMd Fahad Iqbal Polash 3573b1edc14aSMd Fahad Iqbal Polash if (bmode == BRIDGE_MODE_VEB) 3574b1edc14aSMd Fahad Iqbal Polash /* change from VEPA to VEB mode */ 3575b1edc14aSMd Fahad Iqbal Polash ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 3576b1edc14aSMd Fahad Iqbal Polash else 3577b1edc14aSMd Fahad Iqbal Polash /* change from VEB to VEPA mode */ 3578b1edc14aSMd Fahad Iqbal Polash ctxt.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 3579b1edc14aSMd Fahad Iqbal Polash ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); 35805726ca0eSAnirudh Venkataramanan 35815726ca0eSAnirudh Venkataramanan status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL); 3582b1edc14aSMd Fahad Iqbal Polash if (status) { 3583b1edc14aSMd Fahad Iqbal Polash dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n", 3584b1edc14aSMd Fahad Iqbal Polash bmode, status, hw->adminq.sq_last_status); 3585b1edc14aSMd Fahad Iqbal Polash return -EIO; 3586b1edc14aSMd Fahad Iqbal Polash } 3587b1edc14aSMd Fahad Iqbal Polash /* Update sw flags for book keeping */ 3588b1edc14aSMd Fahad Iqbal Polash vsi_props->sw_flags = ctxt.info.sw_flags; 3589b1edc14aSMd Fahad Iqbal Polash 3590b1edc14aSMd Fahad Iqbal Polash return 0; 3591b1edc14aSMd Fahad Iqbal Polash } 3592b1edc14aSMd Fahad Iqbal Polash 3593b1edc14aSMd Fahad Iqbal Polash /** 3594b1edc14aSMd Fahad Iqbal Polash * ice_bridge_setlink - Set the hardware bridge mode 3595b1edc14aSMd Fahad Iqbal Polash * @dev: the netdev being configured 3596b1edc14aSMd Fahad Iqbal Polash * @nlh: RTNL message 3597b1edc14aSMd Fahad Iqbal Polash * @flags: bridge setlink flags 3598b1edc14aSMd Fahad Iqbal Polash * 3599b1edc14aSMd Fahad Iqbal Polash * Sets the bridge mode (VEB/VEPA) of the switch to which the netdev (VSI) is 3600b1edc14aSMd Fahad Iqbal Polash * hooked up to. Iterates through the PF VSI list and sets the loopback mode (if 3601b1edc14aSMd Fahad Iqbal Polash * not already set for all VSIs connected to this switch. And also update the 3602b1edc14aSMd Fahad Iqbal Polash * unicast switch filter rules for the corresponding switch of the netdev. 3603b1edc14aSMd Fahad Iqbal Polash */ 3604b1edc14aSMd Fahad Iqbal Polash static int 3605b1edc14aSMd Fahad Iqbal Polash ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, 3606b1edc14aSMd Fahad Iqbal Polash u16 __always_unused flags) 3607b1edc14aSMd Fahad Iqbal Polash { 3608b1edc14aSMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(dev); 3609b1edc14aSMd Fahad Iqbal Polash struct ice_pf *pf = np->vsi->back; 3610b1edc14aSMd Fahad Iqbal Polash struct nlattr *attr, *br_spec; 3611b1edc14aSMd Fahad Iqbal Polash struct ice_hw *hw = &pf->hw; 3612b1edc14aSMd Fahad Iqbal Polash enum ice_status status; 3613b1edc14aSMd Fahad Iqbal Polash struct ice_sw *pf_sw; 3614b1edc14aSMd Fahad Iqbal Polash int rem, v, err = 0; 3615b1edc14aSMd Fahad Iqbal Polash 3616b1edc14aSMd Fahad Iqbal Polash pf_sw = pf->first_sw; 3617b1edc14aSMd Fahad Iqbal Polash /* find the attribute in the netlink message */ 3618b1edc14aSMd Fahad Iqbal Polash br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); 3619b1edc14aSMd Fahad Iqbal Polash 3620b1edc14aSMd Fahad Iqbal Polash nla_for_each_nested(attr, br_spec, rem) { 3621b1edc14aSMd Fahad Iqbal Polash __u16 mode; 3622b1edc14aSMd Fahad Iqbal Polash 3623b1edc14aSMd Fahad Iqbal Polash if (nla_type(attr) != IFLA_BRIDGE_MODE) 3624b1edc14aSMd Fahad Iqbal Polash continue; 3625b1edc14aSMd Fahad Iqbal Polash mode = nla_get_u16(attr); 3626b1edc14aSMd Fahad Iqbal Polash if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) 3627b1edc14aSMd Fahad Iqbal Polash return -EINVAL; 3628b1edc14aSMd Fahad Iqbal Polash /* Continue if bridge mode is not being flipped */ 3629b1edc14aSMd Fahad Iqbal Polash if (mode == pf_sw->bridge_mode) 3630b1edc14aSMd Fahad Iqbal Polash continue; 3631b1edc14aSMd Fahad Iqbal Polash /* Iterates through the PF VSI list and update the loopback 3632b1edc14aSMd Fahad Iqbal Polash * mode of the VSI 3633b1edc14aSMd Fahad Iqbal Polash */ 3634b1edc14aSMd Fahad Iqbal Polash ice_for_each_vsi(pf, v) { 3635b1edc14aSMd Fahad Iqbal Polash if (!pf->vsi[v]) 3636b1edc14aSMd Fahad Iqbal Polash continue; 3637b1edc14aSMd Fahad Iqbal Polash err = ice_vsi_update_bridge_mode(pf->vsi[v], mode); 3638b1edc14aSMd Fahad Iqbal Polash if (err) 3639b1edc14aSMd Fahad Iqbal Polash return err; 3640b1edc14aSMd Fahad Iqbal Polash } 3641b1edc14aSMd Fahad Iqbal Polash 3642b1edc14aSMd Fahad Iqbal Polash hw->evb_veb = (mode == BRIDGE_MODE_VEB); 3643b1edc14aSMd Fahad Iqbal Polash /* Update the unicast switch filter rules for the corresponding 3644b1edc14aSMd Fahad Iqbal Polash * switch of the netdev 3645b1edc14aSMd Fahad Iqbal Polash */ 3646b1edc14aSMd Fahad Iqbal Polash status = ice_update_sw_rule_bridge_mode(hw); 3647b1edc14aSMd Fahad Iqbal Polash if (status) { 3648b1edc14aSMd Fahad Iqbal Polash netdev_err(dev, "update SW_RULE for bridge mode failed, = %d err %d aq_err %d\n", 3649b1edc14aSMd Fahad Iqbal Polash mode, status, hw->adminq.sq_last_status); 3650b1edc14aSMd Fahad Iqbal Polash /* revert hw->evb_veb */ 3651b1edc14aSMd Fahad Iqbal Polash hw->evb_veb = (pf_sw->bridge_mode == BRIDGE_MODE_VEB); 3652b1edc14aSMd Fahad Iqbal Polash return -EIO; 3653b1edc14aSMd Fahad Iqbal Polash } 3654b1edc14aSMd Fahad Iqbal Polash 3655b1edc14aSMd Fahad Iqbal Polash pf_sw->bridge_mode = mode; 3656b1edc14aSMd Fahad Iqbal Polash } 3657b1edc14aSMd Fahad Iqbal Polash 3658b1edc14aSMd Fahad Iqbal Polash return 0; 3659b1edc14aSMd Fahad Iqbal Polash } 3660b1edc14aSMd Fahad Iqbal Polash 3661b1edc14aSMd Fahad Iqbal Polash /** 3662b3969fd7SSudheer Mogilappagari * ice_tx_timeout - Respond to a Tx Hang 3663b3969fd7SSudheer Mogilappagari * @netdev: network interface device structure 3664b3969fd7SSudheer Mogilappagari */ 3665b3969fd7SSudheer Mogilappagari static void ice_tx_timeout(struct net_device *netdev) 3666b3969fd7SSudheer Mogilappagari { 3667b3969fd7SSudheer Mogilappagari struct ice_netdev_priv *np = netdev_priv(netdev); 3668b3969fd7SSudheer Mogilappagari struct ice_ring *tx_ring = NULL; 3669b3969fd7SSudheer Mogilappagari struct ice_vsi *vsi = np->vsi; 3670b3969fd7SSudheer Mogilappagari struct ice_pf *pf = vsi->back; 3671b3969fd7SSudheer Mogilappagari u32 head, val = 0, i; 3672b3969fd7SSudheer Mogilappagari int hung_queue = -1; 3673b3969fd7SSudheer Mogilappagari 3674b3969fd7SSudheer Mogilappagari pf->tx_timeout_count++; 3675b3969fd7SSudheer Mogilappagari 3676b3969fd7SSudheer Mogilappagari /* find the stopped queue the same way the stack does */ 3677b3969fd7SSudheer Mogilappagari for (i = 0; i < netdev->num_tx_queues; i++) { 3678b3969fd7SSudheer Mogilappagari struct netdev_queue *q; 3679b3969fd7SSudheer Mogilappagari unsigned long trans_start; 3680b3969fd7SSudheer Mogilappagari 3681b3969fd7SSudheer Mogilappagari q = netdev_get_tx_queue(netdev, i); 3682b3969fd7SSudheer Mogilappagari trans_start = q->trans_start; 3683b3969fd7SSudheer Mogilappagari if (netif_xmit_stopped(q) && 3684b3969fd7SSudheer Mogilappagari time_after(jiffies, 3685b3969fd7SSudheer Mogilappagari (trans_start + netdev->watchdog_timeo))) { 3686b3969fd7SSudheer Mogilappagari hung_queue = i; 3687b3969fd7SSudheer Mogilappagari break; 3688b3969fd7SSudheer Mogilappagari } 3689b3969fd7SSudheer Mogilappagari } 3690b3969fd7SSudheer Mogilappagari 3691b3969fd7SSudheer Mogilappagari if (i == netdev->num_tx_queues) { 3692b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout: no netdev hung queue found\n"); 3693b3969fd7SSudheer Mogilappagari } else { 3694b3969fd7SSudheer Mogilappagari /* now that we have an index, find the tx_ring struct */ 3695b3969fd7SSudheer Mogilappagari for (i = 0; i < vsi->num_txq; i++) { 3696b3969fd7SSudheer Mogilappagari if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) { 3697b3969fd7SSudheer Mogilappagari if (hung_queue == 3698b3969fd7SSudheer Mogilappagari vsi->tx_rings[i]->q_index) { 3699b3969fd7SSudheer Mogilappagari tx_ring = vsi->tx_rings[i]; 3700b3969fd7SSudheer Mogilappagari break; 3701b3969fd7SSudheer Mogilappagari } 3702b3969fd7SSudheer Mogilappagari } 3703b3969fd7SSudheer Mogilappagari } 3704b3969fd7SSudheer Mogilappagari } 3705b3969fd7SSudheer Mogilappagari 3706b3969fd7SSudheer Mogilappagari /* Reset recovery level if enough time has elapsed after last timeout. 3707b3969fd7SSudheer Mogilappagari * Also ensure no new reset action happens before next timeout period. 3708b3969fd7SSudheer Mogilappagari */ 3709b3969fd7SSudheer Mogilappagari if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ * 20))) 3710b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level = 1; 3711b3969fd7SSudheer Mogilappagari else if (time_before(jiffies, (pf->tx_timeout_last_recovery + 3712b3969fd7SSudheer Mogilappagari netdev->watchdog_timeo))) 3713b3969fd7SSudheer Mogilappagari return; 3714b3969fd7SSudheer Mogilappagari 3715b3969fd7SSudheer Mogilappagari if (tx_ring) { 3716b3969fd7SSudheer Mogilappagari head = tx_ring->next_to_clean; 3717b3969fd7SSudheer Mogilappagari /* Read interrupt register */ 3718b3969fd7SSudheer Mogilappagari if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 3719b3969fd7SSudheer Mogilappagari val = rd32(&pf->hw, 3720b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL(tx_ring->q_vector->v_idx + 3721eb0208ecSPreethi Banala tx_ring->vsi->hw_base_vector)); 3722b3969fd7SSudheer Mogilappagari 3723b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n", 3724b3969fd7SSudheer Mogilappagari vsi->vsi_num, hung_queue, tx_ring->next_to_clean, 3725b3969fd7SSudheer Mogilappagari head, tx_ring->next_to_use, 3726b3969fd7SSudheer Mogilappagari readl(tx_ring->tail), val); 3727b3969fd7SSudheer Mogilappagari } 3728b3969fd7SSudheer Mogilappagari 3729b3969fd7SSudheer Mogilappagari pf->tx_timeout_last_recovery = jiffies; 3730b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n", 3731b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level, hung_queue); 3732b3969fd7SSudheer Mogilappagari 3733b3969fd7SSudheer Mogilappagari switch (pf->tx_timeout_recovery_level) { 3734b3969fd7SSudheer Mogilappagari case 1: 3735b3969fd7SSudheer Mogilappagari set_bit(__ICE_PFR_REQ, pf->state); 3736b3969fd7SSudheer Mogilappagari break; 3737b3969fd7SSudheer Mogilappagari case 2: 3738b3969fd7SSudheer Mogilappagari set_bit(__ICE_CORER_REQ, pf->state); 3739b3969fd7SSudheer Mogilappagari break; 3740b3969fd7SSudheer Mogilappagari case 3: 3741b3969fd7SSudheer Mogilappagari set_bit(__ICE_GLOBR_REQ, pf->state); 3742b3969fd7SSudheer Mogilappagari break; 3743b3969fd7SSudheer Mogilappagari default: 3744b3969fd7SSudheer Mogilappagari netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in unrecoverable state.\n"); 3745b3969fd7SSudheer Mogilappagari set_bit(__ICE_DOWN, pf->state); 3746b3969fd7SSudheer Mogilappagari set_bit(__ICE_NEEDS_RESTART, vsi->state); 37478d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 3748b3969fd7SSudheer Mogilappagari break; 3749b3969fd7SSudheer Mogilappagari } 3750b3969fd7SSudheer Mogilappagari 3751b3969fd7SSudheer Mogilappagari ice_service_task_schedule(pf); 3752b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level++; 3753b3969fd7SSudheer Mogilappagari } 3754b3969fd7SSudheer Mogilappagari 3755b3969fd7SSudheer Mogilappagari /** 3756cdedef59SAnirudh Venkataramanan * ice_open - Called when a network interface becomes active 3757cdedef59SAnirudh Venkataramanan * @netdev: network interface device structure 3758cdedef59SAnirudh Venkataramanan * 3759cdedef59SAnirudh Venkataramanan * The open entry point is called when a network interface is made 3760cdedef59SAnirudh Venkataramanan * active by the system (IFF_UP). At this point all resources needed 3761cdedef59SAnirudh Venkataramanan * for transmit and receive operations are allocated, the interrupt 3762cdedef59SAnirudh Venkataramanan * handler is registered with the OS, the netdev watchdog is enabled, 3763cdedef59SAnirudh Venkataramanan * and the stack is notified that the interface is ready. 3764cdedef59SAnirudh Venkataramanan * 3765cdedef59SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 3766cdedef59SAnirudh Venkataramanan */ 3767cdedef59SAnirudh Venkataramanan static int ice_open(struct net_device *netdev) 3768cdedef59SAnirudh Venkataramanan { 3769cdedef59SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3770cdedef59SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3771cdedef59SAnirudh Venkataramanan int err; 3772cdedef59SAnirudh Venkataramanan 37730f9d5027SAnirudh Venkataramanan if (test_bit(__ICE_NEEDS_RESTART, vsi->back->state)) { 37740f9d5027SAnirudh Venkataramanan netdev_err(netdev, "driver needs to be unloaded and reloaded\n"); 37750f9d5027SAnirudh Venkataramanan return -EIO; 37760f9d5027SAnirudh Venkataramanan } 37770f9d5027SAnirudh Venkataramanan 3778cdedef59SAnirudh Venkataramanan netif_carrier_off(netdev); 3779cdedef59SAnirudh Venkataramanan 3780cdedef59SAnirudh Venkataramanan err = ice_vsi_open(vsi); 3781cdedef59SAnirudh Venkataramanan 3782cdedef59SAnirudh Venkataramanan if (err) 3783cdedef59SAnirudh Venkataramanan netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n", 3784cdedef59SAnirudh Venkataramanan vsi->vsi_num, vsi->vsw->sw_id); 3785cdedef59SAnirudh Venkataramanan return err; 3786cdedef59SAnirudh Venkataramanan } 3787cdedef59SAnirudh Venkataramanan 3788cdedef59SAnirudh Venkataramanan /** 3789cdedef59SAnirudh Venkataramanan * ice_stop - Disables a network interface 3790cdedef59SAnirudh Venkataramanan * @netdev: network interface device structure 3791cdedef59SAnirudh Venkataramanan * 3792cdedef59SAnirudh Venkataramanan * The stop entry point is called when an interface is de-activated by the OS, 3793cdedef59SAnirudh Venkataramanan * and the netdevice enters the DOWN state. The hardware is still under the 3794cdedef59SAnirudh Venkataramanan * driver's control, but the netdev interface is disabled. 3795cdedef59SAnirudh Venkataramanan * 3796cdedef59SAnirudh Venkataramanan * Returns success only - not allowed to fail 3797cdedef59SAnirudh Venkataramanan */ 3798cdedef59SAnirudh Venkataramanan static int ice_stop(struct net_device *netdev) 3799cdedef59SAnirudh Venkataramanan { 3800cdedef59SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3801cdedef59SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3802cdedef59SAnirudh Venkataramanan 3803cdedef59SAnirudh Venkataramanan ice_vsi_close(vsi); 3804cdedef59SAnirudh Venkataramanan 3805cdedef59SAnirudh Venkataramanan return 0; 3806cdedef59SAnirudh Venkataramanan } 3807cdedef59SAnirudh Venkataramanan 3808e94d4478SAnirudh Venkataramanan /** 3809e94d4478SAnirudh Venkataramanan * ice_features_check - Validate encapsulated packet conforms to limits 3810e94d4478SAnirudh Venkataramanan * @skb: skb buffer 3811e94d4478SAnirudh Venkataramanan * @netdev: This port's netdev 3812e94d4478SAnirudh Venkataramanan * @features: Offload features that the stack believes apply 3813e94d4478SAnirudh Venkataramanan */ 3814e94d4478SAnirudh Venkataramanan static netdev_features_t 3815e94d4478SAnirudh Venkataramanan ice_features_check(struct sk_buff *skb, 3816e94d4478SAnirudh Venkataramanan struct net_device __always_unused *netdev, 3817e94d4478SAnirudh Venkataramanan netdev_features_t features) 3818e94d4478SAnirudh Venkataramanan { 3819e94d4478SAnirudh Venkataramanan size_t len; 3820e94d4478SAnirudh Venkataramanan 3821e94d4478SAnirudh Venkataramanan /* No point in doing any of this if neither checksum nor GSO are 3822e94d4478SAnirudh Venkataramanan * being requested for this frame. We can rule out both by just 3823e94d4478SAnirudh Venkataramanan * checking for CHECKSUM_PARTIAL 3824e94d4478SAnirudh Venkataramanan */ 3825e94d4478SAnirudh Venkataramanan if (skb->ip_summed != CHECKSUM_PARTIAL) 3826e94d4478SAnirudh Venkataramanan return features; 3827e94d4478SAnirudh Venkataramanan 3828e94d4478SAnirudh Venkataramanan /* We cannot support GSO if the MSS is going to be less than 3829e94d4478SAnirudh Venkataramanan * 64 bytes. If it is then we need to drop support for GSO. 3830e94d4478SAnirudh Venkataramanan */ 3831e94d4478SAnirudh Venkataramanan if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) 3832e94d4478SAnirudh Venkataramanan features &= ~NETIF_F_GSO_MASK; 3833e94d4478SAnirudh Venkataramanan 3834e94d4478SAnirudh Venkataramanan len = skb_network_header(skb) - skb->data; 3835e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_MACLEN_MAX)) 3836e94d4478SAnirudh Venkataramanan goto out_rm_features; 3837e94d4478SAnirudh Venkataramanan 3838e94d4478SAnirudh Venkataramanan len = skb_transport_header(skb) - skb_network_header(skb); 3839e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_IPLEN_MAX)) 3840e94d4478SAnirudh Venkataramanan goto out_rm_features; 3841e94d4478SAnirudh Venkataramanan 3842e94d4478SAnirudh Venkataramanan if (skb->encapsulation) { 3843e94d4478SAnirudh Venkataramanan len = skb_inner_network_header(skb) - skb_transport_header(skb); 3844e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_L4LEN_MAX)) 3845e94d4478SAnirudh Venkataramanan goto out_rm_features; 3846e94d4478SAnirudh Venkataramanan 3847e94d4478SAnirudh Venkataramanan len = skb_inner_transport_header(skb) - 3848e94d4478SAnirudh Venkataramanan skb_inner_network_header(skb); 3849e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_IPLEN_MAX)) 3850e94d4478SAnirudh Venkataramanan goto out_rm_features; 3851e94d4478SAnirudh Venkataramanan } 3852e94d4478SAnirudh Venkataramanan 3853e94d4478SAnirudh Venkataramanan return features; 3854e94d4478SAnirudh Venkataramanan out_rm_features: 3855e94d4478SAnirudh Venkataramanan return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); 3856e94d4478SAnirudh Venkataramanan } 3857e94d4478SAnirudh Venkataramanan 3858cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops = { 3859cdedef59SAnirudh Venkataramanan .ndo_open = ice_open, 3860cdedef59SAnirudh Venkataramanan .ndo_stop = ice_stop, 38612b245cb2SAnirudh Venkataramanan .ndo_start_xmit = ice_start_xmit, 3862e94d4478SAnirudh Venkataramanan .ndo_features_check = ice_features_check, 3863e94d4478SAnirudh Venkataramanan .ndo_set_rx_mode = ice_set_rx_mode, 3864e94d4478SAnirudh Venkataramanan .ndo_set_mac_address = ice_set_mac_address, 3865e94d4478SAnirudh Venkataramanan .ndo_validate_addr = eth_validate_addr, 3866e94d4478SAnirudh Venkataramanan .ndo_change_mtu = ice_change_mtu, 3867fcea6f3dSAnirudh Venkataramanan .ndo_get_stats64 = ice_get_stats64, 3868d76a60baSAnirudh Venkataramanan .ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid, 3869d76a60baSAnirudh Venkataramanan .ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid, 3870d76a60baSAnirudh Venkataramanan .ndo_set_features = ice_set_features, 3871b1edc14aSMd Fahad Iqbal Polash .ndo_bridge_getlink = ice_bridge_getlink, 3872b1edc14aSMd Fahad Iqbal Polash .ndo_bridge_setlink = ice_bridge_setlink, 3873e94d4478SAnirudh Venkataramanan .ndo_fdb_add = ice_fdb_add, 3874e94d4478SAnirudh Venkataramanan .ndo_fdb_del = ice_fdb_del, 3875b3969fd7SSudheer Mogilappagari .ndo_tx_timeout = ice_tx_timeout, 3876cdedef59SAnirudh Venkataramanan }; 3877