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" 1037b6f646SAnirudh Venkataramanan #include "ice_dcb_lib.h" 11837f08fdSAnirudh Venkataramanan 12802abbb4SAnirudh Venkataramanan #define DRV_VERSION "0.7.3-k" 13837f08fdSAnirudh Venkataramanan #define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver" 14fcea6f3dSAnirudh Venkataramanan const char ice_drv_ver[] = DRV_VERSION; 15837f08fdSAnirudh Venkataramanan static const char ice_driver_string[] = DRV_SUMMARY; 16837f08fdSAnirudh Venkataramanan static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation."; 17837f08fdSAnirudh Venkataramanan 18837f08fdSAnirudh Venkataramanan MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); 19837f08fdSAnirudh Venkataramanan MODULE_DESCRIPTION(DRV_SUMMARY); 2098674ebeSJesse Brandeburg MODULE_LICENSE("GPL v2"); 21837f08fdSAnirudh Venkataramanan MODULE_VERSION(DRV_VERSION); 22837f08fdSAnirudh Venkataramanan 23837f08fdSAnirudh Venkataramanan static int debug = -1; 24837f08fdSAnirudh Venkataramanan module_param(debug, int, 0644); 257ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 267ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXXXXX)"); 277ec59eeaSAnirudh Venkataramanan #else 287ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)"); 297ec59eeaSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 30837f08fdSAnirudh Venkataramanan 31940b61afSAnirudh Venkataramanan static struct workqueue_struct *ice_wq; 32cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops; 33940b61afSAnirudh Venkataramanan 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 /** 116f9867df6SAnirudh 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 118f9867df6SAnirudh 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 123f9867df6SAnirudh 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 /** 137f9867df6SAnirudh 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 139f9867df6SAnirudh 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 144f9867df6SAnirudh 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 /** 1715eda8afdSAkeem G Abodunrin * ice_cfg_promisc - Enable or disable promiscuous mode for a given PF 1725eda8afdSAkeem G Abodunrin * @vsi: the VSI being configured 1735eda8afdSAkeem G Abodunrin * @promisc_m: mask of promiscuous config bits 1745eda8afdSAkeem G Abodunrin * @set_promisc: enable or disable promisc flag request 1755eda8afdSAkeem G Abodunrin * 1765eda8afdSAkeem G Abodunrin */ 1775eda8afdSAkeem G Abodunrin static int ice_cfg_promisc(struct ice_vsi *vsi, u8 promisc_m, bool set_promisc) 1785eda8afdSAkeem G Abodunrin { 1795eda8afdSAkeem G Abodunrin struct ice_hw *hw = &vsi->back->hw; 1805eda8afdSAkeem G Abodunrin enum ice_status status = 0; 1815eda8afdSAkeem G Abodunrin 1825eda8afdSAkeem G Abodunrin if (vsi->type != ICE_VSI_PF) 1835eda8afdSAkeem G Abodunrin return 0; 1845eda8afdSAkeem G Abodunrin 1855eda8afdSAkeem G Abodunrin if (vsi->vlan_ena) { 1865eda8afdSAkeem G Abodunrin status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m, 1875eda8afdSAkeem G Abodunrin set_promisc); 1885eda8afdSAkeem G Abodunrin } else { 1895eda8afdSAkeem G Abodunrin if (set_promisc) 1905eda8afdSAkeem G Abodunrin status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m, 1915eda8afdSAkeem G Abodunrin 0); 1925eda8afdSAkeem G Abodunrin else 1935eda8afdSAkeem G Abodunrin status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m, 1945eda8afdSAkeem G Abodunrin 0); 1955eda8afdSAkeem G Abodunrin } 1965eda8afdSAkeem G Abodunrin 1975eda8afdSAkeem G Abodunrin if (status) 1985eda8afdSAkeem G Abodunrin return -EIO; 1995eda8afdSAkeem G Abodunrin 2005eda8afdSAkeem G Abodunrin return 0; 2015eda8afdSAkeem G Abodunrin } 2025eda8afdSAkeem G Abodunrin 2035eda8afdSAkeem G Abodunrin /** 204e94d4478SAnirudh Venkataramanan * ice_vsi_sync_fltr - Update the VSI filter list to the HW 205e94d4478SAnirudh Venkataramanan * @vsi: ptr to the VSI 206e94d4478SAnirudh Venkataramanan * 207e94d4478SAnirudh Venkataramanan * Push any outstanding VSI filter changes through the AdminQ. 208e94d4478SAnirudh Venkataramanan */ 209e94d4478SAnirudh Venkataramanan static int ice_vsi_sync_fltr(struct ice_vsi *vsi) 210e94d4478SAnirudh Venkataramanan { 211e94d4478SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 212e94d4478SAnirudh Venkataramanan struct net_device *netdev = vsi->netdev; 213e94d4478SAnirudh Venkataramanan bool promisc_forced_on = false; 214e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 215e94d4478SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 216e94d4478SAnirudh Venkataramanan enum ice_status status = 0; 217e94d4478SAnirudh Venkataramanan u32 changed_flags = 0; 2185eda8afdSAkeem G Abodunrin u8 promisc_m; 219e94d4478SAnirudh Venkataramanan int err = 0; 220e94d4478SAnirudh Venkataramanan 221e94d4478SAnirudh Venkataramanan if (!vsi->netdev) 222e94d4478SAnirudh Venkataramanan return -EINVAL; 223e94d4478SAnirudh Venkataramanan 224e94d4478SAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, vsi->state)) 225e94d4478SAnirudh Venkataramanan usleep_range(1000, 2000); 226e94d4478SAnirudh Venkataramanan 227e94d4478SAnirudh Venkataramanan changed_flags = vsi->current_netdev_flags ^ vsi->netdev->flags; 228e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags = vsi->netdev->flags; 229e94d4478SAnirudh Venkataramanan 230e94d4478SAnirudh Venkataramanan INIT_LIST_HEAD(&vsi->tmp_sync_list); 231e94d4478SAnirudh Venkataramanan INIT_LIST_HEAD(&vsi->tmp_unsync_list); 232e94d4478SAnirudh Venkataramanan 233e94d4478SAnirudh Venkataramanan if (ice_vsi_fltr_changed(vsi)) { 234e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 235e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 236e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 237e94d4478SAnirudh Venkataramanan 238e94d4478SAnirudh Venkataramanan /* grab the netdev's addr_list_lock */ 239e94d4478SAnirudh Venkataramanan netif_addr_lock_bh(netdev); 240e94d4478SAnirudh Venkataramanan __dev_uc_sync(netdev, ice_add_mac_to_sync_list, 241e94d4478SAnirudh Venkataramanan ice_add_mac_to_unsync_list); 242e94d4478SAnirudh Venkataramanan __dev_mc_sync(netdev, ice_add_mac_to_sync_list, 243e94d4478SAnirudh Venkataramanan ice_add_mac_to_unsync_list); 244e94d4478SAnirudh Venkataramanan /* our temp lists are populated. release lock */ 245e94d4478SAnirudh Venkataramanan netif_addr_unlock_bh(netdev); 246e94d4478SAnirudh Venkataramanan } 247e94d4478SAnirudh Venkataramanan 248f9867df6SAnirudh Venkataramanan /* Remove MAC addresses in the unsync list */ 249e94d4478SAnirudh Venkataramanan status = ice_remove_mac(hw, &vsi->tmp_unsync_list); 250e94d4478SAnirudh Venkataramanan ice_free_fltr_list(dev, &vsi->tmp_unsync_list); 251e94d4478SAnirudh Venkataramanan if (status) { 252e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Failed to delete MAC filters\n"); 253e94d4478SAnirudh Venkataramanan /* if we failed because of alloc failures, just bail */ 254e94d4478SAnirudh Venkataramanan if (status == ICE_ERR_NO_MEMORY) { 255e94d4478SAnirudh Venkataramanan err = -ENOMEM; 256e94d4478SAnirudh Venkataramanan goto out; 257e94d4478SAnirudh Venkataramanan } 258e94d4478SAnirudh Venkataramanan } 259e94d4478SAnirudh Venkataramanan 260f9867df6SAnirudh Venkataramanan /* Add MAC addresses in the sync list */ 261e94d4478SAnirudh Venkataramanan status = ice_add_mac(hw, &vsi->tmp_sync_list); 262e94d4478SAnirudh Venkataramanan ice_free_fltr_list(dev, &vsi->tmp_sync_list); 26389f3e4a5SPreethi Banala /* If filter is added successfully or already exists, do not go into 26489f3e4a5SPreethi Banala * 'if' condition and report it as error. Instead continue processing 26589f3e4a5SPreethi Banala * rest of the function. 26689f3e4a5SPreethi Banala */ 26789f3e4a5SPreethi Banala if (status && status != ICE_ERR_ALREADY_EXISTS) { 268e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Failed to add MAC filters\n"); 269f9867df6SAnirudh Venkataramanan /* If there is no more space for new umac filters, VSI 270e94d4478SAnirudh Venkataramanan * should go into promiscuous mode. There should be some 271e94d4478SAnirudh Venkataramanan * space reserved for promiscuous filters. 272e94d4478SAnirudh Venkataramanan */ 273e94d4478SAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOSPC && 274e94d4478SAnirudh Venkataramanan !test_and_set_bit(__ICE_FLTR_OVERFLOW_PROMISC, 275e94d4478SAnirudh Venkataramanan vsi->state)) { 276e94d4478SAnirudh Venkataramanan promisc_forced_on = true; 277e94d4478SAnirudh Venkataramanan netdev_warn(netdev, 278e94d4478SAnirudh Venkataramanan "Reached MAC filter limit, forcing promisc mode on VSI %d\n", 279e94d4478SAnirudh Venkataramanan vsi->vsi_num); 280e94d4478SAnirudh Venkataramanan } else { 281e94d4478SAnirudh Venkataramanan err = -EIO; 282e94d4478SAnirudh Venkataramanan goto out; 283e94d4478SAnirudh Venkataramanan } 284e94d4478SAnirudh Venkataramanan } 285e94d4478SAnirudh Venkataramanan /* check for changes in promiscuous modes */ 2865eda8afdSAkeem G Abodunrin if (changed_flags & IFF_ALLMULTI) { 2875eda8afdSAkeem G Abodunrin if (vsi->current_netdev_flags & IFF_ALLMULTI) { 2885eda8afdSAkeem G Abodunrin if (vsi->vlan_ena) 2895eda8afdSAkeem G Abodunrin promisc_m = ICE_MCAST_VLAN_PROMISC_BITS; 2905eda8afdSAkeem G Abodunrin else 2915eda8afdSAkeem G Abodunrin promisc_m = ICE_MCAST_PROMISC_BITS; 2925eda8afdSAkeem G Abodunrin 2935eda8afdSAkeem G Abodunrin err = ice_cfg_promisc(vsi, promisc_m, true); 2945eda8afdSAkeem G Abodunrin if (err) { 2955eda8afdSAkeem G Abodunrin netdev_err(netdev, "Error setting Multicast promiscuous mode on VSI %i\n", 2965eda8afdSAkeem G Abodunrin vsi->vsi_num); 2975eda8afdSAkeem G Abodunrin vsi->current_netdev_flags &= ~IFF_ALLMULTI; 2985eda8afdSAkeem G Abodunrin goto out_promisc; 2995eda8afdSAkeem G Abodunrin } 3005eda8afdSAkeem G Abodunrin } else if (!(vsi->current_netdev_flags & IFF_ALLMULTI)) { 3015eda8afdSAkeem G Abodunrin if (vsi->vlan_ena) 3025eda8afdSAkeem G Abodunrin promisc_m = ICE_MCAST_VLAN_PROMISC_BITS; 3035eda8afdSAkeem G Abodunrin else 3045eda8afdSAkeem G Abodunrin promisc_m = ICE_MCAST_PROMISC_BITS; 3055eda8afdSAkeem G Abodunrin 3065eda8afdSAkeem G Abodunrin err = ice_cfg_promisc(vsi, promisc_m, false); 3075eda8afdSAkeem G Abodunrin if (err) { 3085eda8afdSAkeem G Abodunrin netdev_err(netdev, "Error clearing Multicast promiscuous mode on VSI %i\n", 3095eda8afdSAkeem G Abodunrin vsi->vsi_num); 3105eda8afdSAkeem G Abodunrin vsi->current_netdev_flags |= IFF_ALLMULTI; 3115eda8afdSAkeem G Abodunrin goto out_promisc; 3125eda8afdSAkeem G Abodunrin } 3135eda8afdSAkeem G Abodunrin } 3145eda8afdSAkeem G Abodunrin } 315e94d4478SAnirudh Venkataramanan 316e94d4478SAnirudh Venkataramanan if (((changed_flags & IFF_PROMISC) || promisc_forced_on) || 317e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) { 318e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags); 319e94d4478SAnirudh Venkataramanan if (vsi->current_netdev_flags & IFF_PROMISC) { 320f9867df6SAnirudh Venkataramanan /* Apply Tx filter rule to get traffic from VMs */ 3214fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, true, 322e94d4478SAnirudh Venkataramanan ICE_FLTR_TX); 323e94d4478SAnirudh Venkataramanan if (status) { 324e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error setting default VSI %i tx rule\n", 325e94d4478SAnirudh Venkataramanan vsi->vsi_num); 326e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags &= ~IFF_PROMISC; 327e94d4478SAnirudh Venkataramanan err = -EIO; 328e94d4478SAnirudh Venkataramanan goto out_promisc; 329e94d4478SAnirudh Venkataramanan } 330f9867df6SAnirudh Venkataramanan /* Apply Rx filter rule to get traffic from wire */ 3314fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, true, 332e94d4478SAnirudh Venkataramanan ICE_FLTR_RX); 333e94d4478SAnirudh Venkataramanan if (status) { 334e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error setting default VSI %i rx rule\n", 335e94d4478SAnirudh Venkataramanan vsi->vsi_num); 336e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags &= ~IFF_PROMISC; 337e94d4478SAnirudh Venkataramanan err = -EIO; 338e94d4478SAnirudh Venkataramanan goto out_promisc; 339e94d4478SAnirudh Venkataramanan } 340e94d4478SAnirudh Venkataramanan } else { 341f9867df6SAnirudh Venkataramanan /* Clear Tx filter rule to stop traffic from VMs */ 3424fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, false, 343e94d4478SAnirudh Venkataramanan ICE_FLTR_TX); 344e94d4478SAnirudh Venkataramanan if (status) { 345e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error clearing default VSI %i tx rule\n", 346e94d4478SAnirudh Venkataramanan vsi->vsi_num); 347e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags |= IFF_PROMISC; 348e94d4478SAnirudh Venkataramanan err = -EIO; 349e94d4478SAnirudh Venkataramanan goto out_promisc; 350e94d4478SAnirudh Venkataramanan } 351f9867df6SAnirudh Venkataramanan /* Clear Rx filter to remove traffic from wire */ 3524fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, false, 353e94d4478SAnirudh Venkataramanan ICE_FLTR_RX); 354e94d4478SAnirudh Venkataramanan if (status) { 355e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error clearing default VSI %i rx rule\n", 356e94d4478SAnirudh Venkataramanan vsi->vsi_num); 357e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags |= IFF_PROMISC; 358e94d4478SAnirudh Venkataramanan err = -EIO; 359e94d4478SAnirudh Venkataramanan goto out_promisc; 360e94d4478SAnirudh Venkataramanan } 361e94d4478SAnirudh Venkataramanan } 362e94d4478SAnirudh Venkataramanan } 363e94d4478SAnirudh Venkataramanan goto exit; 364e94d4478SAnirudh Venkataramanan 365e94d4478SAnirudh Venkataramanan out_promisc: 366e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags); 367e94d4478SAnirudh Venkataramanan goto exit; 368e94d4478SAnirudh Venkataramanan out: 369e94d4478SAnirudh Venkataramanan /* if something went wrong then set the changed flag so we try again */ 370e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 371e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 372e94d4478SAnirudh Venkataramanan exit: 373e94d4478SAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, vsi->state); 374e94d4478SAnirudh Venkataramanan return err; 375e94d4478SAnirudh Venkataramanan } 376e94d4478SAnirudh Venkataramanan 377e94d4478SAnirudh Venkataramanan /** 378e94d4478SAnirudh Venkataramanan * ice_sync_fltr_subtask - Sync the VSI filter list with HW 379e94d4478SAnirudh Venkataramanan * @pf: board private structure 380e94d4478SAnirudh Venkataramanan */ 381e94d4478SAnirudh Venkataramanan static void ice_sync_fltr_subtask(struct ice_pf *pf) 382e94d4478SAnirudh Venkataramanan { 383e94d4478SAnirudh Venkataramanan int v; 384e94d4478SAnirudh Venkataramanan 385e94d4478SAnirudh Venkataramanan if (!pf || !(test_bit(ICE_FLAG_FLTR_SYNC, pf->flags))) 386e94d4478SAnirudh Venkataramanan return; 387e94d4478SAnirudh Venkataramanan 388e94d4478SAnirudh Venkataramanan clear_bit(ICE_FLAG_FLTR_SYNC, pf->flags); 389e94d4478SAnirudh Venkataramanan 39080ed404aSBrett Creeley ice_for_each_vsi(pf, v) 391e94d4478SAnirudh Venkataramanan if (pf->vsi[v] && ice_vsi_fltr_changed(pf->vsi[v]) && 392e94d4478SAnirudh Venkataramanan ice_vsi_sync_fltr(pf->vsi[v])) { 393e94d4478SAnirudh Venkataramanan /* come back and try again later */ 394e94d4478SAnirudh Venkataramanan set_bit(ICE_FLAG_FLTR_SYNC, pf->flags); 395e94d4478SAnirudh Venkataramanan break; 396e94d4478SAnirudh Venkataramanan } 397e94d4478SAnirudh Venkataramanan } 398e94d4478SAnirudh Venkataramanan 399e94d4478SAnirudh Venkataramanan /** 4007b9ffc76SAnirudh Venkataramanan * ice_dis_vsi - pause a VSI 4017b9ffc76SAnirudh Venkataramanan * @vsi: the VSI being paused 4027b9ffc76SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 4037b9ffc76SAnirudh Venkataramanan */ 4047b9ffc76SAnirudh Venkataramanan static void ice_dis_vsi(struct ice_vsi *vsi, bool locked) 4057b9ffc76SAnirudh Venkataramanan { 4067b9ffc76SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state)) 4077b9ffc76SAnirudh Venkataramanan return; 4087b9ffc76SAnirudh Venkataramanan 4097b9ffc76SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, vsi->state); 4107b9ffc76SAnirudh Venkataramanan 4117b9ffc76SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF && vsi->netdev) { 4127b9ffc76SAnirudh Venkataramanan if (netif_running(vsi->netdev)) { 4137b9ffc76SAnirudh Venkataramanan if (!locked) { 4147b9ffc76SAnirudh Venkataramanan rtnl_lock(); 4157b9ffc76SAnirudh Venkataramanan vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); 4167b9ffc76SAnirudh Venkataramanan rtnl_unlock(); 4177b9ffc76SAnirudh Venkataramanan } else { 4187b9ffc76SAnirudh Venkataramanan vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); 4197b9ffc76SAnirudh Venkataramanan } 4207b9ffc76SAnirudh Venkataramanan } else { 4217b9ffc76SAnirudh Venkataramanan ice_vsi_close(vsi); 4227b9ffc76SAnirudh Venkataramanan } 4237b9ffc76SAnirudh Venkataramanan } 4247b9ffc76SAnirudh Venkataramanan } 4257b9ffc76SAnirudh Venkataramanan 4267b9ffc76SAnirudh Venkataramanan /** 4277b9ffc76SAnirudh Venkataramanan * ice_pf_dis_all_vsi - Pause all VSIs on a PF 4287b9ffc76SAnirudh Venkataramanan * @pf: the PF 4297b9ffc76SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 4307b9ffc76SAnirudh Venkataramanan */ 4317b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 4327b9ffc76SAnirudh Venkataramanan void ice_pf_dis_all_vsi(struct ice_pf *pf, bool locked) 4337b9ffc76SAnirudh Venkataramanan #else 4347b9ffc76SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf, bool locked) 4357b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 4367b9ffc76SAnirudh Venkataramanan { 4377b9ffc76SAnirudh Venkataramanan int v; 4387b9ffc76SAnirudh Venkataramanan 4397b9ffc76SAnirudh Venkataramanan ice_for_each_vsi(pf, v) 4407b9ffc76SAnirudh Venkataramanan if (pf->vsi[v]) 4417b9ffc76SAnirudh Venkataramanan ice_dis_vsi(pf->vsi[v], locked); 4427b9ffc76SAnirudh Venkataramanan } 4437b9ffc76SAnirudh Venkataramanan 4447b9ffc76SAnirudh Venkataramanan /** 4450b28b702SAnirudh Venkataramanan * ice_prepare_for_reset - prep for the core to reset 4460b28b702SAnirudh Venkataramanan * @pf: board private structure 4470b28b702SAnirudh Venkataramanan * 4480b28b702SAnirudh Venkataramanan * Inform or close all dependent features in prep for reset. 4490b28b702SAnirudh Venkataramanan */ 4500b28b702SAnirudh Venkataramanan static void 4510b28b702SAnirudh Venkataramanan ice_prepare_for_reset(struct ice_pf *pf) 4520b28b702SAnirudh Venkataramanan { 4530b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 4540b28b702SAnirudh Venkataramanan 4555abac9d7SBrett Creeley /* already prepared for reset */ 4565abac9d7SBrett Creeley if (test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) 4575abac9d7SBrett Creeley return; 4585abac9d7SBrett Creeley 459007676b4SAnirudh Venkataramanan /* Notify VFs of impending reset */ 460007676b4SAnirudh Venkataramanan if (ice_check_sq_alive(hw, &hw->mailboxq)) 461007676b4SAnirudh Venkataramanan ice_vc_notify_reset(pf); 462007676b4SAnirudh Venkataramanan 4630b28b702SAnirudh Venkataramanan /* disable the VSIs and their queues that are not already DOWN */ 4647b9ffc76SAnirudh Venkataramanan ice_pf_dis_all_vsi(pf, false); 4650b28b702SAnirudh Venkataramanan 466c5a2a4a3SUsha Ketineni if (hw->port_info) 467c5a2a4a3SUsha Ketineni ice_sched_clear_port(hw->port_info); 468c5a2a4a3SUsha Ketineni 4690b28b702SAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 4700f9d5027SAnirudh Venkataramanan 4710f9d5027SAnirudh Venkataramanan set_bit(__ICE_PREPARED_FOR_RESET, pf->state); 4720b28b702SAnirudh Venkataramanan } 4730b28b702SAnirudh Venkataramanan 4740b28b702SAnirudh Venkataramanan /** 4750b28b702SAnirudh Venkataramanan * ice_do_reset - Initiate one of many types of resets 4760b28b702SAnirudh Venkataramanan * @pf: board private structure 4770b28b702SAnirudh Venkataramanan * @reset_type: reset type requested 4780b28b702SAnirudh Venkataramanan * before this function was called. 4790b28b702SAnirudh Venkataramanan */ 4800b28b702SAnirudh Venkataramanan static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type) 4810b28b702SAnirudh Venkataramanan { 4820b28b702SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 4830b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 4840b28b702SAnirudh Venkataramanan 4850b28b702SAnirudh Venkataramanan dev_dbg(dev, "reset_type 0x%x requested\n", reset_type); 4860b28b702SAnirudh Venkataramanan WARN_ON(in_interrupt()); 4870b28b702SAnirudh Venkataramanan 4880b28b702SAnirudh Venkataramanan ice_prepare_for_reset(pf); 4890b28b702SAnirudh Venkataramanan 4900b28b702SAnirudh Venkataramanan /* trigger the reset */ 4910b28b702SAnirudh Venkataramanan if (ice_reset(hw, reset_type)) { 4920b28b702SAnirudh Venkataramanan dev_err(dev, "reset %d failed\n", reset_type); 4930b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 4945df7e45dSDave Ertman clear_bit(__ICE_RESET_OICR_RECV, pf->state); 4950f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 4965df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 4975df7e45dSDave Ertman clear_bit(__ICE_CORER_REQ, pf->state); 4985df7e45dSDave Ertman clear_bit(__ICE_GLOBR_REQ, pf->state); 4990b28b702SAnirudh Venkataramanan return; 5000b28b702SAnirudh Venkataramanan } 5010b28b702SAnirudh Venkataramanan 5020f9d5027SAnirudh Venkataramanan /* PFR is a bit of a special case because it doesn't result in an OICR 5030f9d5027SAnirudh Venkataramanan * interrupt. So for PFR, rebuild after the reset and clear the reset- 5040f9d5027SAnirudh Venkataramanan * associated state bits. 5050f9d5027SAnirudh Venkataramanan */ 5060b28b702SAnirudh Venkataramanan if (reset_type == ICE_RESET_PFR) { 5070b28b702SAnirudh Venkataramanan pf->pfr_count++; 5080b28b702SAnirudh Venkataramanan ice_rebuild(pf); 5090f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 5105df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 5111c44e3bcSAkeem G Abodunrin ice_reset_all_vfs(pf, true); 5120b28b702SAnirudh Venkataramanan } 5130b28b702SAnirudh Venkataramanan } 5140b28b702SAnirudh Venkataramanan 5150b28b702SAnirudh Venkataramanan /** 5160b28b702SAnirudh Venkataramanan * ice_reset_subtask - Set up for resetting the device and driver 5170b28b702SAnirudh Venkataramanan * @pf: board private structure 5180b28b702SAnirudh Venkataramanan */ 5190b28b702SAnirudh Venkataramanan static void ice_reset_subtask(struct ice_pf *pf) 5200b28b702SAnirudh Venkataramanan { 5210f9d5027SAnirudh Venkataramanan enum ice_reset_req reset_type = ICE_RESET_INVAL; 5220b28b702SAnirudh Venkataramanan 5230b28b702SAnirudh Venkataramanan /* When a CORER/GLOBR/EMPR is about to happen, the hardware triggers an 5240f9d5027SAnirudh Venkataramanan * OICR interrupt. The OICR handler (ice_misc_intr) determines what type 5250f9d5027SAnirudh Venkataramanan * of reset is pending and sets bits in pf->state indicating the reset 5265df7e45dSDave Ertman * type and __ICE_RESET_OICR_RECV. So, if the latter bit is set 5270f9d5027SAnirudh Venkataramanan * prepare for pending reset if not already (for PF software-initiated 5280f9d5027SAnirudh Venkataramanan * global resets the software should already be prepared for it as 5290f9d5027SAnirudh Venkataramanan * indicated by __ICE_PREPARED_FOR_RESET; for global resets initiated 5300f9d5027SAnirudh Venkataramanan * by firmware or software on other PFs, that bit is not set so prepare 5310f9d5027SAnirudh Venkataramanan * for the reset now), poll for reset done, rebuild and return. 5320b28b702SAnirudh Venkataramanan */ 5335df7e45dSDave Ertman if (test_bit(__ICE_RESET_OICR_RECV, pf->state)) { 5342ebd4428SDave Ertman /* Perform the largest reset requested */ 5352ebd4428SDave Ertman if (test_and_clear_bit(__ICE_CORER_RECV, pf->state)) 5362ebd4428SDave Ertman reset_type = ICE_RESET_CORER; 5372ebd4428SDave Ertman if (test_and_clear_bit(__ICE_GLOBR_RECV, pf->state)) 5382ebd4428SDave Ertman reset_type = ICE_RESET_GLOBR; 5392ebd4428SDave Ertman /* return if no valid reset type requested */ 5402ebd4428SDave Ertman if (reset_type == ICE_RESET_INVAL) 5412ebd4428SDave Ertman return; 5420b28b702SAnirudh Venkataramanan ice_prepare_for_reset(pf); 5430b28b702SAnirudh Venkataramanan 5440b28b702SAnirudh Venkataramanan /* make sure we are ready to rebuild */ 545fd2a9817SAnirudh Venkataramanan if (ice_check_reset(&pf->hw)) { 5460b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 547fd2a9817SAnirudh Venkataramanan } else { 548fd2a9817SAnirudh Venkataramanan /* done with reset. start rebuild */ 549fd2a9817SAnirudh Venkataramanan pf->hw.reset_ongoing = false; 5500b28b702SAnirudh Venkataramanan ice_rebuild(pf); 5510f9d5027SAnirudh Venkataramanan /* clear bit to resume normal operations, but 5520f9d5027SAnirudh Venkataramanan * ICE_NEEDS_RESTART bit is set in case rebuild failed 5530f9d5027SAnirudh Venkataramanan */ 5545df7e45dSDave Ertman clear_bit(__ICE_RESET_OICR_RECV, pf->state); 5550f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 5565df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 5575df7e45dSDave Ertman clear_bit(__ICE_CORER_REQ, pf->state); 5585df7e45dSDave Ertman clear_bit(__ICE_GLOBR_REQ, pf->state); 5591c44e3bcSAkeem G Abodunrin ice_reset_all_vfs(pf, true); 5600f9d5027SAnirudh Venkataramanan } 5610f9d5027SAnirudh Venkataramanan 5620f9d5027SAnirudh Venkataramanan return; 5630b28b702SAnirudh Venkataramanan } 5640b28b702SAnirudh Venkataramanan 5650b28b702SAnirudh Venkataramanan /* No pending resets to finish processing. Check for new resets */ 5665df7e45dSDave Ertman if (test_bit(__ICE_PFR_REQ, pf->state)) 5670f9d5027SAnirudh Venkataramanan reset_type = ICE_RESET_PFR; 5685df7e45dSDave Ertman if (test_bit(__ICE_CORER_REQ, pf->state)) 5690f9d5027SAnirudh Venkataramanan reset_type = ICE_RESET_CORER; 5705df7e45dSDave Ertman if (test_bit(__ICE_GLOBR_REQ, pf->state)) 5710b28b702SAnirudh Venkataramanan reset_type = ICE_RESET_GLOBR; 5720f9d5027SAnirudh Venkataramanan /* If no valid reset type requested just return */ 5730f9d5027SAnirudh Venkataramanan if (reset_type == ICE_RESET_INVAL) 5740f9d5027SAnirudh Venkataramanan return; 5750b28b702SAnirudh Venkataramanan 5760f9d5027SAnirudh Venkataramanan /* reset if not already down or busy */ 5770b28b702SAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 5780b28b702SAnirudh Venkataramanan !test_bit(__ICE_CFG_BUSY, pf->state)) { 5790b28b702SAnirudh Venkataramanan ice_do_reset(pf, reset_type); 5800b28b702SAnirudh Venkataramanan } 5810b28b702SAnirudh Venkataramanan } 5820b28b702SAnirudh Venkataramanan 5830b28b702SAnirudh Venkataramanan /** 584cdedef59SAnirudh Venkataramanan * ice_print_link_msg - print link up or down message 585cdedef59SAnirudh Venkataramanan * @vsi: the VSI whose link status is being queried 586cdedef59SAnirudh Venkataramanan * @isup: boolean for if the link is now up or down 587cdedef59SAnirudh Venkataramanan */ 588fcea6f3dSAnirudh Venkataramanan void ice_print_link_msg(struct ice_vsi *vsi, bool isup) 589cdedef59SAnirudh Venkataramanan { 590cdedef59SAnirudh Venkataramanan const char *speed; 591cdedef59SAnirudh Venkataramanan const char *fc; 592cdedef59SAnirudh Venkataramanan 593cdedef59SAnirudh Venkataramanan if (vsi->current_isup == isup) 594cdedef59SAnirudh Venkataramanan return; 595cdedef59SAnirudh Venkataramanan 596cdedef59SAnirudh Venkataramanan vsi->current_isup = isup; 597cdedef59SAnirudh Venkataramanan 598cdedef59SAnirudh Venkataramanan if (!isup) { 599cdedef59SAnirudh Venkataramanan netdev_info(vsi->netdev, "NIC Link is Down\n"); 600cdedef59SAnirudh Venkataramanan return; 601cdedef59SAnirudh Venkataramanan } 602cdedef59SAnirudh Venkataramanan 603cdedef59SAnirudh Venkataramanan switch (vsi->port_info->phy.link_info.link_speed) { 604cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_40GB: 605cdedef59SAnirudh Venkataramanan speed = "40 G"; 606cdedef59SAnirudh Venkataramanan break; 607cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 608cdedef59SAnirudh Venkataramanan speed = "25 G"; 609cdedef59SAnirudh Venkataramanan break; 610cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_20GB: 611cdedef59SAnirudh Venkataramanan speed = "20 G"; 612cdedef59SAnirudh Venkataramanan break; 613cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_10GB: 614cdedef59SAnirudh Venkataramanan speed = "10 G"; 615cdedef59SAnirudh Venkataramanan break; 616cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_5GB: 617cdedef59SAnirudh Venkataramanan speed = "5 G"; 618cdedef59SAnirudh Venkataramanan break; 619cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_2500MB: 620cdedef59SAnirudh Venkataramanan speed = "2.5 G"; 621cdedef59SAnirudh Venkataramanan break; 622cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_1000MB: 623cdedef59SAnirudh Venkataramanan speed = "1 G"; 624cdedef59SAnirudh Venkataramanan break; 625cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100MB: 626cdedef59SAnirudh Venkataramanan speed = "100 M"; 627cdedef59SAnirudh Venkataramanan break; 628cdedef59SAnirudh Venkataramanan default: 629cdedef59SAnirudh Venkataramanan speed = "Unknown"; 630cdedef59SAnirudh Venkataramanan break; 631cdedef59SAnirudh Venkataramanan } 632cdedef59SAnirudh Venkataramanan 633cdedef59SAnirudh Venkataramanan switch (vsi->port_info->fc.current_mode) { 634cdedef59SAnirudh Venkataramanan case ICE_FC_FULL: 635cdedef59SAnirudh Venkataramanan fc = "RX/TX"; 636cdedef59SAnirudh Venkataramanan break; 637cdedef59SAnirudh Venkataramanan case ICE_FC_TX_PAUSE: 638cdedef59SAnirudh Venkataramanan fc = "TX"; 639cdedef59SAnirudh Venkataramanan break; 640cdedef59SAnirudh Venkataramanan case ICE_FC_RX_PAUSE: 641cdedef59SAnirudh Venkataramanan fc = "RX"; 642cdedef59SAnirudh Venkataramanan break; 643203a068aSBrett Creeley case ICE_FC_NONE: 644203a068aSBrett Creeley fc = "None"; 645203a068aSBrett Creeley break; 646cdedef59SAnirudh Venkataramanan default: 647cdedef59SAnirudh Venkataramanan fc = "Unknown"; 648cdedef59SAnirudh Venkataramanan break; 649cdedef59SAnirudh Venkataramanan } 650cdedef59SAnirudh Venkataramanan 651cdedef59SAnirudh Venkataramanan netdev_info(vsi->netdev, "NIC Link is up %sbps, Flow Control: %s\n", 652cdedef59SAnirudh Venkataramanan speed, fc); 653cdedef59SAnirudh Venkataramanan } 654cdedef59SAnirudh Venkataramanan 655cdedef59SAnirudh Venkataramanan /** 656f9867df6SAnirudh Venkataramanan * ice_vsi_link_event - update the VSI's netdev 657f9867df6SAnirudh Venkataramanan * @vsi: the VSI on which the link event occurred 658f9867df6SAnirudh Venkataramanan * @link_up: whether or not the VSI needs to be set up or down 6590b28b702SAnirudh Venkataramanan */ 6600b28b702SAnirudh Venkataramanan static void ice_vsi_link_event(struct ice_vsi *vsi, bool link_up) 6610b28b702SAnirudh Venkataramanan { 6620b28b702SAnirudh Venkataramanan if (!vsi || test_bit(__ICE_DOWN, vsi->state)) 6630b28b702SAnirudh Venkataramanan return; 6640b28b702SAnirudh Venkataramanan 6650b28b702SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 6660b28b702SAnirudh Venkataramanan if (!vsi->netdev) { 6670b28b702SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, 6680b28b702SAnirudh Venkataramanan "vsi->netdev is not initialized!\n"); 6690b28b702SAnirudh Venkataramanan return; 6700b28b702SAnirudh Venkataramanan } 6710b28b702SAnirudh Venkataramanan if (link_up) { 6720b28b702SAnirudh Venkataramanan netif_carrier_on(vsi->netdev); 6730b28b702SAnirudh Venkataramanan netif_tx_wake_all_queues(vsi->netdev); 6740b28b702SAnirudh Venkataramanan } else { 6750b28b702SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 6760b28b702SAnirudh Venkataramanan netif_tx_stop_all_queues(vsi->netdev); 6770b28b702SAnirudh Venkataramanan } 6780b28b702SAnirudh Venkataramanan } 6790b28b702SAnirudh Venkataramanan } 6800b28b702SAnirudh Venkataramanan 6810b28b702SAnirudh Venkataramanan /** 6820b28b702SAnirudh Venkataramanan * ice_link_event - process the link event 6830b28b702SAnirudh Venkataramanan * @pf: pf that the link event is associated with 6840b28b702SAnirudh Venkataramanan * @pi: port_info for the port that the link event is associated with 6850b28b702SAnirudh Venkataramanan * 6860b28b702SAnirudh Venkataramanan * Returns -EIO if ice_get_link_status() fails 6870b28b702SAnirudh Venkataramanan * Returns 0 on success 6880b28b702SAnirudh Venkataramanan */ 6890b28b702SAnirudh Venkataramanan static int 6900b28b702SAnirudh Venkataramanan ice_link_event(struct ice_pf *pf, struct ice_port_info *pi) 6910b28b702SAnirudh Venkataramanan { 6920b28b702SAnirudh Venkataramanan u8 new_link_speed, old_link_speed; 6930b28b702SAnirudh Venkataramanan struct ice_phy_info *phy_info; 6940b28b702SAnirudh Venkataramanan bool new_link_same_as_old; 6950b28b702SAnirudh Venkataramanan bool new_link, old_link; 6960b28b702SAnirudh Venkataramanan u8 lport; 6970b28b702SAnirudh Venkataramanan u16 v; 6980b28b702SAnirudh Venkataramanan 6990b28b702SAnirudh Venkataramanan phy_info = &pi->phy; 7000b28b702SAnirudh Venkataramanan phy_info->link_info_old = phy_info->link_info; 7010b28b702SAnirudh Venkataramanan /* Force ice_get_link_status() to update link info */ 7020b28b702SAnirudh Venkataramanan phy_info->get_link_info = true; 7030b28b702SAnirudh Venkataramanan 7040b28b702SAnirudh Venkataramanan old_link = (phy_info->link_info_old.link_info & ICE_AQ_LINK_UP); 7050b28b702SAnirudh Venkataramanan old_link_speed = phy_info->link_info_old.link_speed; 7060b28b702SAnirudh Venkataramanan 7070b28b702SAnirudh Venkataramanan lport = pi->lport; 7080b28b702SAnirudh Venkataramanan if (ice_get_link_status(pi, &new_link)) { 7090b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 7100b28b702SAnirudh Venkataramanan "Could not get link status for port %d\n", lport); 7110b28b702SAnirudh Venkataramanan return -EIO; 7120b28b702SAnirudh Venkataramanan } 7130b28b702SAnirudh Venkataramanan 7140b28b702SAnirudh Venkataramanan new_link_speed = phy_info->link_info.link_speed; 7150b28b702SAnirudh Venkataramanan 7160b28b702SAnirudh Venkataramanan new_link_same_as_old = (new_link == old_link && 7170b28b702SAnirudh Venkataramanan new_link_speed == old_link_speed); 7180b28b702SAnirudh Venkataramanan 7190b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) { 7200b28b702SAnirudh Venkataramanan struct ice_vsi *vsi = pf->vsi[v]; 7210b28b702SAnirudh Venkataramanan 7220b28b702SAnirudh Venkataramanan if (!vsi || !vsi->port_info) 7230b28b702SAnirudh Venkataramanan continue; 7240b28b702SAnirudh Venkataramanan 7250b28b702SAnirudh Venkataramanan if (new_link_same_as_old && 7260b28b702SAnirudh Venkataramanan (test_bit(__ICE_DOWN, vsi->state) || 7270b28b702SAnirudh Venkataramanan new_link == netif_carrier_ok(vsi->netdev))) 7280b28b702SAnirudh Venkataramanan continue; 7290b28b702SAnirudh Venkataramanan 7300b28b702SAnirudh Venkataramanan if (vsi->port_info->lport == lport) { 7310b28b702SAnirudh Venkataramanan ice_print_link_msg(vsi, new_link); 7320b28b702SAnirudh Venkataramanan ice_vsi_link_event(vsi, new_link); 7330b28b702SAnirudh Venkataramanan } 7340b28b702SAnirudh Venkataramanan } 7350b28b702SAnirudh Venkataramanan 7364cf7bc0dSMitch Williams if (!new_link_same_as_old && pf->num_alloc_vfs) 73753b8decbSAnirudh Venkataramanan ice_vc_notify_link_state(pf); 73853b8decbSAnirudh Venkataramanan 7390b28b702SAnirudh Venkataramanan return 0; 7400b28b702SAnirudh Venkataramanan } 7410b28b702SAnirudh Venkataramanan 7420b28b702SAnirudh Venkataramanan /** 7434f4be03bSAnirudh Venkataramanan * ice_watchdog_subtask - periodic tasks not using event driven scheduling 7444f4be03bSAnirudh Venkataramanan * @pf: board private structure 7450b28b702SAnirudh Venkataramanan */ 7464f4be03bSAnirudh Venkataramanan static void ice_watchdog_subtask(struct ice_pf *pf) 7470b28b702SAnirudh Venkataramanan { 7484f4be03bSAnirudh Venkataramanan int i; 7490b28b702SAnirudh Venkataramanan 7504f4be03bSAnirudh Venkataramanan /* if interface is down do nothing */ 7514f4be03bSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state) || 7524f4be03bSAnirudh Venkataramanan test_bit(__ICE_CFG_BUSY, pf->state)) 7534f4be03bSAnirudh Venkataramanan return; 7540b28b702SAnirudh Venkataramanan 7554f4be03bSAnirudh Venkataramanan /* make sure we don't do these things too often */ 7564f4be03bSAnirudh Venkataramanan if (time_before(jiffies, 7574f4be03bSAnirudh Venkataramanan pf->serv_tmr_prev + pf->serv_tmr_period)) 7584f4be03bSAnirudh Venkataramanan return; 7590b28b702SAnirudh Venkataramanan 7604f4be03bSAnirudh Venkataramanan pf->serv_tmr_prev = jiffies; 7614f4be03bSAnirudh Venkataramanan 7624f4be03bSAnirudh Venkataramanan /* Update the stats for active netdevs so the network stack 7634f4be03bSAnirudh Venkataramanan * can look at updated numbers whenever it cares to 7644f4be03bSAnirudh Venkataramanan */ 7654f4be03bSAnirudh Venkataramanan ice_update_pf_stats(pf); 76680ed404aSBrett Creeley ice_for_each_vsi(pf, i) 7674f4be03bSAnirudh Venkataramanan if (pf->vsi[i] && pf->vsi[i]->netdev) 7684f4be03bSAnirudh Venkataramanan ice_update_vsi_stats(pf->vsi[i]); 7690b28b702SAnirudh Venkataramanan } 7700b28b702SAnirudh Venkataramanan 7710b28b702SAnirudh Venkataramanan /** 772250c3b3eSBrett Creeley * ice_init_link_events - enable/initialize link events 773250c3b3eSBrett Creeley * @pi: pointer to the port_info instance 774250c3b3eSBrett Creeley * 775250c3b3eSBrett Creeley * Returns -EIO on failure, 0 on success 776250c3b3eSBrett Creeley */ 777250c3b3eSBrett Creeley static int ice_init_link_events(struct ice_port_info *pi) 778250c3b3eSBrett Creeley { 779250c3b3eSBrett Creeley u16 mask; 780250c3b3eSBrett Creeley 781250c3b3eSBrett Creeley mask = ~((u16)(ICE_AQ_LINK_EVENT_UPDOWN | ICE_AQ_LINK_EVENT_MEDIA_NA | 782250c3b3eSBrett Creeley ICE_AQ_LINK_EVENT_MODULE_QUAL_FAIL)); 783250c3b3eSBrett Creeley 784250c3b3eSBrett Creeley if (ice_aq_set_event_mask(pi->hw, pi->lport, mask, NULL)) { 785250c3b3eSBrett Creeley dev_dbg(ice_hw_to_dev(pi->hw), 786250c3b3eSBrett Creeley "Failed to set link event mask for port %d\n", 787250c3b3eSBrett Creeley pi->lport); 788250c3b3eSBrett Creeley return -EIO; 789250c3b3eSBrett Creeley } 790250c3b3eSBrett Creeley 791250c3b3eSBrett Creeley if (ice_aq_get_link_info(pi, true, NULL, NULL)) { 792250c3b3eSBrett Creeley dev_dbg(ice_hw_to_dev(pi->hw), 793250c3b3eSBrett Creeley "Failed to enable link events for port %d\n", 794250c3b3eSBrett Creeley pi->lport); 795250c3b3eSBrett Creeley return -EIO; 796250c3b3eSBrett Creeley } 797250c3b3eSBrett Creeley 798250c3b3eSBrett Creeley return 0; 799250c3b3eSBrett Creeley } 800250c3b3eSBrett Creeley 801250c3b3eSBrett Creeley /** 802250c3b3eSBrett Creeley * ice_handle_link_event - handle link event via ARQ 803250c3b3eSBrett Creeley * @pf: pf that the link event is associated with 804250c3b3eSBrett Creeley * 805250c3b3eSBrett Creeley * Return -EINVAL if port_info is null 806250c3b3eSBrett Creeley * Return status on success 807250c3b3eSBrett Creeley */ 808250c3b3eSBrett Creeley static int ice_handle_link_event(struct ice_pf *pf) 809250c3b3eSBrett Creeley { 810250c3b3eSBrett Creeley struct ice_port_info *port_info; 811250c3b3eSBrett Creeley int status; 812250c3b3eSBrett Creeley 813250c3b3eSBrett Creeley port_info = pf->hw.port_info; 814250c3b3eSBrett Creeley if (!port_info) 815250c3b3eSBrett Creeley return -EINVAL; 816250c3b3eSBrett Creeley 817250c3b3eSBrett Creeley status = ice_link_event(pf, port_info); 818250c3b3eSBrett Creeley if (status) 819250c3b3eSBrett Creeley dev_dbg(&pf->pdev->dev, 820250c3b3eSBrett Creeley "Could not process link event, error %d\n", status); 821250c3b3eSBrett Creeley 822250c3b3eSBrett Creeley return status; 823250c3b3eSBrett Creeley } 824250c3b3eSBrett Creeley 825250c3b3eSBrett Creeley /** 826940b61afSAnirudh Venkataramanan * __ice_clean_ctrlq - helper function to clean controlq rings 827940b61afSAnirudh Venkataramanan * @pf: ptr to struct ice_pf 828940b61afSAnirudh Venkataramanan * @q_type: specific Control queue type 829940b61afSAnirudh Venkataramanan */ 830940b61afSAnirudh Venkataramanan static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) 831940b61afSAnirudh Venkataramanan { 832940b61afSAnirudh Venkataramanan struct ice_rq_event_info event; 833940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 834940b61afSAnirudh Venkataramanan struct ice_ctl_q_info *cq; 835940b61afSAnirudh Venkataramanan u16 pending, i = 0; 836940b61afSAnirudh Venkataramanan const char *qtype; 837940b61afSAnirudh Venkataramanan u32 oldval, val; 838940b61afSAnirudh Venkataramanan 8390b28b702SAnirudh Venkataramanan /* Do not clean control queue if/when PF reset fails */ 8400b28b702SAnirudh Venkataramanan if (test_bit(__ICE_RESET_FAILED, pf->state)) 8410b28b702SAnirudh Venkataramanan return 0; 8420b28b702SAnirudh Venkataramanan 843940b61afSAnirudh Venkataramanan switch (q_type) { 844940b61afSAnirudh Venkataramanan case ICE_CTL_Q_ADMIN: 845940b61afSAnirudh Venkataramanan cq = &hw->adminq; 846940b61afSAnirudh Venkataramanan qtype = "Admin"; 847940b61afSAnirudh Venkataramanan break; 84875d2b253SAnirudh Venkataramanan case ICE_CTL_Q_MAILBOX: 84975d2b253SAnirudh Venkataramanan cq = &hw->mailboxq; 85075d2b253SAnirudh Venkataramanan qtype = "Mailbox"; 85175d2b253SAnirudh Venkataramanan break; 852940b61afSAnirudh Venkataramanan default: 853940b61afSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown control queue type 0x%x\n", 854940b61afSAnirudh Venkataramanan q_type); 855940b61afSAnirudh Venkataramanan return 0; 856940b61afSAnirudh Venkataramanan } 857940b61afSAnirudh Venkataramanan 858940b61afSAnirudh Venkataramanan /* check for error indications - PF_xx_AxQLEN register layout for 859940b61afSAnirudh Venkataramanan * FW/MBX/SB are identical so just use defines for PF_FW_AxQLEN. 860940b61afSAnirudh Venkataramanan */ 861940b61afSAnirudh Venkataramanan val = rd32(hw, cq->rq.len); 862940b61afSAnirudh Venkataramanan if (val & (PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M | 863940b61afSAnirudh Venkataramanan PF_FW_ARQLEN_ARQCRIT_M)) { 864940b61afSAnirudh Venkataramanan oldval = val; 865940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQVFE_M) 866940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 867940b61afSAnirudh Venkataramanan "%s Receive Queue VF Error detected\n", qtype); 868940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQOVFL_M) { 869940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 870940b61afSAnirudh Venkataramanan "%s Receive Queue Overflow Error detected\n", 871940b61afSAnirudh Venkataramanan qtype); 872940b61afSAnirudh Venkataramanan } 873940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQCRIT_M) 874940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 875940b61afSAnirudh Venkataramanan "%s Receive Queue Critical Error detected\n", 876940b61afSAnirudh Venkataramanan qtype); 877940b61afSAnirudh Venkataramanan val &= ~(PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M | 878940b61afSAnirudh Venkataramanan PF_FW_ARQLEN_ARQCRIT_M); 879940b61afSAnirudh Venkataramanan if (oldval != val) 880940b61afSAnirudh Venkataramanan wr32(hw, cq->rq.len, val); 881940b61afSAnirudh Venkataramanan } 882940b61afSAnirudh Venkataramanan 883940b61afSAnirudh Venkataramanan val = rd32(hw, cq->sq.len); 884940b61afSAnirudh Venkataramanan if (val & (PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M | 885940b61afSAnirudh Venkataramanan PF_FW_ATQLEN_ATQCRIT_M)) { 886940b61afSAnirudh Venkataramanan oldval = val; 887940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQVFE_M) 888940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 889940b61afSAnirudh Venkataramanan "%s Send Queue VF Error detected\n", qtype); 890940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQOVFL_M) { 891940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 892940b61afSAnirudh Venkataramanan "%s Send Queue Overflow Error detected\n", 893940b61afSAnirudh Venkataramanan qtype); 894940b61afSAnirudh Venkataramanan } 895940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQCRIT_M) 896940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 897940b61afSAnirudh Venkataramanan "%s Send Queue Critical Error detected\n", 898940b61afSAnirudh Venkataramanan qtype); 899940b61afSAnirudh Venkataramanan val &= ~(PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M | 900940b61afSAnirudh Venkataramanan PF_FW_ATQLEN_ATQCRIT_M); 901940b61afSAnirudh Venkataramanan if (oldval != val) 902940b61afSAnirudh Venkataramanan wr32(hw, cq->sq.len, val); 903940b61afSAnirudh Venkataramanan } 904940b61afSAnirudh Venkataramanan 905940b61afSAnirudh Venkataramanan event.buf_len = cq->rq_buf_size; 906940b61afSAnirudh Venkataramanan event.msg_buf = devm_kzalloc(&pf->pdev->dev, event.buf_len, 907940b61afSAnirudh Venkataramanan GFP_KERNEL); 908940b61afSAnirudh Venkataramanan if (!event.msg_buf) 909940b61afSAnirudh Venkataramanan return 0; 910940b61afSAnirudh Venkataramanan 911940b61afSAnirudh Venkataramanan do { 912940b61afSAnirudh Venkataramanan enum ice_status ret; 9130b28b702SAnirudh Venkataramanan u16 opcode; 914940b61afSAnirudh Venkataramanan 915940b61afSAnirudh Venkataramanan ret = ice_clean_rq_elem(hw, cq, &event, &pending); 916940b61afSAnirudh Venkataramanan if (ret == ICE_ERR_AQ_NO_WORK) 917940b61afSAnirudh Venkataramanan break; 918940b61afSAnirudh Venkataramanan if (ret) { 919940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 920940b61afSAnirudh Venkataramanan "%s Receive Queue event error %d\n", qtype, 921940b61afSAnirudh Venkataramanan ret); 922940b61afSAnirudh Venkataramanan break; 923940b61afSAnirudh Venkataramanan } 9240b28b702SAnirudh Venkataramanan 9250b28b702SAnirudh Venkataramanan opcode = le16_to_cpu(event.desc.opcode); 9260b28b702SAnirudh Venkataramanan 9270b28b702SAnirudh Venkataramanan switch (opcode) { 928250c3b3eSBrett Creeley case ice_aqc_opc_get_link_status: 929250c3b3eSBrett Creeley if (ice_handle_link_event(pf)) 930250c3b3eSBrett Creeley dev_err(&pf->pdev->dev, 931250c3b3eSBrett Creeley "Could not handle link event\n"); 932250c3b3eSBrett Creeley break; 9331071a835SAnirudh Venkataramanan case ice_mbx_opc_send_msg_to_pf: 9341071a835SAnirudh Venkataramanan ice_vc_process_vf_msg(pf, &event); 9351071a835SAnirudh Venkataramanan break; 9368b97ceb1SHieu Tran case ice_aqc_opc_fw_logging: 9378b97ceb1SHieu Tran ice_output_fw_log(hw, &event.desc, event.msg_buf); 9388b97ceb1SHieu Tran break; 93900cc3f1bSAnirudh Venkataramanan case ice_aqc_opc_lldp_set_mib_change: 94000cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(pf, &event); 94100cc3f1bSAnirudh Venkataramanan break; 9420b28b702SAnirudh Venkataramanan default: 9430b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 9440b28b702SAnirudh Venkataramanan "%s Receive Queue unknown event 0x%04x ignored\n", 9450b28b702SAnirudh Venkataramanan qtype, opcode); 9460b28b702SAnirudh Venkataramanan break; 9470b28b702SAnirudh Venkataramanan } 948940b61afSAnirudh Venkataramanan } while (pending && (i++ < ICE_DFLT_IRQ_WORK)); 949940b61afSAnirudh Venkataramanan 950940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, event.msg_buf); 951940b61afSAnirudh Venkataramanan 952940b61afSAnirudh Venkataramanan return pending && (i == ICE_DFLT_IRQ_WORK); 953940b61afSAnirudh Venkataramanan } 954940b61afSAnirudh Venkataramanan 955940b61afSAnirudh Venkataramanan /** 9563d6b640eSAnirudh Venkataramanan * ice_ctrlq_pending - check if there is a difference between ntc and ntu 9573d6b640eSAnirudh Venkataramanan * @hw: pointer to hardware info 9583d6b640eSAnirudh Venkataramanan * @cq: control queue information 9593d6b640eSAnirudh Venkataramanan * 9603d6b640eSAnirudh Venkataramanan * returns true if there are pending messages in a queue, false if there aren't 9613d6b640eSAnirudh Venkataramanan */ 9623d6b640eSAnirudh Venkataramanan static bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq) 9633d6b640eSAnirudh Venkataramanan { 9643d6b640eSAnirudh Venkataramanan u16 ntu; 9653d6b640eSAnirudh Venkataramanan 9663d6b640eSAnirudh Venkataramanan ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask); 9673d6b640eSAnirudh Venkataramanan return cq->rq.next_to_clean != ntu; 9683d6b640eSAnirudh Venkataramanan } 9693d6b640eSAnirudh Venkataramanan 9703d6b640eSAnirudh Venkataramanan /** 971940b61afSAnirudh Venkataramanan * ice_clean_adminq_subtask - clean the AdminQ rings 972940b61afSAnirudh Venkataramanan * @pf: board private structure 973940b61afSAnirudh Venkataramanan */ 974940b61afSAnirudh Venkataramanan static void ice_clean_adminq_subtask(struct ice_pf *pf) 975940b61afSAnirudh Venkataramanan { 976940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 977940b61afSAnirudh Venkataramanan 978940b61afSAnirudh Venkataramanan if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) 979940b61afSAnirudh Venkataramanan return; 980940b61afSAnirudh Venkataramanan 981940b61afSAnirudh Venkataramanan if (__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN)) 982940b61afSAnirudh Venkataramanan return; 983940b61afSAnirudh Venkataramanan 984940b61afSAnirudh Venkataramanan clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); 985940b61afSAnirudh Venkataramanan 9863d6b640eSAnirudh Venkataramanan /* There might be a situation where new messages arrive to a control 9873d6b640eSAnirudh Venkataramanan * queue between processing the last message and clearing the 9883d6b640eSAnirudh Venkataramanan * EVENT_PENDING bit. So before exiting, check queue head again (using 9893d6b640eSAnirudh Venkataramanan * ice_ctrlq_pending) and process new messages if any. 9903d6b640eSAnirudh Venkataramanan */ 9913d6b640eSAnirudh Venkataramanan if (ice_ctrlq_pending(hw, &hw->adminq)) 9923d6b640eSAnirudh Venkataramanan __ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN); 993940b61afSAnirudh Venkataramanan 994940b61afSAnirudh Venkataramanan ice_flush(hw); 995940b61afSAnirudh Venkataramanan } 996940b61afSAnirudh Venkataramanan 997940b61afSAnirudh Venkataramanan /** 99875d2b253SAnirudh Venkataramanan * ice_clean_mailboxq_subtask - clean the MailboxQ rings 99975d2b253SAnirudh Venkataramanan * @pf: board private structure 100075d2b253SAnirudh Venkataramanan */ 100175d2b253SAnirudh Venkataramanan static void ice_clean_mailboxq_subtask(struct ice_pf *pf) 100275d2b253SAnirudh Venkataramanan { 100375d2b253SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 100475d2b253SAnirudh Venkataramanan 100575d2b253SAnirudh Venkataramanan if (!test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state)) 100675d2b253SAnirudh Venkataramanan return; 100775d2b253SAnirudh Venkataramanan 100875d2b253SAnirudh Venkataramanan if (__ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX)) 100975d2b253SAnirudh Venkataramanan return; 101075d2b253SAnirudh Venkataramanan 101175d2b253SAnirudh Venkataramanan clear_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state); 101275d2b253SAnirudh Venkataramanan 101375d2b253SAnirudh Venkataramanan if (ice_ctrlq_pending(hw, &hw->mailboxq)) 101475d2b253SAnirudh Venkataramanan __ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX); 101575d2b253SAnirudh Venkataramanan 101675d2b253SAnirudh Venkataramanan ice_flush(hw); 101775d2b253SAnirudh Venkataramanan } 101875d2b253SAnirudh Venkataramanan 101975d2b253SAnirudh Venkataramanan /** 1020940b61afSAnirudh Venkataramanan * ice_service_task_schedule - schedule the service task to wake up 1021940b61afSAnirudh Venkataramanan * @pf: board private structure 1022940b61afSAnirudh Venkataramanan * 1023940b61afSAnirudh Venkataramanan * If not already scheduled, this puts the task into the work queue. 1024940b61afSAnirudh Venkataramanan */ 1025940b61afSAnirudh Venkataramanan static void ice_service_task_schedule(struct ice_pf *pf) 1026940b61afSAnirudh Venkataramanan { 10278d81fa55SAkeem G Abodunrin if (!test_bit(__ICE_SERVICE_DIS, pf->state) && 10280f9d5027SAnirudh Venkataramanan !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) && 10290f9d5027SAnirudh Venkataramanan !test_bit(__ICE_NEEDS_RESTART, pf->state)) 1030940b61afSAnirudh Venkataramanan queue_work(ice_wq, &pf->serv_task); 1031940b61afSAnirudh Venkataramanan } 1032940b61afSAnirudh Venkataramanan 1033940b61afSAnirudh Venkataramanan /** 1034940b61afSAnirudh Venkataramanan * ice_service_task_complete - finish up the service task 1035940b61afSAnirudh Venkataramanan * @pf: board private structure 1036940b61afSAnirudh Venkataramanan */ 1037940b61afSAnirudh Venkataramanan static void ice_service_task_complete(struct ice_pf *pf) 1038940b61afSAnirudh Venkataramanan { 1039940b61afSAnirudh Venkataramanan WARN_ON(!test_bit(__ICE_SERVICE_SCHED, pf->state)); 1040940b61afSAnirudh Venkataramanan 1041940b61afSAnirudh Venkataramanan /* force memory (pf->state) to sync before next service task */ 1042940b61afSAnirudh Venkataramanan smp_mb__before_atomic(); 1043940b61afSAnirudh Venkataramanan clear_bit(__ICE_SERVICE_SCHED, pf->state); 1044940b61afSAnirudh Venkataramanan } 1045940b61afSAnirudh Venkataramanan 1046940b61afSAnirudh Venkataramanan /** 10478d81fa55SAkeem G Abodunrin * ice_service_task_stop - stop service task and cancel works 10488d81fa55SAkeem G Abodunrin * @pf: board private structure 10498d81fa55SAkeem G Abodunrin */ 10508d81fa55SAkeem G Abodunrin static void ice_service_task_stop(struct ice_pf *pf) 10518d81fa55SAkeem G Abodunrin { 10528d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 10538d81fa55SAkeem G Abodunrin 10548d81fa55SAkeem G Abodunrin if (pf->serv_tmr.function) 10558d81fa55SAkeem G Abodunrin del_timer_sync(&pf->serv_tmr); 10568d81fa55SAkeem G Abodunrin if (pf->serv_task.func) 10578d81fa55SAkeem G Abodunrin cancel_work_sync(&pf->serv_task); 10588d81fa55SAkeem G Abodunrin 10598d81fa55SAkeem G Abodunrin clear_bit(__ICE_SERVICE_SCHED, pf->state); 10608d81fa55SAkeem G Abodunrin } 10618d81fa55SAkeem G Abodunrin 10628d81fa55SAkeem G Abodunrin /** 10635995b6d0SBrett Creeley * ice_service_task_restart - restart service task and schedule works 10645995b6d0SBrett Creeley * @pf: board private structure 10655995b6d0SBrett Creeley * 10665995b6d0SBrett Creeley * This function is needed for suspend and resume works (e.g WoL scenario) 10675995b6d0SBrett Creeley */ 10685995b6d0SBrett Creeley static void ice_service_task_restart(struct ice_pf *pf) 10695995b6d0SBrett Creeley { 10705995b6d0SBrett Creeley clear_bit(__ICE_SERVICE_DIS, pf->state); 10715995b6d0SBrett Creeley ice_service_task_schedule(pf); 10725995b6d0SBrett Creeley } 10735995b6d0SBrett Creeley 10745995b6d0SBrett Creeley /** 1075940b61afSAnirudh Venkataramanan * ice_service_timer - timer callback to schedule service task 1076940b61afSAnirudh Venkataramanan * @t: pointer to timer_list 1077940b61afSAnirudh Venkataramanan */ 1078940b61afSAnirudh Venkataramanan static void ice_service_timer(struct timer_list *t) 1079940b61afSAnirudh Venkataramanan { 1080940b61afSAnirudh Venkataramanan struct ice_pf *pf = from_timer(pf, t, serv_tmr); 1081940b61afSAnirudh Venkataramanan 1082940b61afSAnirudh Venkataramanan mod_timer(&pf->serv_tmr, round_jiffies(pf->serv_tmr_period + jiffies)); 1083940b61afSAnirudh Venkataramanan ice_service_task_schedule(pf); 1084940b61afSAnirudh Venkataramanan } 1085940b61afSAnirudh Venkataramanan 1086940b61afSAnirudh Venkataramanan /** 1087b3969fd7SSudheer Mogilappagari * ice_handle_mdd_event - handle malicious driver detect event 1088b3969fd7SSudheer Mogilappagari * @pf: pointer to the PF structure 1089b3969fd7SSudheer Mogilappagari * 1090b3969fd7SSudheer Mogilappagari * Called from service task. OICR interrupt handler indicates MDD event 1091b3969fd7SSudheer Mogilappagari */ 1092b3969fd7SSudheer Mogilappagari static void ice_handle_mdd_event(struct ice_pf *pf) 1093b3969fd7SSudheer Mogilappagari { 1094b3969fd7SSudheer Mogilappagari struct ice_hw *hw = &pf->hw; 1095b3969fd7SSudheer Mogilappagari bool mdd_detected = false; 1096b3969fd7SSudheer Mogilappagari u32 reg; 10977c4bc1f5SAnirudh Venkataramanan int i; 1098b3969fd7SSudheer Mogilappagari 1099b3969fd7SSudheer Mogilappagari if (!test_bit(__ICE_MDD_EVENT_PENDING, pf->state)) 1100b3969fd7SSudheer Mogilappagari return; 1101b3969fd7SSudheer Mogilappagari 1102b3969fd7SSudheer Mogilappagari /* find what triggered the MDD event */ 1103b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_TX_PQM); 1104b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_TX_PQM_VALID_M) { 1105b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >> 1106b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_PF_NUM_S; 1107b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >> 1108b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_VF_NUM_S; 1109b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >> 1110b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_MAL_TYPE_S; 1111b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >> 1112b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_QNUM_S); 1113b3969fd7SSudheer Mogilappagari 1114b3969fd7SSudheer Mogilappagari if (netif_msg_tx_err(pf)) 1115b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", 1116b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 1117b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_TX_PQM, 0xffffffff); 1118b3969fd7SSudheer Mogilappagari mdd_detected = true; 1119b3969fd7SSudheer Mogilappagari } 1120b3969fd7SSudheer Mogilappagari 1121b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_TX_TCLAN); 1122b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_TX_TCLAN_VALID_M) { 1123b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >> 1124b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_PF_NUM_S; 1125b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >> 1126b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_VF_NUM_S; 1127b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >> 1128b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_MAL_TYPE_S; 1129b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >> 1130b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_QNUM_S); 1131b3969fd7SSudheer Mogilappagari 1132b3969fd7SSudheer Mogilappagari if (netif_msg_rx_err(pf)) 1133b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", 1134b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 1135b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff); 1136b3969fd7SSudheer Mogilappagari mdd_detected = true; 1137b3969fd7SSudheer Mogilappagari } 1138b3969fd7SSudheer Mogilappagari 1139b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_RX); 1140b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_RX_VALID_M) { 1141b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >> 1142b3969fd7SSudheer Mogilappagari GL_MDET_RX_PF_NUM_S; 1143b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >> 1144b3969fd7SSudheer Mogilappagari GL_MDET_RX_VF_NUM_S; 1145b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >> 1146b3969fd7SSudheer Mogilappagari GL_MDET_RX_MAL_TYPE_S; 1147b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_RX_QNUM_M) >> 1148b3969fd7SSudheer Mogilappagari GL_MDET_RX_QNUM_S); 1149b3969fd7SSudheer Mogilappagari 1150b3969fd7SSudheer Mogilappagari if (netif_msg_rx_err(pf)) 1151b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n", 1152b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 1153b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_RX, 0xffffffff); 1154b3969fd7SSudheer Mogilappagari mdd_detected = true; 1155b3969fd7SSudheer Mogilappagari } 1156b3969fd7SSudheer Mogilappagari 1157b3969fd7SSudheer Mogilappagari if (mdd_detected) { 1158b3969fd7SSudheer Mogilappagari bool pf_mdd_detected = false; 1159b3969fd7SSudheer Mogilappagari 1160b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_TX_PQM); 1161b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_TX_PQM_VALID_M) { 1162b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_TX_PQM, 0xFFFF); 1163b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n"); 1164b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1165b3969fd7SSudheer Mogilappagari } 1166b3969fd7SSudheer Mogilappagari 1167b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_TX_TCLAN); 1168b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_TX_TCLAN_VALID_M) { 1169b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF); 1170b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n"); 1171b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1172b3969fd7SSudheer Mogilappagari } 1173b3969fd7SSudheer Mogilappagari 1174b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_RX); 1175b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_RX_VALID_M) { 1176b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_RX, 0xFFFF); 1177b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "RX driver issue detected, PF reset issued\n"); 1178b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1179b3969fd7SSudheer Mogilappagari } 1180b3969fd7SSudheer Mogilappagari /* Queue belongs to the PF initiate a reset */ 1181b3969fd7SSudheer Mogilappagari if (pf_mdd_detected) { 1182b3969fd7SSudheer Mogilappagari set_bit(__ICE_NEEDS_RESTART, pf->state); 1183b3969fd7SSudheer Mogilappagari ice_service_task_schedule(pf); 1184b3969fd7SSudheer Mogilappagari } 1185b3969fd7SSudheer Mogilappagari } 1186b3969fd7SSudheer Mogilappagari 11877c4bc1f5SAnirudh Venkataramanan /* see if one of the VFs needs to be reset */ 11887c4bc1f5SAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) { 11897c4bc1f5SAnirudh Venkataramanan struct ice_vf *vf = &pf->vf[i]; 11907c4bc1f5SAnirudh Venkataramanan 11917c4bc1f5SAnirudh Venkataramanan reg = rd32(hw, VP_MDET_TX_PQM(i)); 11927c4bc1f5SAnirudh Venkataramanan if (reg & VP_MDET_TX_PQM_VALID_M) { 11937c4bc1f5SAnirudh Venkataramanan wr32(hw, VP_MDET_TX_PQM(i), 0xFFFF); 11947c4bc1f5SAnirudh Venkataramanan vf->num_mdd_events++; 11957c4bc1f5SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "TX driver issue detected on VF %d\n", 11967c4bc1f5SAnirudh Venkataramanan i); 11977c4bc1f5SAnirudh Venkataramanan } 11987c4bc1f5SAnirudh Venkataramanan 11997c4bc1f5SAnirudh Venkataramanan reg = rd32(hw, VP_MDET_TX_TCLAN(i)); 12007c4bc1f5SAnirudh Venkataramanan if (reg & VP_MDET_TX_TCLAN_VALID_M) { 12017c4bc1f5SAnirudh Venkataramanan wr32(hw, VP_MDET_TX_TCLAN(i), 0xFFFF); 12027c4bc1f5SAnirudh Venkataramanan vf->num_mdd_events++; 12037c4bc1f5SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "TX driver issue detected on VF %d\n", 12047c4bc1f5SAnirudh Venkataramanan i); 12057c4bc1f5SAnirudh Venkataramanan } 12067c4bc1f5SAnirudh Venkataramanan 12077c4bc1f5SAnirudh Venkataramanan reg = rd32(hw, VP_MDET_TX_TDPU(i)); 12087c4bc1f5SAnirudh Venkataramanan if (reg & VP_MDET_TX_TDPU_VALID_M) { 12097c4bc1f5SAnirudh Venkataramanan wr32(hw, VP_MDET_TX_TDPU(i), 0xFFFF); 12107c4bc1f5SAnirudh Venkataramanan vf->num_mdd_events++; 12117c4bc1f5SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "TX driver issue detected on VF %d\n", 12127c4bc1f5SAnirudh Venkataramanan i); 12137c4bc1f5SAnirudh Venkataramanan } 12147c4bc1f5SAnirudh Venkataramanan 12157c4bc1f5SAnirudh Venkataramanan reg = rd32(hw, VP_MDET_RX(i)); 12167c4bc1f5SAnirudh Venkataramanan if (reg & VP_MDET_RX_VALID_M) { 12177c4bc1f5SAnirudh Venkataramanan wr32(hw, VP_MDET_RX(i), 0xFFFF); 12187c4bc1f5SAnirudh Venkataramanan vf->num_mdd_events++; 12197c4bc1f5SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "RX driver issue detected on VF %d\n", 12207c4bc1f5SAnirudh Venkataramanan i); 12217c4bc1f5SAnirudh Venkataramanan } 12227c4bc1f5SAnirudh Venkataramanan 12237c4bc1f5SAnirudh Venkataramanan if (vf->num_mdd_events > ICE_DFLT_NUM_MDD_EVENTS_ALLOWED) { 12247c4bc1f5SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 12257c4bc1f5SAnirudh Venkataramanan "Too many MDD events on VF %d, disabled\n", i); 12267c4bc1f5SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 12277c4bc1f5SAnirudh Venkataramanan "Use PF Control I/F to re-enable the VF\n"); 12287c4bc1f5SAnirudh Venkataramanan set_bit(ICE_VF_STATE_DIS, vf->vf_states); 12297c4bc1f5SAnirudh Venkataramanan } 12307c4bc1f5SAnirudh Venkataramanan } 12317c4bc1f5SAnirudh Venkataramanan 1232b3969fd7SSudheer Mogilappagari /* re-enable MDD interrupt cause */ 1233b3969fd7SSudheer Mogilappagari clear_bit(__ICE_MDD_EVENT_PENDING, pf->state); 1234b3969fd7SSudheer Mogilappagari reg = rd32(hw, PFINT_OICR_ENA); 1235b3969fd7SSudheer Mogilappagari reg |= PFINT_OICR_MAL_DETECT_M; 1236b3969fd7SSudheer Mogilappagari wr32(hw, PFINT_OICR_ENA, reg); 1237b3969fd7SSudheer Mogilappagari ice_flush(hw); 1238b3969fd7SSudheer Mogilappagari } 1239b3969fd7SSudheer Mogilappagari 1240b3969fd7SSudheer Mogilappagari /** 1241940b61afSAnirudh Venkataramanan * ice_service_task - manage and run subtasks 1242940b61afSAnirudh Venkataramanan * @work: pointer to work_struct contained by the PF struct 1243940b61afSAnirudh Venkataramanan */ 1244940b61afSAnirudh Venkataramanan static void ice_service_task(struct work_struct *work) 1245940b61afSAnirudh Venkataramanan { 1246940b61afSAnirudh Venkataramanan struct ice_pf *pf = container_of(work, struct ice_pf, serv_task); 1247940b61afSAnirudh Venkataramanan unsigned long start_time = jiffies; 1248940b61afSAnirudh Venkataramanan 1249940b61afSAnirudh Venkataramanan /* subtasks */ 12500b28b702SAnirudh Venkataramanan 12510b28b702SAnirudh Venkataramanan /* process reset requests first */ 12520b28b702SAnirudh Venkataramanan ice_reset_subtask(pf); 12530b28b702SAnirudh Venkataramanan 12540f9d5027SAnirudh Venkataramanan /* bail if a reset/recovery cycle is pending or rebuild failed */ 12555df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state) || 12560f9d5027SAnirudh Venkataramanan test_bit(__ICE_SUSPENDED, pf->state) || 12570f9d5027SAnirudh Venkataramanan test_bit(__ICE_NEEDS_RESTART, pf->state)) { 12580b28b702SAnirudh Venkataramanan ice_service_task_complete(pf); 12590b28b702SAnirudh Venkataramanan return; 12600b28b702SAnirudh Venkataramanan } 12610b28b702SAnirudh Venkataramanan 1262b3969fd7SSudheer Mogilappagari ice_check_for_hang_subtask(pf); 1263e94d4478SAnirudh Venkataramanan ice_sync_fltr_subtask(pf); 1264b3969fd7SSudheer Mogilappagari ice_handle_mdd_event(pf); 1265007676b4SAnirudh Venkataramanan ice_process_vflr_event(pf); 1266fcea6f3dSAnirudh Venkataramanan ice_watchdog_subtask(pf); 1267940b61afSAnirudh Venkataramanan ice_clean_adminq_subtask(pf); 126875d2b253SAnirudh Venkataramanan ice_clean_mailboxq_subtask(pf); 1269940b61afSAnirudh Venkataramanan 1270940b61afSAnirudh Venkataramanan /* Clear __ICE_SERVICE_SCHED flag to allow scheduling next event */ 1271940b61afSAnirudh Venkataramanan ice_service_task_complete(pf); 1272940b61afSAnirudh Venkataramanan 1273940b61afSAnirudh Venkataramanan /* If the tasks have taken longer than one service timer period 1274940b61afSAnirudh Venkataramanan * or there is more work to be done, reset the service timer to 1275940b61afSAnirudh Venkataramanan * schedule the service task now. 1276940b61afSAnirudh Venkataramanan */ 1277940b61afSAnirudh Venkataramanan if (time_after(jiffies, (start_time + pf->serv_tmr_period)) || 1278b3969fd7SSudheer Mogilappagari test_bit(__ICE_MDD_EVENT_PENDING, pf->state) || 1279007676b4SAnirudh Venkataramanan test_bit(__ICE_VFLR_EVENT_PENDING, pf->state) || 128075d2b253SAnirudh Venkataramanan test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state) || 1281940b61afSAnirudh Venkataramanan test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) 1282940b61afSAnirudh Venkataramanan mod_timer(&pf->serv_tmr, jiffies); 1283940b61afSAnirudh Venkataramanan } 1284940b61afSAnirudh Venkataramanan 1285837f08fdSAnirudh Venkataramanan /** 1286f31e4b6fSAnirudh Venkataramanan * ice_set_ctrlq_len - helper function to set controlq length 1287f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW instance 1288f31e4b6fSAnirudh Venkataramanan */ 1289f31e4b6fSAnirudh Venkataramanan static void ice_set_ctrlq_len(struct ice_hw *hw) 1290f31e4b6fSAnirudh Venkataramanan { 1291f31e4b6fSAnirudh Venkataramanan hw->adminq.num_rq_entries = ICE_AQ_LEN; 1292f31e4b6fSAnirudh Venkataramanan hw->adminq.num_sq_entries = ICE_AQ_LEN; 1293f31e4b6fSAnirudh Venkataramanan hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN; 1294f31e4b6fSAnirudh Venkataramanan hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN; 129575d2b253SAnirudh Venkataramanan hw->mailboxq.num_rq_entries = ICE_MBXQ_LEN; 129675d2b253SAnirudh Venkataramanan hw->mailboxq.num_sq_entries = ICE_MBXQ_LEN; 129775d2b253SAnirudh Venkataramanan hw->mailboxq.rq_buf_size = ICE_MBXQ_MAX_BUF_LEN; 129875d2b253SAnirudh Venkataramanan hw->mailboxq.sq_buf_size = ICE_MBXQ_MAX_BUF_LEN; 1299f31e4b6fSAnirudh Venkataramanan } 1300f31e4b6fSAnirudh Venkataramanan 1301f31e4b6fSAnirudh Venkataramanan /** 1302cdedef59SAnirudh Venkataramanan * ice_irq_affinity_notify - Callback for affinity changes 1303cdedef59SAnirudh Venkataramanan * @notify: context as to what irq was changed 1304cdedef59SAnirudh Venkataramanan * @mask: the new affinity mask 1305cdedef59SAnirudh Venkataramanan * 1306cdedef59SAnirudh Venkataramanan * This is a callback function used by the irq_set_affinity_notifier function 1307cdedef59SAnirudh Venkataramanan * so that we may register to receive changes to the irq affinity masks. 1308cdedef59SAnirudh Venkataramanan */ 1309c8b7abddSBruce Allan static void 1310c8b7abddSBruce Allan ice_irq_affinity_notify(struct irq_affinity_notify *notify, 1311cdedef59SAnirudh Venkataramanan const cpumask_t *mask) 1312cdedef59SAnirudh Venkataramanan { 1313cdedef59SAnirudh Venkataramanan struct ice_q_vector *q_vector = 1314cdedef59SAnirudh Venkataramanan container_of(notify, struct ice_q_vector, affinity_notify); 1315cdedef59SAnirudh Venkataramanan 1316cdedef59SAnirudh Venkataramanan cpumask_copy(&q_vector->affinity_mask, mask); 1317cdedef59SAnirudh Venkataramanan } 1318cdedef59SAnirudh Venkataramanan 1319cdedef59SAnirudh Venkataramanan /** 1320cdedef59SAnirudh Venkataramanan * ice_irq_affinity_release - Callback for affinity notifier release 1321cdedef59SAnirudh Venkataramanan * @ref: internal core kernel usage 1322cdedef59SAnirudh Venkataramanan * 1323cdedef59SAnirudh Venkataramanan * This is a callback function used by the irq_set_affinity_notifier function 1324cdedef59SAnirudh Venkataramanan * to inform the current notification subscriber that they will no longer 1325cdedef59SAnirudh Venkataramanan * receive notifications. 1326cdedef59SAnirudh Venkataramanan */ 1327cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_release(struct kref __always_unused *ref) {} 1328cdedef59SAnirudh Venkataramanan 1329cdedef59SAnirudh Venkataramanan /** 1330cdedef59SAnirudh Venkataramanan * ice_vsi_ena_irq - Enable IRQ for the given VSI 1331cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 1332cdedef59SAnirudh Venkataramanan */ 1333cdedef59SAnirudh Venkataramanan static int ice_vsi_ena_irq(struct ice_vsi *vsi) 1334cdedef59SAnirudh Venkataramanan { 1335cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1336cdedef59SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1337cdedef59SAnirudh Venkataramanan 1338cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 1339cdedef59SAnirudh Venkataramanan int i; 1340cdedef59SAnirudh Venkataramanan 1341cdedef59SAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++) 1342cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]); 1343cdedef59SAnirudh Venkataramanan } 1344cdedef59SAnirudh Venkataramanan 1345cdedef59SAnirudh Venkataramanan ice_flush(hw); 1346cdedef59SAnirudh Venkataramanan return 0; 1347cdedef59SAnirudh Venkataramanan } 1348cdedef59SAnirudh Venkataramanan 1349cdedef59SAnirudh Venkataramanan /** 1350cdedef59SAnirudh Venkataramanan * ice_vsi_req_irq_msix - get MSI-X vectors from the OS for the VSI 1351cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 1352cdedef59SAnirudh Venkataramanan * @basename: name for the vector 1353cdedef59SAnirudh Venkataramanan */ 1354cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) 1355cdedef59SAnirudh Venkataramanan { 1356cdedef59SAnirudh Venkataramanan int q_vectors = vsi->num_q_vectors; 1357cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1358eb0208ecSPreethi Banala int base = vsi->sw_base_vector; 1359cdedef59SAnirudh Venkataramanan int rx_int_idx = 0; 1360cdedef59SAnirudh Venkataramanan int tx_int_idx = 0; 1361cdedef59SAnirudh Venkataramanan int vector, err; 1362cdedef59SAnirudh Venkataramanan int irq_num; 1363cdedef59SAnirudh Venkataramanan 1364cdedef59SAnirudh Venkataramanan for (vector = 0; vector < q_vectors; vector++) { 1365cdedef59SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[vector]; 1366cdedef59SAnirudh Venkataramanan 1367cdedef59SAnirudh Venkataramanan irq_num = pf->msix_entries[base + vector].vector; 1368cdedef59SAnirudh Venkataramanan 1369cdedef59SAnirudh Venkataramanan if (q_vector->tx.ring && q_vector->rx.ring) { 1370cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1371cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "TxRx", rx_int_idx++); 1372cdedef59SAnirudh Venkataramanan tx_int_idx++; 1373cdedef59SAnirudh Venkataramanan } else if (q_vector->rx.ring) { 1374cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1375cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "rx", rx_int_idx++); 1376cdedef59SAnirudh Venkataramanan } else if (q_vector->tx.ring) { 1377cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1378cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "tx", tx_int_idx++); 1379cdedef59SAnirudh Venkataramanan } else { 1380cdedef59SAnirudh Venkataramanan /* skip this unused q_vector */ 1381cdedef59SAnirudh Venkataramanan continue; 1382cdedef59SAnirudh Venkataramanan } 13838d051b8bSAlan Brady err = devm_request_irq(&pf->pdev->dev, irq_num, 13848d051b8bSAlan Brady vsi->irq_handler, 0, 13858d051b8bSAlan Brady q_vector->name, q_vector); 1386cdedef59SAnirudh Venkataramanan if (err) { 1387cdedef59SAnirudh Venkataramanan netdev_err(vsi->netdev, 1388cdedef59SAnirudh Venkataramanan "MSIX request_irq failed, error: %d\n", err); 1389cdedef59SAnirudh Venkataramanan goto free_q_irqs; 1390cdedef59SAnirudh Venkataramanan } 1391cdedef59SAnirudh Venkataramanan 1392cdedef59SAnirudh Venkataramanan /* register for affinity change notifications */ 1393cdedef59SAnirudh Venkataramanan q_vector->affinity_notify.notify = ice_irq_affinity_notify; 1394cdedef59SAnirudh Venkataramanan q_vector->affinity_notify.release = ice_irq_affinity_release; 1395cdedef59SAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify); 1396cdedef59SAnirudh Venkataramanan 1397cdedef59SAnirudh Venkataramanan /* assign the mask for this irq */ 1398cdedef59SAnirudh Venkataramanan irq_set_affinity_hint(irq_num, &q_vector->affinity_mask); 1399cdedef59SAnirudh Venkataramanan } 1400cdedef59SAnirudh Venkataramanan 1401cdedef59SAnirudh Venkataramanan vsi->irqs_ready = true; 1402cdedef59SAnirudh Venkataramanan return 0; 1403cdedef59SAnirudh Venkataramanan 1404cdedef59SAnirudh Venkataramanan free_q_irqs: 1405cdedef59SAnirudh Venkataramanan while (vector) { 1406cdedef59SAnirudh Venkataramanan vector--; 1407cdedef59SAnirudh Venkataramanan irq_num = pf->msix_entries[base + vector].vector, 1408cdedef59SAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 1409cdedef59SAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 1410cdedef59SAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, &vsi->q_vectors[vector]); 1411cdedef59SAnirudh Venkataramanan } 1412cdedef59SAnirudh Venkataramanan return err; 1413cdedef59SAnirudh Venkataramanan } 1414cdedef59SAnirudh Venkataramanan 1415cdedef59SAnirudh Venkataramanan /** 1416940b61afSAnirudh Venkataramanan * ice_ena_misc_vector - enable the non-queue interrupts 1417940b61afSAnirudh Venkataramanan * @pf: board private structure 1418940b61afSAnirudh Venkataramanan */ 1419940b61afSAnirudh Venkataramanan static void ice_ena_misc_vector(struct ice_pf *pf) 1420940b61afSAnirudh Venkataramanan { 1421940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1422940b61afSAnirudh Venkataramanan u32 val; 1423940b61afSAnirudh Venkataramanan 1424940b61afSAnirudh Venkataramanan /* clear things first */ 1425940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, 0); /* disable all */ 1426940b61afSAnirudh Venkataramanan rd32(hw, PFINT_OICR); /* read to clear */ 1427940b61afSAnirudh Venkataramanan 14283bcd7fa3SBruce Allan val = (PFINT_OICR_ECC_ERR_M | 1429940b61afSAnirudh Venkataramanan PFINT_OICR_MAL_DETECT_M | 1430940b61afSAnirudh Venkataramanan PFINT_OICR_GRST_M | 1431940b61afSAnirudh Venkataramanan PFINT_OICR_PCI_EXCEPTION_M | 1432007676b4SAnirudh Venkataramanan PFINT_OICR_VFLR_M | 14333bcd7fa3SBruce Allan PFINT_OICR_HMC_ERR_M | 14343bcd7fa3SBruce Allan PFINT_OICR_PE_CRITERR_M); 1435940b61afSAnirudh Venkataramanan 1436940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, val); 1437940b61afSAnirudh Venkataramanan 1438940b61afSAnirudh Venkataramanan /* SW_ITR_IDX = 0, but don't change INTENA */ 1439eb0208ecSPreethi Banala wr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx), 1440940b61afSAnirudh Venkataramanan GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); 1441940b61afSAnirudh Venkataramanan } 1442940b61afSAnirudh Venkataramanan 1443940b61afSAnirudh Venkataramanan /** 1444940b61afSAnirudh Venkataramanan * ice_misc_intr - misc interrupt handler 1445940b61afSAnirudh Venkataramanan * @irq: interrupt number 1446940b61afSAnirudh Venkataramanan * @data: pointer to a q_vector 1447940b61afSAnirudh Venkataramanan */ 1448940b61afSAnirudh Venkataramanan static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) 1449940b61afSAnirudh Venkataramanan { 1450940b61afSAnirudh Venkataramanan struct ice_pf *pf = (struct ice_pf *)data; 1451940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1452940b61afSAnirudh Venkataramanan irqreturn_t ret = IRQ_NONE; 1453940b61afSAnirudh Venkataramanan u32 oicr, ena_mask; 1454940b61afSAnirudh Venkataramanan 1455940b61afSAnirudh Venkataramanan set_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); 145675d2b253SAnirudh Venkataramanan set_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state); 1457940b61afSAnirudh Venkataramanan 1458940b61afSAnirudh Venkataramanan oicr = rd32(hw, PFINT_OICR); 1459940b61afSAnirudh Venkataramanan ena_mask = rd32(hw, PFINT_OICR_ENA); 1460940b61afSAnirudh Venkataramanan 1461b3969fd7SSudheer Mogilappagari if (oicr & PFINT_OICR_MAL_DETECT_M) { 1462b3969fd7SSudheer Mogilappagari ena_mask &= ~PFINT_OICR_MAL_DETECT_M; 1463b3969fd7SSudheer Mogilappagari set_bit(__ICE_MDD_EVENT_PENDING, pf->state); 1464b3969fd7SSudheer Mogilappagari } 1465007676b4SAnirudh Venkataramanan if (oicr & PFINT_OICR_VFLR_M) { 1466007676b4SAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_VFLR_M; 1467007676b4SAnirudh Venkataramanan set_bit(__ICE_VFLR_EVENT_PENDING, pf->state); 1468007676b4SAnirudh Venkataramanan } 1469b3969fd7SSudheer Mogilappagari 14700b28b702SAnirudh Venkataramanan if (oicr & PFINT_OICR_GRST_M) { 14710b28b702SAnirudh Venkataramanan u32 reset; 1472b3969fd7SSudheer Mogilappagari 14730b28b702SAnirudh Venkataramanan /* we have a reset warning */ 14740b28b702SAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_GRST_M; 14750b28b702SAnirudh Venkataramanan reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >> 14760b28b702SAnirudh Venkataramanan GLGEN_RSTAT_RESET_TYPE_S; 14770b28b702SAnirudh Venkataramanan 14780b28b702SAnirudh Venkataramanan if (reset == ICE_RESET_CORER) 14790b28b702SAnirudh Venkataramanan pf->corer_count++; 14800b28b702SAnirudh Venkataramanan else if (reset == ICE_RESET_GLOBR) 14810b28b702SAnirudh Venkataramanan pf->globr_count++; 1482ca4929b6SBrett Creeley else if (reset == ICE_RESET_EMPR) 14830b28b702SAnirudh Venkataramanan pf->empr_count++; 1484ca4929b6SBrett Creeley else 1485ca4929b6SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid reset type %d\n", 1486ca4929b6SBrett Creeley reset); 14870b28b702SAnirudh Venkataramanan 14880b28b702SAnirudh Venkataramanan /* If a reset cycle isn't already in progress, we set a bit in 14890b28b702SAnirudh Venkataramanan * pf->state so that the service task can start a reset/rebuild. 14900b28b702SAnirudh Venkataramanan * We also make note of which reset happened so that peer 14910b28b702SAnirudh Venkataramanan * devices/drivers can be informed. 14920b28b702SAnirudh Venkataramanan */ 14935df7e45dSDave Ertman if (!test_and_set_bit(__ICE_RESET_OICR_RECV, pf->state)) { 14940b28b702SAnirudh Venkataramanan if (reset == ICE_RESET_CORER) 14950b28b702SAnirudh Venkataramanan set_bit(__ICE_CORER_RECV, pf->state); 14960b28b702SAnirudh Venkataramanan else if (reset == ICE_RESET_GLOBR) 14970b28b702SAnirudh Venkataramanan set_bit(__ICE_GLOBR_RECV, pf->state); 14980b28b702SAnirudh Venkataramanan else 14990b28b702SAnirudh Venkataramanan set_bit(__ICE_EMPR_RECV, pf->state); 15000b28b702SAnirudh Venkataramanan 1501fd2a9817SAnirudh Venkataramanan /* There are couple of different bits at play here. 1502fd2a9817SAnirudh Venkataramanan * hw->reset_ongoing indicates whether the hardware is 1503fd2a9817SAnirudh Venkataramanan * in reset. This is set to true when a reset interrupt 1504fd2a9817SAnirudh Venkataramanan * is received and set back to false after the driver 1505fd2a9817SAnirudh Venkataramanan * has determined that the hardware is out of reset. 1506fd2a9817SAnirudh Venkataramanan * 15075df7e45dSDave Ertman * __ICE_RESET_OICR_RECV in pf->state indicates 1508fd2a9817SAnirudh Venkataramanan * that a post reset rebuild is required before the 1509fd2a9817SAnirudh Venkataramanan * driver is operational again. This is set above. 1510fd2a9817SAnirudh Venkataramanan * 1511fd2a9817SAnirudh Venkataramanan * As this is the start of the reset/rebuild cycle, set 1512fd2a9817SAnirudh Venkataramanan * both to indicate that. 1513fd2a9817SAnirudh Venkataramanan */ 1514fd2a9817SAnirudh Venkataramanan hw->reset_ongoing = true; 15150b28b702SAnirudh Venkataramanan } 15160b28b702SAnirudh Venkataramanan } 15170b28b702SAnirudh Venkataramanan 1518940b61afSAnirudh Venkataramanan if (oicr & PFINT_OICR_HMC_ERR_M) { 1519940b61afSAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_HMC_ERR_M; 1520940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 1521940b61afSAnirudh Venkataramanan "HMC Error interrupt - info 0x%x, data 0x%x\n", 1522940b61afSAnirudh Venkataramanan rd32(hw, PFHMC_ERRORINFO), 1523940b61afSAnirudh Venkataramanan rd32(hw, PFHMC_ERRORDATA)); 1524940b61afSAnirudh Venkataramanan } 1525940b61afSAnirudh Venkataramanan 1526940b61afSAnirudh Venkataramanan /* Report and mask off any remaining unexpected interrupts */ 1527940b61afSAnirudh Venkataramanan oicr &= ena_mask; 1528940b61afSAnirudh Venkataramanan if (oicr) { 1529940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "unhandled interrupt oicr=0x%08x\n", 1530940b61afSAnirudh Venkataramanan oicr); 1531940b61afSAnirudh Venkataramanan /* If a critical error is pending there is no choice but to 1532940b61afSAnirudh Venkataramanan * reset the device. 1533940b61afSAnirudh Venkataramanan */ 1534940b61afSAnirudh Venkataramanan if (oicr & (PFINT_OICR_PE_CRITERR_M | 1535940b61afSAnirudh Venkataramanan PFINT_OICR_PCI_EXCEPTION_M | 15360b28b702SAnirudh Venkataramanan PFINT_OICR_ECC_ERR_M)) { 1537940b61afSAnirudh Venkataramanan set_bit(__ICE_PFR_REQ, pf->state); 15380b28b702SAnirudh Venkataramanan ice_service_task_schedule(pf); 15390b28b702SAnirudh Venkataramanan } 1540940b61afSAnirudh Venkataramanan ena_mask &= ~oicr; 1541940b61afSAnirudh Venkataramanan } 1542940b61afSAnirudh Venkataramanan ret = IRQ_HANDLED; 1543940b61afSAnirudh Venkataramanan 1544940b61afSAnirudh Venkataramanan /* re-enable interrupt causes that are not handled during this pass */ 1545940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, ena_mask); 1546940b61afSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) { 1547940b61afSAnirudh Venkataramanan ice_service_task_schedule(pf); 1548cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, NULL, NULL); 1549940b61afSAnirudh Venkataramanan } 1550940b61afSAnirudh Venkataramanan 1551940b61afSAnirudh Venkataramanan return ret; 1552940b61afSAnirudh Venkataramanan } 1553940b61afSAnirudh Venkataramanan 1554940b61afSAnirudh Venkataramanan /** 15550e04e8e1SBrett Creeley * ice_dis_ctrlq_interrupts - disable control queue interrupts 15560e04e8e1SBrett Creeley * @hw: pointer to HW structure 15570e04e8e1SBrett Creeley */ 15580e04e8e1SBrett Creeley static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) 15590e04e8e1SBrett Creeley { 15600e04e8e1SBrett Creeley /* disable Admin queue Interrupt causes */ 15610e04e8e1SBrett Creeley wr32(hw, PFINT_FW_CTL, 15620e04e8e1SBrett Creeley rd32(hw, PFINT_FW_CTL) & ~PFINT_FW_CTL_CAUSE_ENA_M); 15630e04e8e1SBrett Creeley 15640e04e8e1SBrett Creeley /* disable Mailbox queue Interrupt causes */ 15650e04e8e1SBrett Creeley wr32(hw, PFINT_MBX_CTL, 15660e04e8e1SBrett Creeley rd32(hw, PFINT_MBX_CTL) & ~PFINT_MBX_CTL_CAUSE_ENA_M); 15670e04e8e1SBrett Creeley 15680e04e8e1SBrett Creeley /* disable Control queue Interrupt causes */ 15690e04e8e1SBrett Creeley wr32(hw, PFINT_OICR_CTL, 15700e04e8e1SBrett Creeley rd32(hw, PFINT_OICR_CTL) & ~PFINT_OICR_CTL_CAUSE_ENA_M); 15710e04e8e1SBrett Creeley 15720e04e8e1SBrett Creeley ice_flush(hw); 15730e04e8e1SBrett Creeley } 15740e04e8e1SBrett Creeley 15750e04e8e1SBrett Creeley /** 1576940b61afSAnirudh Venkataramanan * ice_free_irq_msix_misc - Unroll misc vector setup 1577940b61afSAnirudh Venkataramanan * @pf: board private structure 1578940b61afSAnirudh Venkataramanan */ 1579940b61afSAnirudh Venkataramanan static void ice_free_irq_msix_misc(struct ice_pf *pf) 1580940b61afSAnirudh Venkataramanan { 15810e04e8e1SBrett Creeley struct ice_hw *hw = &pf->hw; 15820e04e8e1SBrett Creeley 15830e04e8e1SBrett Creeley ice_dis_ctrlq_interrupts(hw); 15840e04e8e1SBrett Creeley 1585940b61afSAnirudh Venkataramanan /* disable OICR interrupt */ 15860e04e8e1SBrett Creeley wr32(hw, PFINT_OICR_ENA, 0); 15870e04e8e1SBrett Creeley ice_flush(hw); 1588940b61afSAnirudh Venkataramanan 1589940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { 1590eb0208ecSPreethi Banala synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector); 1591940b61afSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, 1592eb0208ecSPreethi Banala pf->msix_entries[pf->sw_oicr_idx].vector, pf); 1593940b61afSAnirudh Venkataramanan } 1594940b61afSAnirudh Venkataramanan 1595eb0208ecSPreethi Banala pf->num_avail_sw_msix += 1; 1596eb0208ecSPreethi Banala ice_free_res(pf->sw_irq_tracker, pf->sw_oicr_idx, ICE_RES_MISC_VEC_ID); 1597eb0208ecSPreethi Banala pf->num_avail_hw_msix += 1; 1598eb0208ecSPreethi Banala ice_free_res(pf->hw_irq_tracker, pf->hw_oicr_idx, ICE_RES_MISC_VEC_ID); 1599940b61afSAnirudh Venkataramanan } 1600940b61afSAnirudh Venkataramanan 1601940b61afSAnirudh Venkataramanan /** 16020e04e8e1SBrett Creeley * ice_ena_ctrlq_interrupts - enable control queue interrupts 16030e04e8e1SBrett Creeley * @hw: pointer to HW structure 16040e04e8e1SBrett Creeley * @v_idx: HW vector index to associate the control queue interrupts with 16050e04e8e1SBrett Creeley */ 16060e04e8e1SBrett Creeley static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 v_idx) 16070e04e8e1SBrett Creeley { 16080e04e8e1SBrett Creeley u32 val; 16090e04e8e1SBrett Creeley 16100e04e8e1SBrett Creeley val = ((v_idx & PFINT_OICR_CTL_MSIX_INDX_M) | 16110e04e8e1SBrett Creeley PFINT_OICR_CTL_CAUSE_ENA_M); 16120e04e8e1SBrett Creeley wr32(hw, PFINT_OICR_CTL, val); 16130e04e8e1SBrett Creeley 16140e04e8e1SBrett Creeley /* enable Admin queue Interrupt causes */ 16150e04e8e1SBrett Creeley val = ((v_idx & PFINT_FW_CTL_MSIX_INDX_M) | 16160e04e8e1SBrett Creeley PFINT_FW_CTL_CAUSE_ENA_M); 16170e04e8e1SBrett Creeley wr32(hw, PFINT_FW_CTL, val); 16180e04e8e1SBrett Creeley 16190e04e8e1SBrett Creeley /* enable Mailbox queue Interrupt causes */ 16200e04e8e1SBrett Creeley val = ((v_idx & PFINT_MBX_CTL_MSIX_INDX_M) | 16210e04e8e1SBrett Creeley PFINT_MBX_CTL_CAUSE_ENA_M); 16220e04e8e1SBrett Creeley wr32(hw, PFINT_MBX_CTL, val); 16230e04e8e1SBrett Creeley 16240e04e8e1SBrett Creeley ice_flush(hw); 16250e04e8e1SBrett Creeley } 16260e04e8e1SBrett Creeley 16270e04e8e1SBrett Creeley /** 1628940b61afSAnirudh Venkataramanan * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events 1629940b61afSAnirudh Venkataramanan * @pf: board private structure 1630940b61afSAnirudh Venkataramanan * 1631940b61afSAnirudh Venkataramanan * This sets up the handler for MSIX 0, which is used to manage the 1632940b61afSAnirudh Venkataramanan * non-queue interrupts, e.g. AdminQ and errors. This is not used 1633940b61afSAnirudh Venkataramanan * when in MSI or Legacy interrupt mode. 1634940b61afSAnirudh Venkataramanan */ 1635940b61afSAnirudh Venkataramanan static int ice_req_irq_msix_misc(struct ice_pf *pf) 1636940b61afSAnirudh Venkataramanan { 1637940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1638940b61afSAnirudh Venkataramanan int oicr_idx, err = 0; 1639940b61afSAnirudh Venkataramanan 1640940b61afSAnirudh Venkataramanan if (!pf->int_name[0]) 1641940b61afSAnirudh Venkataramanan snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", 1642940b61afSAnirudh Venkataramanan dev_driver_string(&pf->pdev->dev), 1643940b61afSAnirudh Venkataramanan dev_name(&pf->pdev->dev)); 1644940b61afSAnirudh Venkataramanan 16450b28b702SAnirudh Venkataramanan /* Do not request IRQ but do enable OICR interrupt since settings are 16460b28b702SAnirudh Venkataramanan * lost during reset. Note that this function is called only during 16470b28b702SAnirudh Venkataramanan * rebuild path and not while reset is in progress. 16480b28b702SAnirudh Venkataramanan */ 16495df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) 16500b28b702SAnirudh Venkataramanan goto skip_req_irq; 16510b28b702SAnirudh Venkataramanan 1652eb0208ecSPreethi Banala /* reserve one vector in sw_irq_tracker for misc interrupts */ 1653eb0208ecSPreethi Banala oicr_idx = ice_get_res(pf, pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1654940b61afSAnirudh Venkataramanan if (oicr_idx < 0) 1655940b61afSAnirudh Venkataramanan return oicr_idx; 1656940b61afSAnirudh Venkataramanan 1657eb0208ecSPreethi Banala pf->num_avail_sw_msix -= 1; 1658eb0208ecSPreethi Banala pf->sw_oicr_idx = oicr_idx; 1659eb0208ecSPreethi Banala 1660eb0208ecSPreethi Banala /* reserve one vector in hw_irq_tracker for misc interrupts */ 1661eb0208ecSPreethi Banala oicr_idx = ice_get_res(pf, pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1662eb0208ecSPreethi Banala if (oicr_idx < 0) { 1663eb0208ecSPreethi Banala ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1664eb0208ecSPreethi Banala pf->num_avail_sw_msix += 1; 1665eb0208ecSPreethi Banala return oicr_idx; 1666eb0208ecSPreethi Banala } 1667eb0208ecSPreethi Banala pf->num_avail_hw_msix -= 1; 1668eb0208ecSPreethi Banala pf->hw_oicr_idx = oicr_idx; 1669940b61afSAnirudh Venkataramanan 1670940b61afSAnirudh Venkataramanan err = devm_request_irq(&pf->pdev->dev, 1671eb0208ecSPreethi Banala pf->msix_entries[pf->sw_oicr_idx].vector, 1672940b61afSAnirudh Venkataramanan ice_misc_intr, 0, pf->int_name, pf); 1673940b61afSAnirudh Venkataramanan if (err) { 1674940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1675940b61afSAnirudh Venkataramanan "devm_request_irq for %s failed: %d\n", 1676940b61afSAnirudh Venkataramanan pf->int_name, err); 1677eb0208ecSPreethi Banala ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1678eb0208ecSPreethi Banala pf->num_avail_sw_msix += 1; 1679eb0208ecSPreethi Banala ice_free_res(pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1680eb0208ecSPreethi Banala pf->num_avail_hw_msix += 1; 1681940b61afSAnirudh Venkataramanan return err; 1682940b61afSAnirudh Venkataramanan } 1683940b61afSAnirudh Venkataramanan 16840b28b702SAnirudh Venkataramanan skip_req_irq: 1685940b61afSAnirudh Venkataramanan ice_ena_misc_vector(pf); 1686940b61afSAnirudh Venkataramanan 16870e04e8e1SBrett Creeley ice_ena_ctrlq_interrupts(hw, pf->hw_oicr_idx); 1688eb0208ecSPreethi Banala wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), 168963f545edSBrett Creeley ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); 1690940b61afSAnirudh Venkataramanan 1691940b61afSAnirudh Venkataramanan ice_flush(hw); 1692cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, NULL, NULL); 1693940b61afSAnirudh Venkataramanan 1694940b61afSAnirudh Venkataramanan return 0; 1695940b61afSAnirudh Venkataramanan } 1696940b61afSAnirudh Venkataramanan 1697940b61afSAnirudh Venkataramanan /** 1698df0f8479SAnirudh Venkataramanan * ice_napi_del - Remove NAPI handler for the VSI 1699df0f8479SAnirudh Venkataramanan * @vsi: VSI for which NAPI handler is to be removed 17003a858ba3SAnirudh Venkataramanan */ 170125525b69SDave Ertman void ice_napi_del(struct ice_vsi *vsi) 17023a858ba3SAnirudh Venkataramanan { 17033a858ba3SAnirudh Venkataramanan int v_idx; 17043a858ba3SAnirudh Venkataramanan 1705df0f8479SAnirudh Venkataramanan if (!vsi->netdev) 1706df0f8479SAnirudh Venkataramanan return; 1707df0f8479SAnirudh Venkataramanan 17083a858ba3SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1709df0f8479SAnirudh Venkataramanan netif_napi_del(&vsi->q_vectors[v_idx]->napi); 17103a858ba3SAnirudh Venkataramanan } 17113a858ba3SAnirudh Venkataramanan 17123a858ba3SAnirudh Venkataramanan /** 1713df0f8479SAnirudh Venkataramanan * ice_napi_add - register NAPI handler for the VSI 1714df0f8479SAnirudh Venkataramanan * @vsi: VSI for which NAPI handler is to be registered 1715df0f8479SAnirudh Venkataramanan * 1716df0f8479SAnirudh Venkataramanan * This function is only called in the driver's load path. Registering the NAPI 1717df0f8479SAnirudh Venkataramanan * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume, 1718df0f8479SAnirudh Venkataramanan * reset/rebuild, etc.) 1719df0f8479SAnirudh Venkataramanan */ 1720df0f8479SAnirudh Venkataramanan static void ice_napi_add(struct ice_vsi *vsi) 1721df0f8479SAnirudh Venkataramanan { 1722df0f8479SAnirudh Venkataramanan int v_idx; 1723df0f8479SAnirudh Venkataramanan 1724df0f8479SAnirudh Venkataramanan if (!vsi->netdev) 1725df0f8479SAnirudh Venkataramanan return; 1726df0f8479SAnirudh Venkataramanan 1727df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1728df0f8479SAnirudh Venkataramanan netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi, 1729df0f8479SAnirudh Venkataramanan ice_napi_poll, NAPI_POLL_WEIGHT); 1730df0f8479SAnirudh Venkataramanan } 1731df0f8479SAnirudh Venkataramanan 1732df0f8479SAnirudh Venkataramanan /** 1733df0f8479SAnirudh Venkataramanan * ice_cfg_netdev - Allocate, configure and register a netdev 1734df0f8479SAnirudh Venkataramanan * @vsi: the VSI associated with the new netdev 17353a858ba3SAnirudh Venkataramanan * 17363a858ba3SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 17373a858ba3SAnirudh Venkataramanan */ 17383a858ba3SAnirudh Venkataramanan static int ice_cfg_netdev(struct ice_vsi *vsi) 17393a858ba3SAnirudh Venkataramanan { 1740d76a60baSAnirudh Venkataramanan netdev_features_t csumo_features; 1741d76a60baSAnirudh Venkataramanan netdev_features_t vlano_features; 1742d76a60baSAnirudh Venkataramanan netdev_features_t dflt_features; 1743d76a60baSAnirudh Venkataramanan netdev_features_t tso_features; 17443a858ba3SAnirudh Venkataramanan struct ice_netdev_priv *np; 17453a858ba3SAnirudh Venkataramanan struct net_device *netdev; 17463a858ba3SAnirudh Venkataramanan u8 mac_addr[ETH_ALEN]; 1747df0f8479SAnirudh Venkataramanan int err; 17483a858ba3SAnirudh Venkataramanan 1749c6dfd690SBruce Allan netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq, 1750c6dfd690SBruce Allan vsi->alloc_rxq); 17513a858ba3SAnirudh Venkataramanan if (!netdev) 17523a858ba3SAnirudh Venkataramanan return -ENOMEM; 17533a858ba3SAnirudh Venkataramanan 17543a858ba3SAnirudh Venkataramanan vsi->netdev = netdev; 17553a858ba3SAnirudh Venkataramanan np = netdev_priv(netdev); 17563a858ba3SAnirudh Venkataramanan np->vsi = vsi; 17573a858ba3SAnirudh Venkataramanan 1758d76a60baSAnirudh Venkataramanan dflt_features = NETIF_F_SG | 17593a858ba3SAnirudh Venkataramanan NETIF_F_HIGHDMA | 17603a858ba3SAnirudh Venkataramanan NETIF_F_RXHASH; 17613a858ba3SAnirudh Venkataramanan 1762d76a60baSAnirudh Venkataramanan csumo_features = NETIF_F_RXCSUM | 1763d76a60baSAnirudh Venkataramanan NETIF_F_IP_CSUM | 1764cf909e19SAnirudh Venkataramanan NETIF_F_SCTP_CRC | 1765d76a60baSAnirudh Venkataramanan NETIF_F_IPV6_CSUM; 1766d76a60baSAnirudh Venkataramanan 1767d76a60baSAnirudh Venkataramanan vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER | 1768d76a60baSAnirudh Venkataramanan NETIF_F_HW_VLAN_CTAG_TX | 1769d76a60baSAnirudh Venkataramanan NETIF_F_HW_VLAN_CTAG_RX; 1770d76a60baSAnirudh Venkataramanan 1771d76a60baSAnirudh Venkataramanan tso_features = NETIF_F_TSO; 1772d76a60baSAnirudh Venkataramanan 1773d76a60baSAnirudh Venkataramanan /* set features that user can change */ 1774d76a60baSAnirudh Venkataramanan netdev->hw_features = dflt_features | csumo_features | 1775d76a60baSAnirudh Venkataramanan vlano_features | tso_features; 1776d76a60baSAnirudh Venkataramanan 17773a858ba3SAnirudh Venkataramanan /* enable features */ 17783a858ba3SAnirudh Venkataramanan netdev->features |= netdev->hw_features; 1779d76a60baSAnirudh Venkataramanan /* encap and VLAN devices inherit default, csumo and tso features */ 1780d76a60baSAnirudh Venkataramanan netdev->hw_enc_features |= dflt_features | csumo_features | 1781d76a60baSAnirudh Venkataramanan tso_features; 1782d76a60baSAnirudh Venkataramanan netdev->vlan_features |= dflt_features | csumo_features | 1783d76a60baSAnirudh Venkataramanan tso_features; 17843a858ba3SAnirudh Venkataramanan 17853a858ba3SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 17863a858ba3SAnirudh Venkataramanan SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev); 17873a858ba3SAnirudh Venkataramanan ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr); 17883a858ba3SAnirudh Venkataramanan 17893a858ba3SAnirudh Venkataramanan ether_addr_copy(netdev->dev_addr, mac_addr); 17903a858ba3SAnirudh Venkataramanan ether_addr_copy(netdev->perm_addr, mac_addr); 17913a858ba3SAnirudh Venkataramanan } 17923a858ba3SAnirudh Venkataramanan 17933a858ba3SAnirudh Venkataramanan netdev->priv_flags |= IFF_UNICAST_FLT; 17943a858ba3SAnirudh Venkataramanan 1795cdedef59SAnirudh Venkataramanan /* assign netdev_ops */ 1796cdedef59SAnirudh Venkataramanan netdev->netdev_ops = &ice_netdev_ops; 1797cdedef59SAnirudh Venkataramanan 17983a858ba3SAnirudh Venkataramanan /* setup watchdog timeout value to be 5 second */ 17993a858ba3SAnirudh Venkataramanan netdev->watchdog_timeo = 5 * HZ; 18003a858ba3SAnirudh Venkataramanan 1801fcea6f3dSAnirudh Venkataramanan ice_set_ethtool_ops(netdev); 1802fcea6f3dSAnirudh Venkataramanan 18033a858ba3SAnirudh Venkataramanan netdev->min_mtu = ETH_MIN_MTU; 18043a858ba3SAnirudh Venkataramanan netdev->max_mtu = ICE_MAX_MTU; 18053a858ba3SAnirudh Venkataramanan 1806df0f8479SAnirudh Venkataramanan err = register_netdev(vsi->netdev); 18073a858ba3SAnirudh Venkataramanan if (err) 18083a858ba3SAnirudh Venkataramanan return err; 18093a858ba3SAnirudh Venkataramanan 1810df0f8479SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 18113a858ba3SAnirudh Venkataramanan 1812df0f8479SAnirudh Venkataramanan /* make sure transmit queues start off as stopped */ 1813df0f8479SAnirudh Venkataramanan netif_tx_stop_all_queues(vsi->netdev); 18143a858ba3SAnirudh Venkataramanan 18153a858ba3SAnirudh Venkataramanan return 0; 18163a858ba3SAnirudh Venkataramanan } 18173a858ba3SAnirudh Venkataramanan 18183a858ba3SAnirudh Venkataramanan /** 1819d76a60baSAnirudh Venkataramanan * ice_fill_rss_lut - Fill the RSS lookup table with default values 1820d76a60baSAnirudh Venkataramanan * @lut: Lookup table 1821d76a60baSAnirudh Venkataramanan * @rss_table_size: Lookup table size 1822d76a60baSAnirudh Venkataramanan * @rss_size: Range of queue number for hashing 1823d76a60baSAnirudh Venkataramanan */ 1824d76a60baSAnirudh Venkataramanan void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size) 1825d76a60baSAnirudh Venkataramanan { 1826d76a60baSAnirudh Venkataramanan u16 i; 1827d76a60baSAnirudh Venkataramanan 1828d76a60baSAnirudh Venkataramanan for (i = 0; i < rss_table_size; i++) 1829d76a60baSAnirudh Venkataramanan lut[i] = i % rss_size; 1830d76a60baSAnirudh Venkataramanan } 1831d76a60baSAnirudh Venkataramanan 1832d76a60baSAnirudh Venkataramanan /** 18330f9d5027SAnirudh Venkataramanan * ice_pf_vsi_setup - Set up a PF VSI 18340f9d5027SAnirudh Venkataramanan * @pf: board private structure 18350f9d5027SAnirudh Venkataramanan * @pi: pointer to the port_info instance 18360f9d5027SAnirudh Venkataramanan * 18370f9d5027SAnirudh Venkataramanan * Returns pointer to the successfully allocated VSI sw struct on success, 18380f9d5027SAnirudh Venkataramanan * otherwise returns NULL on failure. 18390f9d5027SAnirudh Venkataramanan */ 18400f9d5027SAnirudh Venkataramanan static struct ice_vsi * 18410f9d5027SAnirudh Venkataramanan ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi) 18420f9d5027SAnirudh Venkataramanan { 18430f9d5027SAnirudh Venkataramanan return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID); 18440f9d5027SAnirudh Venkataramanan } 18450f9d5027SAnirudh Venkataramanan 18460f9d5027SAnirudh Venkataramanan /** 1847f9867df6SAnirudh Venkataramanan * ice_vlan_rx_add_vid - Add a VLAN ID filter to HW offload 1848d76a60baSAnirudh Venkataramanan * @netdev: network interface to be adjusted 1849d76a60baSAnirudh Venkataramanan * @proto: unused protocol 1850f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be added 1851d76a60baSAnirudh Venkataramanan * 1852f9867df6SAnirudh Venkataramanan * net_device_ops implementation for adding VLAN IDs 1853d76a60baSAnirudh Venkataramanan */ 1854c8b7abddSBruce Allan static int 1855c8b7abddSBruce Allan ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto, 1856c8b7abddSBruce Allan u16 vid) 1857d76a60baSAnirudh Venkataramanan { 1858d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1859d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 18605eda8afdSAkeem G Abodunrin int ret; 1861d76a60baSAnirudh Venkataramanan 1862d76a60baSAnirudh Venkataramanan if (vid >= VLAN_N_VID) { 1863d76a60baSAnirudh Venkataramanan netdev_err(netdev, "VLAN id requested %d is out of range %d\n", 1864d76a60baSAnirudh Venkataramanan vid, VLAN_N_VID); 1865d76a60baSAnirudh Venkataramanan return -EINVAL; 1866d76a60baSAnirudh Venkataramanan } 1867d76a60baSAnirudh Venkataramanan 1868d76a60baSAnirudh Venkataramanan if (vsi->info.pvid) 1869d76a60baSAnirudh Venkataramanan return -EINVAL; 1870d76a60baSAnirudh Venkataramanan 18714f74dcc1SBrett Creeley /* Enable VLAN pruning when VLAN 0 is added */ 18724f74dcc1SBrett Creeley if (unlikely(!vid)) { 18735eda8afdSAkeem G Abodunrin ret = ice_cfg_vlan_pruning(vsi, true, false); 18744f74dcc1SBrett Creeley if (ret) 18754f74dcc1SBrett Creeley return ret; 18764f74dcc1SBrett Creeley } 18774f74dcc1SBrett Creeley 1878f9867df6SAnirudh Venkataramanan /* Add all VLAN IDs including 0 to the switch filter. VLAN ID 0 is 1879d76a60baSAnirudh Venkataramanan * needed to continue allowing all untagged packets since VLAN prune 1880d76a60baSAnirudh Venkataramanan * list is applied to all packets by the switch 1881d76a60baSAnirudh Venkataramanan */ 18825eda8afdSAkeem G Abodunrin ret = ice_vsi_add_vlan(vsi, vid); 18835eda8afdSAkeem G Abodunrin if (!ret) { 18845eda8afdSAkeem G Abodunrin vsi->vlan_ena = true; 18855eda8afdSAkeem G Abodunrin set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 18865eda8afdSAkeem G Abodunrin } 18875eda8afdSAkeem G Abodunrin 18885eda8afdSAkeem G Abodunrin return ret; 1889d76a60baSAnirudh Venkataramanan } 1890d76a60baSAnirudh Venkataramanan 1891d76a60baSAnirudh Venkataramanan /** 1892f9867df6SAnirudh Venkataramanan * ice_vlan_rx_kill_vid - Remove a VLAN ID filter from HW offload 1893d76a60baSAnirudh Venkataramanan * @netdev: network interface to be adjusted 1894d76a60baSAnirudh Venkataramanan * @proto: unused protocol 1895f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be removed 1896d76a60baSAnirudh Venkataramanan * 1897f9867df6SAnirudh Venkataramanan * net_device_ops implementation for removing VLAN IDs 1898d76a60baSAnirudh Venkataramanan */ 1899c8b7abddSBruce Allan static int 1900c8b7abddSBruce Allan ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto, 1901c8b7abddSBruce Allan u16 vid) 1902d76a60baSAnirudh Venkataramanan { 1903d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1904d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 19055eda8afdSAkeem G Abodunrin int ret; 1906d76a60baSAnirudh Venkataramanan 1907d76a60baSAnirudh Venkataramanan if (vsi->info.pvid) 1908d76a60baSAnirudh Venkataramanan return -EINVAL; 1909d76a60baSAnirudh Venkataramanan 19104f74dcc1SBrett Creeley /* Make sure ice_vsi_kill_vlan is successful before updating VLAN 19114f74dcc1SBrett Creeley * information 1912d76a60baSAnirudh Venkataramanan */ 19135eda8afdSAkeem G Abodunrin ret = ice_vsi_kill_vlan(vsi, vid); 19145eda8afdSAkeem G Abodunrin if (ret) 19155eda8afdSAkeem G Abodunrin return ret; 1916d76a60baSAnirudh Venkataramanan 19174f74dcc1SBrett Creeley /* Disable VLAN pruning when VLAN 0 is removed */ 19184f74dcc1SBrett Creeley if (unlikely(!vid)) 19195eda8afdSAkeem G Abodunrin ret = ice_cfg_vlan_pruning(vsi, false, false); 19204f74dcc1SBrett Creeley 19215eda8afdSAkeem G Abodunrin vsi->vlan_ena = false; 19225eda8afdSAkeem G Abodunrin set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 19235eda8afdSAkeem G Abodunrin return ret; 1924d76a60baSAnirudh Venkataramanan } 1925d76a60baSAnirudh Venkataramanan 1926d76a60baSAnirudh Venkataramanan /** 19273a858ba3SAnirudh Venkataramanan * ice_setup_pf_sw - Setup the HW switch on startup or after reset 19283a858ba3SAnirudh Venkataramanan * @pf: board private structure 19293a858ba3SAnirudh Venkataramanan * 19303a858ba3SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 19313a858ba3SAnirudh Venkataramanan */ 19323a858ba3SAnirudh Venkataramanan static int ice_setup_pf_sw(struct ice_pf *pf) 19333a858ba3SAnirudh Venkataramanan { 19349daf8208SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 19359daf8208SAnirudh Venkataramanan u8 broadcast[ETH_ALEN]; 19363a858ba3SAnirudh Venkataramanan struct ice_vsi *vsi; 19373a858ba3SAnirudh Venkataramanan int status = 0; 19383a858ba3SAnirudh Venkataramanan 19395df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) 19400f9d5027SAnirudh Venkataramanan return -EBUSY; 19410f9d5027SAnirudh Venkataramanan 19420f9d5027SAnirudh Venkataramanan vsi = ice_pf_vsi_setup(pf, pf->hw.port_info); 19433a858ba3SAnirudh Venkataramanan if (!vsi) { 19443a858ba3SAnirudh Venkataramanan status = -ENOMEM; 19450f9d5027SAnirudh Venkataramanan goto unroll_vsi_setup; 19460b28b702SAnirudh Venkataramanan } 19473a858ba3SAnirudh Venkataramanan 1948df0f8479SAnirudh Venkataramanan status = ice_cfg_netdev(vsi); 1949df0f8479SAnirudh Venkataramanan if (status) { 1950df0f8479SAnirudh Venkataramanan status = -ENODEV; 1951df0f8479SAnirudh Venkataramanan goto unroll_vsi_setup; 1952df0f8479SAnirudh Venkataramanan } 1953df0f8479SAnirudh Venkataramanan 1954df0f8479SAnirudh Venkataramanan /* registering the NAPI handler requires both the queues and 1955df0f8479SAnirudh Venkataramanan * netdev to be created, which are done in ice_pf_vsi_setup() 1956df0f8479SAnirudh Venkataramanan * and ice_cfg_netdev() respectively 1957df0f8479SAnirudh Venkataramanan */ 1958df0f8479SAnirudh Venkataramanan ice_napi_add(vsi); 1959df0f8479SAnirudh Venkataramanan 19600f9d5027SAnirudh Venkataramanan /* To add a MAC filter, first add the MAC to a list and then 19610f9d5027SAnirudh Venkataramanan * pass the list to ice_add_mac. 19629daf8208SAnirudh Venkataramanan */ 19630f9d5027SAnirudh Venkataramanan 19640f9d5027SAnirudh Venkataramanan /* Add a unicast MAC filter so the VSI can get its packets */ 19659daf8208SAnirudh Venkataramanan status = ice_add_mac_to_list(vsi, &tmp_add_list, 19669daf8208SAnirudh Venkataramanan vsi->port_info->mac.perm_addr); 19679daf8208SAnirudh Venkataramanan if (status) 1968df0f8479SAnirudh Venkataramanan goto unroll_napi_add; 19699daf8208SAnirudh Venkataramanan 19709daf8208SAnirudh Venkataramanan /* VSI needs to receive broadcast traffic, so add the broadcast 19710f9d5027SAnirudh Venkataramanan * MAC address to the list as well. 19729daf8208SAnirudh Venkataramanan */ 19739daf8208SAnirudh Venkataramanan eth_broadcast_addr(broadcast); 19749daf8208SAnirudh Venkataramanan status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast); 19759daf8208SAnirudh Venkataramanan if (status) 19760f9d5027SAnirudh Venkataramanan goto free_mac_list; 19779daf8208SAnirudh Venkataramanan 19789daf8208SAnirudh Venkataramanan /* program MAC filters for entries in tmp_add_list */ 19799daf8208SAnirudh Venkataramanan status = ice_add_mac(&pf->hw, &tmp_add_list); 19809daf8208SAnirudh Venkataramanan if (status) { 19819daf8208SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Could not add MAC filters\n"); 19829daf8208SAnirudh Venkataramanan status = -ENOMEM; 19830f9d5027SAnirudh Venkataramanan goto free_mac_list; 19849daf8208SAnirudh Venkataramanan } 19859daf8208SAnirudh Venkataramanan 19869daf8208SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 19879daf8208SAnirudh Venkataramanan return status; 19889daf8208SAnirudh Venkataramanan 19890f9d5027SAnirudh Venkataramanan free_mac_list: 19909daf8208SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 19919daf8208SAnirudh Venkataramanan 1992df0f8479SAnirudh Venkataramanan unroll_napi_add: 19933a858ba3SAnirudh Venkataramanan if (vsi) { 1994df0f8479SAnirudh Venkataramanan ice_napi_del(vsi); 19953a858ba3SAnirudh Venkataramanan if (vsi->netdev) { 1996df0f8479SAnirudh Venkataramanan if (vsi->netdev->reg_state == NETREG_REGISTERED) 1997df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 19983a858ba3SAnirudh Venkataramanan free_netdev(vsi->netdev); 19993a858ba3SAnirudh Venkataramanan vsi->netdev = NULL; 20003a858ba3SAnirudh Venkataramanan } 2001df0f8479SAnirudh Venkataramanan } 20029daf8208SAnirudh Venkataramanan 2003df0f8479SAnirudh Venkataramanan unroll_vsi_setup: 2004df0f8479SAnirudh Venkataramanan if (vsi) { 2005df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 20063a858ba3SAnirudh Venkataramanan ice_vsi_delete(vsi); 20073a858ba3SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 20083a858ba3SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 20093a858ba3SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 20103a858ba3SAnirudh Venkataramanan ice_vsi_clear(vsi); 20113a858ba3SAnirudh Venkataramanan } 20123a858ba3SAnirudh Venkataramanan return status; 20133a858ba3SAnirudh Venkataramanan } 20143a858ba3SAnirudh Venkataramanan 20153a858ba3SAnirudh Venkataramanan /** 2016940b61afSAnirudh Venkataramanan * ice_determine_q_usage - Calculate queue distribution 2017940b61afSAnirudh Venkataramanan * @pf: board private structure 2018940b61afSAnirudh Venkataramanan * 2019940b61afSAnirudh Venkataramanan * Return -ENOMEM if we don't get enough queues for all ports 2020940b61afSAnirudh Venkataramanan */ 2021940b61afSAnirudh Venkataramanan static void ice_determine_q_usage(struct ice_pf *pf) 2022940b61afSAnirudh Venkataramanan { 2023940b61afSAnirudh Venkataramanan u16 q_left_tx, q_left_rx; 2024940b61afSAnirudh Venkataramanan 2025940b61afSAnirudh Venkataramanan q_left_tx = pf->hw.func_caps.common_cap.num_txq; 2026940b61afSAnirudh Venkataramanan q_left_rx = pf->hw.func_caps.common_cap.num_rxq; 2027940b61afSAnirudh Venkataramanan 20285513b920SAnirudh Venkataramanan pf->num_lan_tx = min_t(int, q_left_tx, num_online_cpus()); 2029d76a60baSAnirudh Venkataramanan 2030d337f2afSAnirudh Venkataramanan /* only 1 Rx queue unless RSS is enabled */ 2031d76a60baSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 2032940b61afSAnirudh Venkataramanan pf->num_lan_rx = 1; 2033d76a60baSAnirudh Venkataramanan else 2034d76a60baSAnirudh Venkataramanan pf->num_lan_rx = min_t(int, q_left_rx, num_online_cpus()); 2035940b61afSAnirudh Venkataramanan 2036940b61afSAnirudh Venkataramanan pf->q_left_tx = q_left_tx - pf->num_lan_tx; 2037940b61afSAnirudh Venkataramanan pf->q_left_rx = q_left_rx - pf->num_lan_rx; 2038940b61afSAnirudh Venkataramanan } 2039940b61afSAnirudh Venkataramanan 2040940b61afSAnirudh Venkataramanan /** 2041940b61afSAnirudh Venkataramanan * ice_deinit_pf - Unrolls initialziations done by ice_init_pf 2042940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 2043940b61afSAnirudh Venkataramanan */ 2044940b61afSAnirudh Venkataramanan static void ice_deinit_pf(struct ice_pf *pf) 2045940b61afSAnirudh Venkataramanan { 20468d81fa55SAkeem G Abodunrin ice_service_task_stop(pf); 2047940b61afSAnirudh Venkataramanan mutex_destroy(&pf->sw_mutex); 2048940b61afSAnirudh Venkataramanan mutex_destroy(&pf->avail_q_mutex); 2049940b61afSAnirudh Venkataramanan } 2050940b61afSAnirudh Venkataramanan 2051940b61afSAnirudh Venkataramanan /** 2052940b61afSAnirudh Venkataramanan * ice_init_pf - Initialize general software structures (struct ice_pf) 2053940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 2054940b61afSAnirudh Venkataramanan */ 2055940b61afSAnirudh Venkataramanan static void ice_init_pf(struct ice_pf *pf) 2056940b61afSAnirudh Venkataramanan { 2057940b61afSAnirudh Venkataramanan bitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS); 2058940b61afSAnirudh Venkataramanan set_bit(ICE_FLAG_MSIX_ENA, pf->flags); 205975d2b253SAnirudh Venkataramanan #ifdef CONFIG_PCI_IOV 206075d2b253SAnirudh Venkataramanan if (pf->hw.func_caps.common_cap.sr_iov_1_1) { 206175d2b253SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 206275d2b253SAnirudh Venkataramanan 206375d2b253SAnirudh Venkataramanan set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags); 206475d2b253SAnirudh Venkataramanan pf->num_vfs_supported = min_t(int, hw->func_caps.num_allocd_vfs, 206575d2b253SAnirudh Venkataramanan ICE_MAX_VF_COUNT); 206675d2b253SAnirudh Venkataramanan } 206775d2b253SAnirudh Venkataramanan #endif /* CONFIG_PCI_IOV */ 2068940b61afSAnirudh Venkataramanan 2069940b61afSAnirudh Venkataramanan mutex_init(&pf->sw_mutex); 2070940b61afSAnirudh Venkataramanan mutex_init(&pf->avail_q_mutex); 2071940b61afSAnirudh Venkataramanan 2072940b61afSAnirudh Venkataramanan /* Clear avail_[t|r]x_qs bitmaps (set all to avail) */ 2073940b61afSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 2074940b61afSAnirudh Venkataramanan bitmap_zero(pf->avail_txqs, ICE_MAX_TXQS); 2075940b61afSAnirudh Venkataramanan bitmap_zero(pf->avail_rxqs, ICE_MAX_RXQS); 2076940b61afSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 2077940b61afSAnirudh Venkataramanan 2078d76a60baSAnirudh Venkataramanan if (pf->hw.func_caps.common_cap.rss_table_size) 2079d76a60baSAnirudh Venkataramanan set_bit(ICE_FLAG_RSS_ENA, pf->flags); 2080d76a60baSAnirudh Venkataramanan 2081940b61afSAnirudh Venkataramanan /* setup service timer and periodic service task */ 2082940b61afSAnirudh Venkataramanan timer_setup(&pf->serv_tmr, ice_service_timer, 0); 2083940b61afSAnirudh Venkataramanan pf->serv_tmr_period = HZ; 2084940b61afSAnirudh Venkataramanan INIT_WORK(&pf->serv_task, ice_service_task); 2085940b61afSAnirudh Venkataramanan clear_bit(__ICE_SERVICE_SCHED, pf->state); 2086940b61afSAnirudh Venkataramanan } 2087940b61afSAnirudh Venkataramanan 2088940b61afSAnirudh Venkataramanan /** 2089940b61afSAnirudh Venkataramanan * ice_ena_msix_range - Request a range of MSIX vectors from the OS 2090940b61afSAnirudh Venkataramanan * @pf: board private structure 2091940b61afSAnirudh Venkataramanan * 2092940b61afSAnirudh Venkataramanan * compute the number of MSIX vectors required (v_budget) and request from 2093940b61afSAnirudh Venkataramanan * the OS. Return the number of vectors reserved or negative on failure 2094940b61afSAnirudh Venkataramanan */ 2095940b61afSAnirudh Venkataramanan static int ice_ena_msix_range(struct ice_pf *pf) 2096940b61afSAnirudh Venkataramanan { 2097940b61afSAnirudh Venkataramanan int v_left, v_actual, v_budget = 0; 2098940b61afSAnirudh Venkataramanan int needed, err, i; 2099940b61afSAnirudh Venkataramanan 2100940b61afSAnirudh Venkataramanan v_left = pf->hw.func_caps.common_cap.num_msix_vectors; 2101940b61afSAnirudh Venkataramanan 2102940b61afSAnirudh Venkataramanan /* reserve one vector for miscellaneous handler */ 2103940b61afSAnirudh Venkataramanan needed = 1; 2104940b61afSAnirudh Venkataramanan v_budget += needed; 2105940b61afSAnirudh Venkataramanan v_left -= needed; 2106940b61afSAnirudh Venkataramanan 2107940b61afSAnirudh Venkataramanan /* reserve vectors for LAN traffic */ 2108940b61afSAnirudh Venkataramanan pf->num_lan_msix = min_t(int, num_online_cpus(), v_left); 2109940b61afSAnirudh Venkataramanan v_budget += pf->num_lan_msix; 2110eb0208ecSPreethi Banala v_left -= pf->num_lan_msix; 2111940b61afSAnirudh Venkataramanan 2112940b61afSAnirudh Venkataramanan pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget, 2113c6dfd690SBruce Allan sizeof(*pf->msix_entries), GFP_KERNEL); 2114940b61afSAnirudh Venkataramanan 2115940b61afSAnirudh Venkataramanan if (!pf->msix_entries) { 2116940b61afSAnirudh Venkataramanan err = -ENOMEM; 2117940b61afSAnirudh Venkataramanan goto exit_err; 2118940b61afSAnirudh Venkataramanan } 2119940b61afSAnirudh Venkataramanan 2120940b61afSAnirudh Venkataramanan for (i = 0; i < v_budget; i++) 2121940b61afSAnirudh Venkataramanan pf->msix_entries[i].entry = i; 2122940b61afSAnirudh Venkataramanan 2123940b61afSAnirudh Venkataramanan /* actually reserve the vectors */ 2124940b61afSAnirudh Venkataramanan v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries, 2125940b61afSAnirudh Venkataramanan ICE_MIN_MSIX, v_budget); 2126940b61afSAnirudh Venkataramanan 2127940b61afSAnirudh Venkataramanan if (v_actual < 0) { 2128940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "unable to reserve MSI-X vectors\n"); 2129940b61afSAnirudh Venkataramanan err = v_actual; 2130940b61afSAnirudh Venkataramanan goto msix_err; 2131940b61afSAnirudh Venkataramanan } 2132940b61afSAnirudh Venkataramanan 2133940b61afSAnirudh Venkataramanan if (v_actual < v_budget) { 2134940b61afSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 2135940b61afSAnirudh Venkataramanan "not enough vectors. requested = %d, obtained = %d\n", 2136940b61afSAnirudh Venkataramanan v_budget, v_actual); 2137940b61afSAnirudh Venkataramanan if (v_actual >= (pf->num_lan_msix + 1)) { 2138eb0208ecSPreethi Banala pf->num_avail_sw_msix = v_actual - 2139eb0208ecSPreethi Banala (pf->num_lan_msix + 1); 2140940b61afSAnirudh Venkataramanan } else if (v_actual >= 2) { 2141940b61afSAnirudh Venkataramanan pf->num_lan_msix = 1; 2142eb0208ecSPreethi Banala pf->num_avail_sw_msix = v_actual - 2; 2143940b61afSAnirudh Venkataramanan } else { 2144940b61afSAnirudh Venkataramanan pci_disable_msix(pf->pdev); 2145940b61afSAnirudh Venkataramanan err = -ERANGE; 2146940b61afSAnirudh Venkataramanan goto msix_err; 2147940b61afSAnirudh Venkataramanan } 2148940b61afSAnirudh Venkataramanan } 2149940b61afSAnirudh Venkataramanan 2150940b61afSAnirudh Venkataramanan return v_actual; 2151940b61afSAnirudh Venkataramanan 2152940b61afSAnirudh Venkataramanan msix_err: 2153940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->msix_entries); 2154940b61afSAnirudh Venkataramanan goto exit_err; 2155940b61afSAnirudh Venkataramanan 2156940b61afSAnirudh Venkataramanan exit_err: 2157940b61afSAnirudh Venkataramanan pf->num_lan_msix = 0; 2158940b61afSAnirudh Venkataramanan clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); 2159940b61afSAnirudh Venkataramanan return err; 2160940b61afSAnirudh Venkataramanan } 2161940b61afSAnirudh Venkataramanan 2162940b61afSAnirudh Venkataramanan /** 2163940b61afSAnirudh Venkataramanan * ice_dis_msix - Disable MSI-X interrupt setup in OS 2164940b61afSAnirudh Venkataramanan * @pf: board private structure 2165940b61afSAnirudh Venkataramanan */ 2166940b61afSAnirudh Venkataramanan static void ice_dis_msix(struct ice_pf *pf) 2167940b61afSAnirudh Venkataramanan { 2168940b61afSAnirudh Venkataramanan pci_disable_msix(pf->pdev); 2169940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->msix_entries); 2170940b61afSAnirudh Venkataramanan pf->msix_entries = NULL; 2171940b61afSAnirudh Venkataramanan clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); 2172940b61afSAnirudh Venkataramanan } 2173940b61afSAnirudh Venkataramanan 2174940b61afSAnirudh Venkataramanan /** 2175eb0208ecSPreethi Banala * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme 2176eb0208ecSPreethi Banala * @pf: board private structure 2177eb0208ecSPreethi Banala */ 2178eb0208ecSPreethi Banala static void ice_clear_interrupt_scheme(struct ice_pf *pf) 2179eb0208ecSPreethi Banala { 2180eb0208ecSPreethi Banala if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 2181eb0208ecSPreethi Banala ice_dis_msix(pf); 2182eb0208ecSPreethi Banala 2183eb0208ecSPreethi Banala if (pf->sw_irq_tracker) { 2184eb0208ecSPreethi Banala devm_kfree(&pf->pdev->dev, pf->sw_irq_tracker); 2185eb0208ecSPreethi Banala pf->sw_irq_tracker = NULL; 2186eb0208ecSPreethi Banala } 2187eb0208ecSPreethi Banala 2188eb0208ecSPreethi Banala if (pf->hw_irq_tracker) { 2189eb0208ecSPreethi Banala devm_kfree(&pf->pdev->dev, pf->hw_irq_tracker); 2190eb0208ecSPreethi Banala pf->hw_irq_tracker = NULL; 2191eb0208ecSPreethi Banala } 2192eb0208ecSPreethi Banala } 2193eb0208ecSPreethi Banala 2194eb0208ecSPreethi Banala /** 2195940b61afSAnirudh Venkataramanan * ice_init_interrupt_scheme - Determine proper interrupt scheme 2196940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 2197940b61afSAnirudh Venkataramanan */ 2198940b61afSAnirudh Venkataramanan static int ice_init_interrupt_scheme(struct ice_pf *pf) 2199940b61afSAnirudh Venkataramanan { 2200eb0208ecSPreethi Banala int vectors = 0, hw_vectors = 0; 2201940b61afSAnirudh Venkataramanan 2202940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 2203940b61afSAnirudh Venkataramanan vectors = ice_ena_msix_range(pf); 2204940b61afSAnirudh Venkataramanan else 2205940b61afSAnirudh Venkataramanan return -ENODEV; 2206940b61afSAnirudh Venkataramanan 2207940b61afSAnirudh Venkataramanan if (vectors < 0) 2208940b61afSAnirudh Venkataramanan return vectors; 2209940b61afSAnirudh Venkataramanan 2210940b61afSAnirudh Venkataramanan /* set up vector assignment tracking */ 2211c6dfd690SBruce Allan pf->sw_irq_tracker = 2212c6dfd690SBruce Allan devm_kzalloc(&pf->pdev->dev, sizeof(*pf->sw_irq_tracker) + 2213c6dfd690SBruce Allan (sizeof(u16) * vectors), GFP_KERNEL); 2214eb0208ecSPreethi Banala if (!pf->sw_irq_tracker) { 2215940b61afSAnirudh Venkataramanan ice_dis_msix(pf); 2216940b61afSAnirudh Venkataramanan return -ENOMEM; 2217940b61afSAnirudh Venkataramanan } 2218940b61afSAnirudh Venkataramanan 2219eb0208ecSPreethi Banala /* populate SW interrupts pool with number of OS granted IRQs. */ 2220eb0208ecSPreethi Banala pf->num_avail_sw_msix = vectors; 2221eb0208ecSPreethi Banala pf->sw_irq_tracker->num_entries = vectors; 2222eb0208ecSPreethi Banala 2223eb0208ecSPreethi Banala /* set up HW vector assignment tracking */ 2224eb0208ecSPreethi Banala hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors; 2225c6dfd690SBruce Allan pf->hw_irq_tracker = 2226c6dfd690SBruce Allan devm_kzalloc(&pf->pdev->dev, sizeof(*pf->hw_irq_tracker) + 2227c6dfd690SBruce Allan (sizeof(u16) * hw_vectors), GFP_KERNEL); 2228eb0208ecSPreethi Banala if (!pf->hw_irq_tracker) { 2229eb0208ecSPreethi Banala ice_clear_interrupt_scheme(pf); 2230eb0208ecSPreethi Banala return -ENOMEM; 2231eb0208ecSPreethi Banala } 2232eb0208ecSPreethi Banala 2233eb0208ecSPreethi Banala /* populate HW interrupts pool with number of HW supported irqs. */ 2234eb0208ecSPreethi Banala pf->num_avail_hw_msix = hw_vectors; 2235eb0208ecSPreethi Banala pf->hw_irq_tracker->num_entries = hw_vectors; 2236940b61afSAnirudh Venkataramanan 2237940b61afSAnirudh Venkataramanan return 0; 2238940b61afSAnirudh Venkataramanan } 2239940b61afSAnirudh Venkataramanan 2240940b61afSAnirudh Venkataramanan /** 2241c585ea42SBrett Creeley * ice_verify_cacheline_size - verify driver's assumption of 64 Byte cache lines 2242c585ea42SBrett Creeley * @pf: pointer to the PF structure 2243c585ea42SBrett Creeley * 2244c585ea42SBrett Creeley * There is no error returned here because the driver should be able to handle 2245c585ea42SBrett Creeley * 128 Byte cache lines, so we only print a warning in case issues are seen, 2246c585ea42SBrett Creeley * specifically with Tx. 2247c585ea42SBrett Creeley */ 2248c585ea42SBrett Creeley static void ice_verify_cacheline_size(struct ice_pf *pf) 2249c585ea42SBrett Creeley { 2250c585ea42SBrett Creeley if (rd32(&pf->hw, GLPCI_CNF2) & GLPCI_CNF2_CACHELINE_SIZE_M) 2251c585ea42SBrett Creeley dev_warn(&pf->pdev->dev, 2252c585ea42SBrett Creeley "%d Byte cache line assumption is invalid, driver may have Tx timeouts!\n", 2253c585ea42SBrett Creeley ICE_CACHE_LINE_BYTES); 2254c585ea42SBrett Creeley } 2255c585ea42SBrett Creeley 2256c585ea42SBrett Creeley /** 2257837f08fdSAnirudh Venkataramanan * ice_probe - Device initialization routine 2258837f08fdSAnirudh Venkataramanan * @pdev: PCI device information struct 2259837f08fdSAnirudh Venkataramanan * @ent: entry in ice_pci_tbl 2260837f08fdSAnirudh Venkataramanan * 2261837f08fdSAnirudh Venkataramanan * Returns 0 on success, negative on failure 2262837f08fdSAnirudh Venkataramanan */ 2263c8b7abddSBruce Allan static int 2264c8b7abddSBruce Allan ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) 2265837f08fdSAnirudh Venkataramanan { 226677ed84f4SBruce Allan struct device *dev = &pdev->dev; 2267837f08fdSAnirudh Venkataramanan struct ice_pf *pf; 2268837f08fdSAnirudh Venkataramanan struct ice_hw *hw; 2269837f08fdSAnirudh Venkataramanan int err; 2270837f08fdSAnirudh Venkataramanan 2271837f08fdSAnirudh Venkataramanan /* this driver uses devres, see Documentation/driver-model/devres.txt */ 2272837f08fdSAnirudh Venkataramanan err = pcim_enable_device(pdev); 2273837f08fdSAnirudh Venkataramanan if (err) 2274837f08fdSAnirudh Venkataramanan return err; 2275837f08fdSAnirudh Venkataramanan 2276837f08fdSAnirudh Venkataramanan err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev)); 2277837f08fdSAnirudh Venkataramanan if (err) { 227877ed84f4SBruce Allan dev_err(dev, "BAR0 I/O map error %d\n", err); 2279837f08fdSAnirudh Venkataramanan return err; 2280837f08fdSAnirudh Venkataramanan } 2281837f08fdSAnirudh Venkataramanan 228277ed84f4SBruce Allan pf = devm_kzalloc(dev, sizeof(*pf), GFP_KERNEL); 2283837f08fdSAnirudh Venkataramanan if (!pf) 2284837f08fdSAnirudh Venkataramanan return -ENOMEM; 2285837f08fdSAnirudh Venkataramanan 2286837f08fdSAnirudh Venkataramanan /* set up for high or low dma */ 228777ed84f4SBruce Allan err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 2288837f08fdSAnirudh Venkataramanan if (err) 228977ed84f4SBruce Allan err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 2290837f08fdSAnirudh Venkataramanan if (err) { 229177ed84f4SBruce Allan dev_err(dev, "DMA configuration failed: 0x%x\n", err); 2292837f08fdSAnirudh Venkataramanan return err; 2293837f08fdSAnirudh Venkataramanan } 2294837f08fdSAnirudh Venkataramanan 2295837f08fdSAnirudh Venkataramanan pci_enable_pcie_error_reporting(pdev); 2296837f08fdSAnirudh Venkataramanan pci_set_master(pdev); 2297837f08fdSAnirudh Venkataramanan 2298837f08fdSAnirudh Venkataramanan pf->pdev = pdev; 2299837f08fdSAnirudh Venkataramanan pci_set_drvdata(pdev, pf); 2300837f08fdSAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 23018d81fa55SAkeem G Abodunrin /* Disable service task until DOWN bit is cleared */ 23028d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 2303837f08fdSAnirudh Venkataramanan 2304837f08fdSAnirudh Venkataramanan hw = &pf->hw; 2305837f08fdSAnirudh Venkataramanan hw->hw_addr = pcim_iomap_table(pdev)[ICE_BAR0]; 2306837f08fdSAnirudh Venkataramanan hw->back = pf; 2307837f08fdSAnirudh Venkataramanan hw->vendor_id = pdev->vendor; 2308837f08fdSAnirudh Venkataramanan hw->device_id = pdev->device; 2309837f08fdSAnirudh Venkataramanan pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); 2310837f08fdSAnirudh Venkataramanan hw->subsystem_vendor_id = pdev->subsystem_vendor; 2311837f08fdSAnirudh Venkataramanan hw->subsystem_device_id = pdev->subsystem_device; 2312837f08fdSAnirudh Venkataramanan hw->bus.device = PCI_SLOT(pdev->devfn); 2313837f08fdSAnirudh Venkataramanan hw->bus.func = PCI_FUNC(pdev->devfn); 2314f31e4b6fSAnirudh Venkataramanan ice_set_ctrlq_len(hw); 2315f31e4b6fSAnirudh Venkataramanan 2316837f08fdSAnirudh Venkataramanan pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M); 2317837f08fdSAnirudh Venkataramanan 23187ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 23197ec59eeaSAnirudh Venkataramanan if (debug < -1) 23207ec59eeaSAnirudh Venkataramanan hw->debug_mask = debug; 23217ec59eeaSAnirudh Venkataramanan #endif 23227ec59eeaSAnirudh Venkataramanan 2323f31e4b6fSAnirudh Venkataramanan err = ice_init_hw(hw); 2324f31e4b6fSAnirudh Venkataramanan if (err) { 232577ed84f4SBruce Allan dev_err(dev, "ice_init_hw failed: %d\n", err); 2326f31e4b6fSAnirudh Venkataramanan err = -EIO; 2327f31e4b6fSAnirudh Venkataramanan goto err_exit_unroll; 2328f31e4b6fSAnirudh Venkataramanan } 2329f31e4b6fSAnirudh Venkataramanan 233077ed84f4SBruce Allan dev_info(dev, "firmware %d.%d.%05d api %d.%d\n", 2331f31e4b6fSAnirudh Venkataramanan hw->fw_maj_ver, hw->fw_min_ver, hw->fw_build, 2332f31e4b6fSAnirudh Venkataramanan hw->api_maj_ver, hw->api_min_ver); 2333f31e4b6fSAnirudh Venkataramanan 2334940b61afSAnirudh Venkataramanan ice_init_pf(pf); 2335940b61afSAnirudh Venkataramanan 233637b6f646SAnirudh Venkataramanan err = ice_init_pf_dcb(pf); 233737b6f646SAnirudh Venkataramanan if (err) { 233837b6f646SAnirudh Venkataramanan clear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags); 233937b6f646SAnirudh Venkataramanan clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 234037b6f646SAnirudh Venkataramanan 234137b6f646SAnirudh Venkataramanan /* do not fail overall init if DCB init fails */ 234237b6f646SAnirudh Venkataramanan err = 0; 234337b6f646SAnirudh Venkataramanan } 234437b6f646SAnirudh Venkataramanan 2345940b61afSAnirudh Venkataramanan ice_determine_q_usage(pf); 2346940b61afSAnirudh Venkataramanan 2347995c90f2SAnirudh Venkataramanan pf->num_alloc_vsi = hw->func_caps.guar_num_vsi; 2348940b61afSAnirudh Venkataramanan if (!pf->num_alloc_vsi) { 2349940b61afSAnirudh Venkataramanan err = -EIO; 2350940b61afSAnirudh Venkataramanan goto err_init_pf_unroll; 2351940b61afSAnirudh Venkataramanan } 2352940b61afSAnirudh Venkataramanan 235377ed84f4SBruce Allan pf->vsi = devm_kcalloc(dev, pf->num_alloc_vsi, sizeof(*pf->vsi), 235477ed84f4SBruce Allan GFP_KERNEL); 2355940b61afSAnirudh Venkataramanan if (!pf->vsi) { 2356940b61afSAnirudh Venkataramanan err = -ENOMEM; 2357940b61afSAnirudh Venkataramanan goto err_init_pf_unroll; 2358940b61afSAnirudh Venkataramanan } 2359940b61afSAnirudh Venkataramanan 2360940b61afSAnirudh Venkataramanan err = ice_init_interrupt_scheme(pf); 2361940b61afSAnirudh Venkataramanan if (err) { 236277ed84f4SBruce Allan dev_err(dev, "ice_init_interrupt_scheme failed: %d\n", err); 2363940b61afSAnirudh Venkataramanan err = -EIO; 2364940b61afSAnirudh Venkataramanan goto err_init_interrupt_unroll; 2365940b61afSAnirudh Venkataramanan } 2366940b61afSAnirudh Venkataramanan 23678d81fa55SAkeem G Abodunrin /* Driver is mostly up */ 23688d81fa55SAkeem G Abodunrin clear_bit(__ICE_DOWN, pf->state); 23698d81fa55SAkeem G Abodunrin 2370940b61afSAnirudh Venkataramanan /* In case of MSIX we are going to setup the misc vector right here 2371940b61afSAnirudh Venkataramanan * to handle admin queue events etc. In case of legacy and MSI 2372940b61afSAnirudh Venkataramanan * the misc functionality and queue processing is combined in 2373940b61afSAnirudh Venkataramanan * the same vector and that gets setup at open. 2374940b61afSAnirudh Venkataramanan */ 2375940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 2376940b61afSAnirudh Venkataramanan err = ice_req_irq_msix_misc(pf); 2377940b61afSAnirudh Venkataramanan if (err) { 237877ed84f4SBruce Allan dev_err(dev, "setup of misc vector failed: %d\n", err); 2379940b61afSAnirudh Venkataramanan goto err_init_interrupt_unroll; 2380940b61afSAnirudh Venkataramanan } 2381940b61afSAnirudh Venkataramanan } 2382940b61afSAnirudh Venkataramanan 2383940b61afSAnirudh Venkataramanan /* create switch struct for the switch element created by FW on boot */ 238477ed84f4SBruce Allan pf->first_sw = devm_kzalloc(dev, sizeof(*pf->first_sw), GFP_KERNEL); 2385940b61afSAnirudh Venkataramanan if (!pf->first_sw) { 2386940b61afSAnirudh Venkataramanan err = -ENOMEM; 2387940b61afSAnirudh Venkataramanan goto err_msix_misc_unroll; 2388940b61afSAnirudh Venkataramanan } 2389940b61afSAnirudh Venkataramanan 2390b1edc14aSMd Fahad Iqbal Polash if (hw->evb_veb) 2391940b61afSAnirudh Venkataramanan pf->first_sw->bridge_mode = BRIDGE_MODE_VEB; 2392b1edc14aSMd Fahad Iqbal Polash else 2393b1edc14aSMd Fahad Iqbal Polash pf->first_sw->bridge_mode = BRIDGE_MODE_VEPA; 2394b1edc14aSMd Fahad Iqbal Polash 2395940b61afSAnirudh Venkataramanan pf->first_sw->pf = pf; 2396940b61afSAnirudh Venkataramanan 2397940b61afSAnirudh Venkataramanan /* record the sw_id available for later use */ 2398940b61afSAnirudh Venkataramanan pf->first_sw->sw_id = hw->port_info->sw_id; 2399940b61afSAnirudh Venkataramanan 24003a858ba3SAnirudh Venkataramanan err = ice_setup_pf_sw(pf); 24013a858ba3SAnirudh Venkataramanan if (err) { 240277ed84f4SBruce Allan dev_err(dev, "probe failed due to setup pf switch:%d\n", err); 24033a858ba3SAnirudh Venkataramanan goto err_alloc_sw_unroll; 24043a858ba3SAnirudh Venkataramanan } 24059daf8208SAnirudh Venkataramanan 24068d81fa55SAkeem G Abodunrin clear_bit(__ICE_SERVICE_DIS, pf->state); 24079daf8208SAnirudh Venkataramanan 24089daf8208SAnirudh Venkataramanan /* since everything is good, start the service timer */ 24099daf8208SAnirudh Venkataramanan mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); 24109daf8208SAnirudh Venkataramanan 2411250c3b3eSBrett Creeley err = ice_init_link_events(pf->hw.port_info); 2412250c3b3eSBrett Creeley if (err) { 2413250c3b3eSBrett Creeley dev_err(dev, "ice_init_link_events failed: %d\n", err); 2414250c3b3eSBrett Creeley goto err_alloc_sw_unroll; 2415250c3b3eSBrett Creeley } 2416250c3b3eSBrett Creeley 2417c585ea42SBrett Creeley ice_verify_cacheline_size(pf); 2418c585ea42SBrett Creeley 2419837f08fdSAnirudh Venkataramanan return 0; 2420f31e4b6fSAnirudh Venkataramanan 24213a858ba3SAnirudh Venkataramanan err_alloc_sw_unroll: 24228d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 24233a858ba3SAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 24243a858ba3SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->first_sw); 2425940b61afSAnirudh Venkataramanan err_msix_misc_unroll: 2426940b61afSAnirudh Venkataramanan ice_free_irq_msix_misc(pf); 2427940b61afSAnirudh Venkataramanan err_init_interrupt_unroll: 2428940b61afSAnirudh Venkataramanan ice_clear_interrupt_scheme(pf); 242977ed84f4SBruce Allan devm_kfree(dev, pf->vsi); 2430940b61afSAnirudh Venkataramanan err_init_pf_unroll: 2431940b61afSAnirudh Venkataramanan ice_deinit_pf(pf); 2432940b61afSAnirudh Venkataramanan ice_deinit_hw(hw); 2433f31e4b6fSAnirudh Venkataramanan err_exit_unroll: 2434f31e4b6fSAnirudh Venkataramanan pci_disable_pcie_error_reporting(pdev); 2435f31e4b6fSAnirudh Venkataramanan return err; 2436837f08fdSAnirudh Venkataramanan } 2437837f08fdSAnirudh Venkataramanan 2438837f08fdSAnirudh Venkataramanan /** 2439837f08fdSAnirudh Venkataramanan * ice_remove - Device removal routine 2440837f08fdSAnirudh Venkataramanan * @pdev: PCI device information struct 2441837f08fdSAnirudh Venkataramanan */ 2442837f08fdSAnirudh Venkataramanan static void ice_remove(struct pci_dev *pdev) 2443837f08fdSAnirudh Venkataramanan { 2444837f08fdSAnirudh Venkataramanan struct ice_pf *pf = pci_get_drvdata(pdev); 244581b23589SDave Ertman int i; 2446837f08fdSAnirudh Venkataramanan 2447837f08fdSAnirudh Venkataramanan if (!pf) 2448837f08fdSAnirudh Venkataramanan return; 2449837f08fdSAnirudh Venkataramanan 2450afd9d4abSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_RESET_WAIT; i++) { 2451afd9d4abSAnirudh Venkataramanan if (!ice_is_reset_in_progress(pf->state)) 2452afd9d4abSAnirudh Venkataramanan break; 2453afd9d4abSAnirudh Venkataramanan msleep(100); 2454afd9d4abSAnirudh Venkataramanan } 2455afd9d4abSAnirudh Venkataramanan 2456837f08fdSAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 24578d81fa55SAkeem G Abodunrin ice_service_task_stop(pf); 2458f31e4b6fSAnirudh Venkataramanan 2459ddf30f7fSAnirudh Venkataramanan if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) 2460ddf30f7fSAnirudh Venkataramanan ice_free_vfs(pf); 24610f9d5027SAnirudh Venkataramanan ice_vsi_release_all(pf); 2462940b61afSAnirudh Venkataramanan ice_free_irq_msix_misc(pf); 246381b23589SDave Ertman ice_for_each_vsi(pf, i) { 246481b23589SDave Ertman if (!pf->vsi[i]) 246581b23589SDave Ertman continue; 246681b23589SDave Ertman ice_vsi_free_q_vectors(pf->vsi[i]); 246781b23589SDave Ertman } 2468940b61afSAnirudh Venkataramanan ice_clear_interrupt_scheme(pf); 2469940b61afSAnirudh Venkataramanan ice_deinit_pf(pf); 2470f31e4b6fSAnirudh Venkataramanan ice_deinit_hw(&pf->hw); 2471837f08fdSAnirudh Venkataramanan pci_disable_pcie_error_reporting(pdev); 2472837f08fdSAnirudh Venkataramanan } 2473837f08fdSAnirudh Venkataramanan 24745995b6d0SBrett Creeley /** 24755995b6d0SBrett Creeley * ice_pci_err_detected - warning that PCI error has been detected 24765995b6d0SBrett Creeley * @pdev: PCI device information struct 24775995b6d0SBrett Creeley * @err: the type of PCI error 24785995b6d0SBrett Creeley * 24795995b6d0SBrett Creeley * Called to warn that something happened on the PCI bus and the error handling 24805995b6d0SBrett Creeley * is in progress. Allows the driver to gracefully prepare/handle PCI errors. 24815995b6d0SBrett Creeley */ 24825995b6d0SBrett Creeley static pci_ers_result_t 24835995b6d0SBrett Creeley ice_pci_err_detected(struct pci_dev *pdev, enum pci_channel_state err) 24845995b6d0SBrett Creeley { 24855995b6d0SBrett Creeley struct ice_pf *pf = pci_get_drvdata(pdev); 24865995b6d0SBrett Creeley 24875995b6d0SBrett Creeley if (!pf) { 24885995b6d0SBrett Creeley dev_err(&pdev->dev, "%s: unrecoverable device error %d\n", 24895995b6d0SBrett Creeley __func__, err); 24905995b6d0SBrett Creeley return PCI_ERS_RESULT_DISCONNECT; 24915995b6d0SBrett Creeley } 24925995b6d0SBrett Creeley 24935995b6d0SBrett Creeley if (!test_bit(__ICE_SUSPENDED, pf->state)) { 24945995b6d0SBrett Creeley ice_service_task_stop(pf); 24955995b6d0SBrett Creeley 24965995b6d0SBrett Creeley if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) { 24975995b6d0SBrett Creeley set_bit(__ICE_PFR_REQ, pf->state); 24985995b6d0SBrett Creeley ice_prepare_for_reset(pf); 24995995b6d0SBrett Creeley } 25005995b6d0SBrett Creeley } 25015995b6d0SBrett Creeley 25025995b6d0SBrett Creeley return PCI_ERS_RESULT_NEED_RESET; 25035995b6d0SBrett Creeley } 25045995b6d0SBrett Creeley 25055995b6d0SBrett Creeley /** 25065995b6d0SBrett Creeley * ice_pci_err_slot_reset - a PCI slot reset has just happened 25075995b6d0SBrett Creeley * @pdev: PCI device information struct 25085995b6d0SBrett Creeley * 25095995b6d0SBrett Creeley * Called to determine if the driver can recover from the PCI slot reset by 25105995b6d0SBrett Creeley * using a register read to determine if the device is recoverable. 25115995b6d0SBrett Creeley */ 25125995b6d0SBrett Creeley static pci_ers_result_t ice_pci_err_slot_reset(struct pci_dev *pdev) 25135995b6d0SBrett Creeley { 25145995b6d0SBrett Creeley struct ice_pf *pf = pci_get_drvdata(pdev); 25155995b6d0SBrett Creeley pci_ers_result_t result; 25165995b6d0SBrett Creeley int err; 25175995b6d0SBrett Creeley u32 reg; 25185995b6d0SBrett Creeley 25195995b6d0SBrett Creeley err = pci_enable_device_mem(pdev); 25205995b6d0SBrett Creeley if (err) { 25215995b6d0SBrett Creeley dev_err(&pdev->dev, 25225995b6d0SBrett Creeley "Cannot re-enable PCI device after reset, error %d\n", 25235995b6d0SBrett Creeley err); 25245995b6d0SBrett Creeley result = PCI_ERS_RESULT_DISCONNECT; 25255995b6d0SBrett Creeley } else { 25265995b6d0SBrett Creeley pci_set_master(pdev); 25275995b6d0SBrett Creeley pci_restore_state(pdev); 25285995b6d0SBrett Creeley pci_save_state(pdev); 25295995b6d0SBrett Creeley pci_wake_from_d3(pdev, false); 25305995b6d0SBrett Creeley 25315995b6d0SBrett Creeley /* Check for life */ 25325995b6d0SBrett Creeley reg = rd32(&pf->hw, GLGEN_RTRIG); 25335995b6d0SBrett Creeley if (!reg) 25345995b6d0SBrett Creeley result = PCI_ERS_RESULT_RECOVERED; 25355995b6d0SBrett Creeley else 25365995b6d0SBrett Creeley result = PCI_ERS_RESULT_DISCONNECT; 25375995b6d0SBrett Creeley } 25385995b6d0SBrett Creeley 25395995b6d0SBrett Creeley err = pci_cleanup_aer_uncorrect_error_status(pdev); 25405995b6d0SBrett Creeley if (err) 25415995b6d0SBrett Creeley dev_dbg(&pdev->dev, 25425995b6d0SBrett Creeley "pci_cleanup_aer_uncorrect_error_status failed, error %d\n", 25435995b6d0SBrett Creeley err); 25445995b6d0SBrett Creeley /* non-fatal, continue */ 25455995b6d0SBrett Creeley 25465995b6d0SBrett Creeley return result; 25475995b6d0SBrett Creeley } 25485995b6d0SBrett Creeley 25495995b6d0SBrett Creeley /** 25505995b6d0SBrett Creeley * ice_pci_err_resume - restart operations after PCI error recovery 25515995b6d0SBrett Creeley * @pdev: PCI device information struct 25525995b6d0SBrett Creeley * 25535995b6d0SBrett Creeley * Called to allow the driver to bring things back up after PCI error and/or 25545995b6d0SBrett Creeley * reset recovery have finished 25555995b6d0SBrett Creeley */ 25565995b6d0SBrett Creeley static void ice_pci_err_resume(struct pci_dev *pdev) 25575995b6d0SBrett Creeley { 25585995b6d0SBrett Creeley struct ice_pf *pf = pci_get_drvdata(pdev); 25595995b6d0SBrett Creeley 25605995b6d0SBrett Creeley if (!pf) { 25615995b6d0SBrett Creeley dev_err(&pdev->dev, 25625995b6d0SBrett Creeley "%s failed, device is unrecoverable\n", __func__); 25635995b6d0SBrett Creeley return; 25645995b6d0SBrett Creeley } 25655995b6d0SBrett Creeley 25665995b6d0SBrett Creeley if (test_bit(__ICE_SUSPENDED, pf->state)) { 25675995b6d0SBrett Creeley dev_dbg(&pdev->dev, "%s failed to resume normal operations!\n", 25685995b6d0SBrett Creeley __func__); 25695995b6d0SBrett Creeley return; 25705995b6d0SBrett Creeley } 25715995b6d0SBrett Creeley 25725995b6d0SBrett Creeley ice_do_reset(pf, ICE_RESET_PFR); 25735995b6d0SBrett Creeley ice_service_task_restart(pf); 25745995b6d0SBrett Creeley mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); 25755995b6d0SBrett Creeley } 25765995b6d0SBrett Creeley 25775995b6d0SBrett Creeley /** 25785995b6d0SBrett Creeley * ice_pci_err_reset_prepare - prepare device driver for PCI reset 25795995b6d0SBrett Creeley * @pdev: PCI device information struct 25805995b6d0SBrett Creeley */ 25815995b6d0SBrett Creeley static void ice_pci_err_reset_prepare(struct pci_dev *pdev) 25825995b6d0SBrett Creeley { 25835995b6d0SBrett Creeley struct ice_pf *pf = pci_get_drvdata(pdev); 25845995b6d0SBrett Creeley 25855995b6d0SBrett Creeley if (!test_bit(__ICE_SUSPENDED, pf->state)) { 25865995b6d0SBrett Creeley ice_service_task_stop(pf); 25875995b6d0SBrett Creeley 25885995b6d0SBrett Creeley if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) { 25895995b6d0SBrett Creeley set_bit(__ICE_PFR_REQ, pf->state); 25905995b6d0SBrett Creeley ice_prepare_for_reset(pf); 25915995b6d0SBrett Creeley } 25925995b6d0SBrett Creeley } 25935995b6d0SBrett Creeley } 25945995b6d0SBrett Creeley 25955995b6d0SBrett Creeley /** 25965995b6d0SBrett Creeley * ice_pci_err_reset_done - PCI reset done, device driver reset can begin 25975995b6d0SBrett Creeley * @pdev: PCI device information struct 25985995b6d0SBrett Creeley */ 25995995b6d0SBrett Creeley static void ice_pci_err_reset_done(struct pci_dev *pdev) 26005995b6d0SBrett Creeley { 26015995b6d0SBrett Creeley ice_pci_err_resume(pdev); 26025995b6d0SBrett Creeley } 26035995b6d0SBrett Creeley 2604837f08fdSAnirudh Venkataramanan /* ice_pci_tbl - PCI Device ID Table 2605837f08fdSAnirudh Venkataramanan * 2606837f08fdSAnirudh Venkataramanan * Wildcard entries (PCI_ANY_ID) should come last 2607837f08fdSAnirudh Venkataramanan * Last entry must be all 0s 2608837f08fdSAnirudh Venkataramanan * 2609837f08fdSAnirudh Venkataramanan * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, 2610837f08fdSAnirudh Venkataramanan * Class, Class Mask, private data (not used) } 2611837f08fdSAnirudh Venkataramanan */ 2612837f08fdSAnirudh Venkataramanan static const struct pci_device_id ice_pci_tbl[] = { 2613633d7449SAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_BACKPLANE), 0 }, 2614633d7449SAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_QSFP), 0 }, 2615633d7449SAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_SFP), 0 }, 2616837f08fdSAnirudh Venkataramanan /* required last entry */ 2617837f08fdSAnirudh Venkataramanan { 0, } 2618837f08fdSAnirudh Venkataramanan }; 2619837f08fdSAnirudh Venkataramanan MODULE_DEVICE_TABLE(pci, ice_pci_tbl); 2620837f08fdSAnirudh Venkataramanan 26215995b6d0SBrett Creeley static const struct pci_error_handlers ice_pci_err_handler = { 26225995b6d0SBrett Creeley .error_detected = ice_pci_err_detected, 26235995b6d0SBrett Creeley .slot_reset = ice_pci_err_slot_reset, 26245995b6d0SBrett Creeley .reset_prepare = ice_pci_err_reset_prepare, 26255995b6d0SBrett Creeley .reset_done = ice_pci_err_reset_done, 26265995b6d0SBrett Creeley .resume = ice_pci_err_resume 26275995b6d0SBrett Creeley }; 26285995b6d0SBrett Creeley 2629837f08fdSAnirudh Venkataramanan static struct pci_driver ice_driver = { 2630837f08fdSAnirudh Venkataramanan .name = KBUILD_MODNAME, 2631837f08fdSAnirudh Venkataramanan .id_table = ice_pci_tbl, 2632837f08fdSAnirudh Venkataramanan .probe = ice_probe, 2633837f08fdSAnirudh Venkataramanan .remove = ice_remove, 2634ddf30f7fSAnirudh Venkataramanan .sriov_configure = ice_sriov_configure, 26355995b6d0SBrett Creeley .err_handler = &ice_pci_err_handler 2636837f08fdSAnirudh Venkataramanan }; 2637837f08fdSAnirudh Venkataramanan 2638837f08fdSAnirudh Venkataramanan /** 2639837f08fdSAnirudh Venkataramanan * ice_module_init - Driver registration routine 2640837f08fdSAnirudh Venkataramanan * 2641837f08fdSAnirudh Venkataramanan * ice_module_init is the first routine called when the driver is 2642837f08fdSAnirudh Venkataramanan * loaded. All it does is register with the PCI subsystem. 2643837f08fdSAnirudh Venkataramanan */ 2644837f08fdSAnirudh Venkataramanan static int __init ice_module_init(void) 2645837f08fdSAnirudh Venkataramanan { 2646837f08fdSAnirudh Venkataramanan int status; 2647837f08fdSAnirudh Venkataramanan 2648837f08fdSAnirudh Venkataramanan pr_info("%s - version %s\n", ice_driver_string, ice_drv_ver); 2649837f08fdSAnirudh Venkataramanan pr_info("%s\n", ice_copyright); 2650837f08fdSAnirudh Venkataramanan 26510f9d5027SAnirudh Venkataramanan ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME); 2652940b61afSAnirudh Venkataramanan if (!ice_wq) { 2653940b61afSAnirudh Venkataramanan pr_err("Failed to create workqueue\n"); 2654940b61afSAnirudh Venkataramanan return -ENOMEM; 2655940b61afSAnirudh Venkataramanan } 2656940b61afSAnirudh Venkataramanan 2657837f08fdSAnirudh Venkataramanan status = pci_register_driver(&ice_driver); 2658940b61afSAnirudh Venkataramanan if (status) { 2659837f08fdSAnirudh Venkataramanan pr_err("failed to register pci driver, err %d\n", status); 2660940b61afSAnirudh Venkataramanan destroy_workqueue(ice_wq); 2661940b61afSAnirudh Venkataramanan } 2662837f08fdSAnirudh Venkataramanan 2663837f08fdSAnirudh Venkataramanan return status; 2664837f08fdSAnirudh Venkataramanan } 2665837f08fdSAnirudh Venkataramanan module_init(ice_module_init); 2666837f08fdSAnirudh Venkataramanan 2667837f08fdSAnirudh Venkataramanan /** 2668837f08fdSAnirudh Venkataramanan * ice_module_exit - Driver exit cleanup routine 2669837f08fdSAnirudh Venkataramanan * 2670837f08fdSAnirudh Venkataramanan * ice_module_exit is called just before the driver is removed 2671837f08fdSAnirudh Venkataramanan * from memory. 2672837f08fdSAnirudh Venkataramanan */ 2673837f08fdSAnirudh Venkataramanan static void __exit ice_module_exit(void) 2674837f08fdSAnirudh Venkataramanan { 2675837f08fdSAnirudh Venkataramanan pci_unregister_driver(&ice_driver); 2676940b61afSAnirudh Venkataramanan destroy_workqueue(ice_wq); 2677837f08fdSAnirudh Venkataramanan pr_info("module unloaded\n"); 2678837f08fdSAnirudh Venkataramanan } 2679837f08fdSAnirudh Venkataramanan module_exit(ice_module_exit); 26803a858ba3SAnirudh Venkataramanan 26813a858ba3SAnirudh Venkataramanan /** 2682f9867df6SAnirudh Venkataramanan * ice_set_mac_address - NDO callback to set MAC address 2683e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 2684e94d4478SAnirudh Venkataramanan * @pi: pointer to an address structure 2685e94d4478SAnirudh Venkataramanan * 2686e94d4478SAnirudh Venkataramanan * Returns 0 on success, negative on failure 2687e94d4478SAnirudh Venkataramanan */ 2688e94d4478SAnirudh Venkataramanan static int ice_set_mac_address(struct net_device *netdev, void *pi) 2689e94d4478SAnirudh Venkataramanan { 2690e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2691e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2692e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2693e94d4478SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2694e94d4478SAnirudh Venkataramanan struct sockaddr *addr = pi; 2695e94d4478SAnirudh Venkataramanan enum ice_status status; 2696e94d4478SAnirudh Venkataramanan LIST_HEAD(a_mac_list); 2697e94d4478SAnirudh Venkataramanan LIST_HEAD(r_mac_list); 2698e94d4478SAnirudh Venkataramanan u8 flags = 0; 2699e94d4478SAnirudh Venkataramanan int err; 2700e94d4478SAnirudh Venkataramanan u8 *mac; 2701e94d4478SAnirudh Venkataramanan 2702e94d4478SAnirudh Venkataramanan mac = (u8 *)addr->sa_data; 2703e94d4478SAnirudh Venkataramanan 2704e94d4478SAnirudh Venkataramanan if (!is_valid_ether_addr(mac)) 2705e94d4478SAnirudh Venkataramanan return -EADDRNOTAVAIL; 2706e94d4478SAnirudh Venkataramanan 2707e94d4478SAnirudh Venkataramanan if (ether_addr_equal(netdev->dev_addr, mac)) { 2708e94d4478SAnirudh Venkataramanan netdev_warn(netdev, "already using mac %pM\n", mac); 2709e94d4478SAnirudh Venkataramanan return 0; 2710e94d4478SAnirudh Venkataramanan } 2711e94d4478SAnirudh Venkataramanan 2712e94d4478SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state) || 27135df7e45dSDave Ertman ice_is_reset_in_progress(pf->state)) { 2714e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. device not ready\n", 2715e94d4478SAnirudh Venkataramanan mac); 2716e94d4478SAnirudh Venkataramanan return -EBUSY; 2717e94d4478SAnirudh Venkataramanan } 2718e94d4478SAnirudh Venkataramanan 2719f9867df6SAnirudh Venkataramanan /* When we change the MAC address we also have to change the MAC address 2720f9867df6SAnirudh Venkataramanan * based filter rules that were created previously for the old MAC 2721e94d4478SAnirudh Venkataramanan * address. So first, we remove the old filter rule using ice_remove_mac 2722e94d4478SAnirudh Venkataramanan * and then create a new filter rule using ice_add_mac. Note that for 2723f9867df6SAnirudh Venkataramanan * both these operations, we first need to form a "list" of MAC 2724f9867df6SAnirudh Venkataramanan * addresses (even though in this case, we have only 1 MAC address to be 2725e94d4478SAnirudh Venkataramanan * added/removed) and this done using ice_add_mac_to_list. Depending on 2726f9867df6SAnirudh Venkataramanan * the ensuing operation this "list" of MAC addresses is either to be 2727e94d4478SAnirudh Venkataramanan * added or removed from the filter. 2728e94d4478SAnirudh Venkataramanan */ 2729e94d4478SAnirudh Venkataramanan err = ice_add_mac_to_list(vsi, &r_mac_list, netdev->dev_addr); 2730e94d4478SAnirudh Venkataramanan if (err) { 2731e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2732e94d4478SAnirudh Venkataramanan goto free_lists; 2733e94d4478SAnirudh Venkataramanan } 2734e94d4478SAnirudh Venkataramanan 2735e94d4478SAnirudh Venkataramanan status = ice_remove_mac(hw, &r_mac_list); 2736e94d4478SAnirudh Venkataramanan if (status) { 2737e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2738e94d4478SAnirudh Venkataramanan goto free_lists; 2739e94d4478SAnirudh Venkataramanan } 2740e94d4478SAnirudh Venkataramanan 2741e94d4478SAnirudh Venkataramanan err = ice_add_mac_to_list(vsi, &a_mac_list, mac); 2742e94d4478SAnirudh Venkataramanan if (err) { 2743e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2744e94d4478SAnirudh Venkataramanan goto free_lists; 2745e94d4478SAnirudh Venkataramanan } 2746e94d4478SAnirudh Venkataramanan 2747e94d4478SAnirudh Venkataramanan status = ice_add_mac(hw, &a_mac_list); 2748e94d4478SAnirudh Venkataramanan if (status) { 2749e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2750e94d4478SAnirudh Venkataramanan goto free_lists; 2751e94d4478SAnirudh Venkataramanan } 2752e94d4478SAnirudh Venkataramanan 2753e94d4478SAnirudh Venkataramanan free_lists: 2754e94d4478SAnirudh Venkataramanan /* free list entries */ 2755e94d4478SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &r_mac_list); 2756e94d4478SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &a_mac_list); 2757e94d4478SAnirudh Venkataramanan 2758e94d4478SAnirudh Venkataramanan if (err) { 2759e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. filter update failed\n", 2760e94d4478SAnirudh Venkataramanan mac); 2761e94d4478SAnirudh Venkataramanan return err; 2762e94d4478SAnirudh Venkataramanan } 2763e94d4478SAnirudh Venkataramanan 2764f9867df6SAnirudh Venkataramanan /* change the netdev's MAC address */ 2765e94d4478SAnirudh Venkataramanan memcpy(netdev->dev_addr, mac, netdev->addr_len); 2766e94d4478SAnirudh Venkataramanan netdev_dbg(vsi->netdev, "updated mac address to %pM\n", 2767e94d4478SAnirudh Venkataramanan netdev->dev_addr); 2768e94d4478SAnirudh Venkataramanan 2769f9867df6SAnirudh Venkataramanan /* write new MAC address to the firmware */ 2770e94d4478SAnirudh Venkataramanan flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL; 2771e94d4478SAnirudh Venkataramanan status = ice_aq_manage_mac_write(hw, mac, flags, NULL); 2772e94d4478SAnirudh Venkataramanan if (status) { 2773e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. write to firmware failed.\n", 2774e94d4478SAnirudh Venkataramanan mac); 2775e94d4478SAnirudh Venkataramanan } 2776e94d4478SAnirudh Venkataramanan return 0; 2777e94d4478SAnirudh Venkataramanan } 2778e94d4478SAnirudh Venkataramanan 2779e94d4478SAnirudh Venkataramanan /** 2780e94d4478SAnirudh Venkataramanan * ice_set_rx_mode - NDO callback to set the netdev filters 2781e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 2782e94d4478SAnirudh Venkataramanan */ 2783e94d4478SAnirudh Venkataramanan static void ice_set_rx_mode(struct net_device *netdev) 2784e94d4478SAnirudh Venkataramanan { 2785e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2786e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2787e94d4478SAnirudh Venkataramanan 2788e94d4478SAnirudh Venkataramanan if (!vsi) 2789e94d4478SAnirudh Venkataramanan return; 2790e94d4478SAnirudh Venkataramanan 2791e94d4478SAnirudh Venkataramanan /* Set the flags to synchronize filters 2792e94d4478SAnirudh Venkataramanan * ndo_set_rx_mode may be triggered even without a change in netdev 2793e94d4478SAnirudh Venkataramanan * flags 2794e94d4478SAnirudh Venkataramanan */ 2795e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 2796e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 2797e94d4478SAnirudh Venkataramanan set_bit(ICE_FLAG_FLTR_SYNC, vsi->back->flags); 2798e94d4478SAnirudh Venkataramanan 2799e94d4478SAnirudh Venkataramanan /* schedule our worker thread which will take care of 2800e94d4478SAnirudh Venkataramanan * applying the new filter changes 2801e94d4478SAnirudh Venkataramanan */ 2802e94d4478SAnirudh Venkataramanan ice_service_task_schedule(vsi->back); 2803e94d4478SAnirudh Venkataramanan } 2804e94d4478SAnirudh Venkataramanan 2805e94d4478SAnirudh Venkataramanan /** 2806e94d4478SAnirudh Venkataramanan * ice_fdb_add - add an entry to the hardware database 2807e94d4478SAnirudh Venkataramanan * @ndm: the input from the stack 2808e94d4478SAnirudh Venkataramanan * @tb: pointer to array of nladdr (unused) 2809e94d4478SAnirudh Venkataramanan * @dev: the net device pointer 2810e94d4478SAnirudh Venkataramanan * @addr: the MAC address entry being added 2811f9867df6SAnirudh Venkataramanan * @vid: VLAN ID 2812e94d4478SAnirudh Venkataramanan * @flags: instructions from stack about fdb operation 281399be37edSBruce Allan * @extack: netlink extended ack 2814e94d4478SAnirudh Venkataramanan */ 281599be37edSBruce Allan static int 281699be37edSBruce Allan ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[], 281799be37edSBruce Allan struct net_device *dev, const unsigned char *addr, u16 vid, 281899be37edSBruce Allan u16 flags, struct netlink_ext_ack __always_unused *extack) 2819e94d4478SAnirudh Venkataramanan { 2820e94d4478SAnirudh Venkataramanan int err; 2821e94d4478SAnirudh Venkataramanan 2822e94d4478SAnirudh Venkataramanan if (vid) { 2823e94d4478SAnirudh Venkataramanan netdev_err(dev, "VLANs aren't supported yet for dev_uc|mc_add()\n"); 2824e94d4478SAnirudh Venkataramanan return -EINVAL; 2825e94d4478SAnirudh Venkataramanan } 2826e94d4478SAnirudh Venkataramanan if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { 2827e94d4478SAnirudh Venkataramanan netdev_err(dev, "FDB only supports static addresses\n"); 2828e94d4478SAnirudh Venkataramanan return -EINVAL; 2829e94d4478SAnirudh Venkataramanan } 2830e94d4478SAnirudh Venkataramanan 2831e94d4478SAnirudh Venkataramanan if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) 2832e94d4478SAnirudh Venkataramanan err = dev_uc_add_excl(dev, addr); 2833e94d4478SAnirudh Venkataramanan else if (is_multicast_ether_addr(addr)) 2834e94d4478SAnirudh Venkataramanan err = dev_mc_add_excl(dev, addr); 2835e94d4478SAnirudh Venkataramanan else 2836e94d4478SAnirudh Venkataramanan err = -EINVAL; 2837e94d4478SAnirudh Venkataramanan 2838e94d4478SAnirudh Venkataramanan /* Only return duplicate errors if NLM_F_EXCL is set */ 2839e94d4478SAnirudh Venkataramanan if (err == -EEXIST && !(flags & NLM_F_EXCL)) 2840e94d4478SAnirudh Venkataramanan err = 0; 2841e94d4478SAnirudh Venkataramanan 2842e94d4478SAnirudh Venkataramanan return err; 2843e94d4478SAnirudh Venkataramanan } 2844e94d4478SAnirudh Venkataramanan 2845e94d4478SAnirudh Venkataramanan /** 2846e94d4478SAnirudh Venkataramanan * ice_fdb_del - delete an entry from the hardware database 2847e94d4478SAnirudh Venkataramanan * @ndm: the input from the stack 2848e94d4478SAnirudh Venkataramanan * @tb: pointer to array of nladdr (unused) 2849e94d4478SAnirudh Venkataramanan * @dev: the net device pointer 2850e94d4478SAnirudh Venkataramanan * @addr: the MAC address entry being added 2851f9867df6SAnirudh Venkataramanan * @vid: VLAN ID 2852e94d4478SAnirudh Venkataramanan */ 2853c8b7abddSBruce Allan static int 2854c8b7abddSBruce Allan ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[], 2855e94d4478SAnirudh Venkataramanan struct net_device *dev, const unsigned char *addr, 2856e94d4478SAnirudh Venkataramanan __always_unused u16 vid) 2857e94d4478SAnirudh Venkataramanan { 2858e94d4478SAnirudh Venkataramanan int err; 2859e94d4478SAnirudh Venkataramanan 2860e94d4478SAnirudh Venkataramanan if (ndm->ndm_state & NUD_PERMANENT) { 2861e94d4478SAnirudh Venkataramanan netdev_err(dev, "FDB only supports static addresses\n"); 2862e94d4478SAnirudh Venkataramanan return -EINVAL; 2863e94d4478SAnirudh Venkataramanan } 2864e94d4478SAnirudh Venkataramanan 2865e94d4478SAnirudh Venkataramanan if (is_unicast_ether_addr(addr)) 2866e94d4478SAnirudh Venkataramanan err = dev_uc_del(dev, addr); 2867e94d4478SAnirudh Venkataramanan else if (is_multicast_ether_addr(addr)) 2868e94d4478SAnirudh Venkataramanan err = dev_mc_del(dev, addr); 2869e94d4478SAnirudh Venkataramanan else 2870e94d4478SAnirudh Venkataramanan err = -EINVAL; 2871e94d4478SAnirudh Venkataramanan 2872e94d4478SAnirudh Venkataramanan return err; 2873e94d4478SAnirudh Venkataramanan } 2874e94d4478SAnirudh Venkataramanan 2875e94d4478SAnirudh Venkataramanan /** 2876d76a60baSAnirudh Venkataramanan * ice_set_features - set the netdev feature flags 2877d76a60baSAnirudh Venkataramanan * @netdev: ptr to the netdev being adjusted 2878d76a60baSAnirudh Venkataramanan * @features: the feature set that the stack is suggesting 2879d76a60baSAnirudh Venkataramanan */ 2880c8b7abddSBruce Allan static int 2881c8b7abddSBruce Allan ice_set_features(struct net_device *netdev, netdev_features_t features) 2882d76a60baSAnirudh Venkataramanan { 2883d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2884d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2885d76a60baSAnirudh Venkataramanan int ret = 0; 2886d76a60baSAnirudh Venkataramanan 2887492af0abSMd Fahad Iqbal Polash if (features & NETIF_F_RXHASH && !(netdev->features & NETIF_F_RXHASH)) 2888492af0abSMd Fahad Iqbal Polash ret = ice_vsi_manage_rss_lut(vsi, true); 2889492af0abSMd Fahad Iqbal Polash else if (!(features & NETIF_F_RXHASH) && 2890492af0abSMd Fahad Iqbal Polash netdev->features & NETIF_F_RXHASH) 2891492af0abSMd Fahad Iqbal Polash ret = ice_vsi_manage_rss_lut(vsi, false); 2892492af0abSMd Fahad Iqbal Polash 2893d76a60baSAnirudh Venkataramanan if ((features & NETIF_F_HW_VLAN_CTAG_RX) && 2894d76a60baSAnirudh Venkataramanan !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) 2895d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, true); 2896d76a60baSAnirudh Venkataramanan else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && 2897d76a60baSAnirudh Venkataramanan (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) 2898d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, false); 2899d76a60baSAnirudh Venkataramanan else if ((features & NETIF_F_HW_VLAN_CTAG_TX) && 2900d76a60baSAnirudh Venkataramanan !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) 2901d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2902d76a60baSAnirudh Venkataramanan else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) && 2903d76a60baSAnirudh Venkataramanan (netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) 2904d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2905d76a60baSAnirudh Venkataramanan 2906d76a60baSAnirudh Venkataramanan return ret; 2907d76a60baSAnirudh Venkataramanan } 2908d76a60baSAnirudh Venkataramanan 2909d76a60baSAnirudh Venkataramanan /** 2910f9867df6SAnirudh Venkataramanan * ice_vsi_vlan_setup - Setup VLAN offload properties on a VSI 2911f9867df6SAnirudh Venkataramanan * @vsi: VSI to setup VLAN properties for 2912d76a60baSAnirudh Venkataramanan */ 2913d76a60baSAnirudh Venkataramanan static int ice_vsi_vlan_setup(struct ice_vsi *vsi) 2914d76a60baSAnirudh Venkataramanan { 2915d76a60baSAnirudh Venkataramanan int ret = 0; 2916d76a60baSAnirudh Venkataramanan 2917d76a60baSAnirudh Venkataramanan if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) 2918d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, true); 2919d76a60baSAnirudh Venkataramanan if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX) 2920d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2921d76a60baSAnirudh Venkataramanan 2922d76a60baSAnirudh Venkataramanan return ret; 2923d76a60baSAnirudh Venkataramanan } 2924d76a60baSAnirudh Venkataramanan 2925d76a60baSAnirudh Venkataramanan /** 2926cdedef59SAnirudh Venkataramanan * ice_vsi_cfg - Setup the VSI 2927cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 2928cdedef59SAnirudh Venkataramanan * 2929cdedef59SAnirudh Venkataramanan * Return 0 on success and negative value on error 2930cdedef59SAnirudh Venkataramanan */ 2931cdedef59SAnirudh Venkataramanan static int ice_vsi_cfg(struct ice_vsi *vsi) 2932cdedef59SAnirudh Venkataramanan { 2933cdedef59SAnirudh Venkataramanan int err; 2934cdedef59SAnirudh Venkataramanan 2935c7f2c42bSAnirudh Venkataramanan if (vsi->netdev) { 2936e94d4478SAnirudh Venkataramanan ice_set_rx_mode(vsi->netdev); 29379ecd25c2SAnirudh Venkataramanan 29389ecd25c2SAnirudh Venkataramanan err = ice_vsi_vlan_setup(vsi); 29399ecd25c2SAnirudh Venkataramanan 2940d76a60baSAnirudh Venkataramanan if (err) 2941d76a60baSAnirudh Venkataramanan return err; 2942c7f2c42bSAnirudh Venkataramanan } 2943a629cf0aSAnirudh Venkataramanan ice_vsi_cfg_dcb_rings(vsi); 294403f7a986SAnirudh Venkataramanan 294503f7a986SAnirudh Venkataramanan err = ice_vsi_cfg_lan_txqs(vsi); 2946cdedef59SAnirudh Venkataramanan if (!err) 2947cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg_rxqs(vsi); 2948cdedef59SAnirudh Venkataramanan 2949cdedef59SAnirudh Venkataramanan return err; 2950cdedef59SAnirudh Venkataramanan } 2951cdedef59SAnirudh Venkataramanan 2952cdedef59SAnirudh Venkataramanan /** 29532b245cb2SAnirudh Venkataramanan * ice_napi_enable_all - Enable NAPI for all q_vectors in the VSI 29542b245cb2SAnirudh Venkataramanan * @vsi: the VSI being configured 29552b245cb2SAnirudh Venkataramanan */ 29562b245cb2SAnirudh Venkataramanan static void ice_napi_enable_all(struct ice_vsi *vsi) 29572b245cb2SAnirudh Venkataramanan { 29582b245cb2SAnirudh Venkataramanan int q_idx; 29592b245cb2SAnirudh Venkataramanan 29602b245cb2SAnirudh Venkataramanan if (!vsi->netdev) 29612b245cb2SAnirudh Venkataramanan return; 29622b245cb2SAnirudh Venkataramanan 2963eec90376SYoung Xiao for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) { 2964eec90376SYoung Xiao struct ice_q_vector *q_vector = vsi->q_vectors[q_idx]; 2965eec90376SYoung Xiao 2966eec90376SYoung Xiao if (q_vector->rx.ring || q_vector->tx.ring) 2967eec90376SYoung Xiao napi_enable(&q_vector->napi); 2968eec90376SYoung Xiao } 29692b245cb2SAnirudh Venkataramanan } 29702b245cb2SAnirudh Venkataramanan 29712b245cb2SAnirudh Venkataramanan /** 2972cdedef59SAnirudh Venkataramanan * ice_up_complete - Finish the last steps of bringing up a connection 2973cdedef59SAnirudh Venkataramanan * @vsi: The VSI being configured 2974cdedef59SAnirudh Venkataramanan * 2975cdedef59SAnirudh Venkataramanan * Return 0 on success and negative value on error 2976cdedef59SAnirudh Venkataramanan */ 2977cdedef59SAnirudh Venkataramanan static int ice_up_complete(struct ice_vsi *vsi) 2978cdedef59SAnirudh Venkataramanan { 2979cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2980cdedef59SAnirudh Venkataramanan int err; 2981cdedef59SAnirudh Venkataramanan 2982cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 2983cdedef59SAnirudh Venkataramanan ice_vsi_cfg_msix(vsi); 2984cdedef59SAnirudh Venkataramanan else 2985cdedef59SAnirudh Venkataramanan return -ENOTSUPP; 2986cdedef59SAnirudh Venkataramanan 2987cdedef59SAnirudh Venkataramanan /* Enable only Rx rings, Tx rings were enabled by the FW when the 2988cdedef59SAnirudh Venkataramanan * Tx queue group list was configured and the context bits were 2989cdedef59SAnirudh Venkataramanan * programmed using ice_vsi_cfg_txqs 2990cdedef59SAnirudh Venkataramanan */ 2991cdedef59SAnirudh Venkataramanan err = ice_vsi_start_rx_rings(vsi); 2992cdedef59SAnirudh Venkataramanan if (err) 2993cdedef59SAnirudh Venkataramanan return err; 2994cdedef59SAnirudh Venkataramanan 2995cdedef59SAnirudh Venkataramanan clear_bit(__ICE_DOWN, vsi->state); 29962b245cb2SAnirudh Venkataramanan ice_napi_enable_all(vsi); 2997cdedef59SAnirudh Venkataramanan ice_vsi_ena_irq(vsi); 2998cdedef59SAnirudh Venkataramanan 2999cdedef59SAnirudh Venkataramanan if (vsi->port_info && 3000cdedef59SAnirudh Venkataramanan (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) && 3001cdedef59SAnirudh Venkataramanan vsi->netdev) { 3002cdedef59SAnirudh Venkataramanan ice_print_link_msg(vsi, true); 3003cdedef59SAnirudh Venkataramanan netif_tx_start_all_queues(vsi->netdev); 3004cdedef59SAnirudh Venkataramanan netif_carrier_on(vsi->netdev); 3005cdedef59SAnirudh Venkataramanan } 3006cdedef59SAnirudh Venkataramanan 3007cdedef59SAnirudh Venkataramanan ice_service_task_schedule(pf); 3008cdedef59SAnirudh Venkataramanan 30091b5c19c7SBruce Allan return 0; 3010cdedef59SAnirudh Venkataramanan } 3011cdedef59SAnirudh Venkataramanan 3012cdedef59SAnirudh Venkataramanan /** 3013fcea6f3dSAnirudh Venkataramanan * ice_up - Bring the connection back up after being down 3014fcea6f3dSAnirudh Venkataramanan * @vsi: VSI being configured 3015fcea6f3dSAnirudh Venkataramanan */ 3016fcea6f3dSAnirudh Venkataramanan int ice_up(struct ice_vsi *vsi) 3017fcea6f3dSAnirudh Venkataramanan { 3018fcea6f3dSAnirudh Venkataramanan int err; 3019fcea6f3dSAnirudh Venkataramanan 3020fcea6f3dSAnirudh Venkataramanan err = ice_vsi_cfg(vsi); 3021fcea6f3dSAnirudh Venkataramanan if (!err) 3022fcea6f3dSAnirudh Venkataramanan err = ice_up_complete(vsi); 3023fcea6f3dSAnirudh Venkataramanan 3024fcea6f3dSAnirudh Venkataramanan return err; 3025fcea6f3dSAnirudh Venkataramanan } 3026fcea6f3dSAnirudh Venkataramanan 3027fcea6f3dSAnirudh Venkataramanan /** 3028fcea6f3dSAnirudh Venkataramanan * ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring 3029fcea6f3dSAnirudh Venkataramanan * @ring: Tx or Rx ring to read stats from 3030fcea6f3dSAnirudh Venkataramanan * @pkts: packets stats counter 3031fcea6f3dSAnirudh Venkataramanan * @bytes: bytes stats counter 3032fcea6f3dSAnirudh Venkataramanan * 3033fcea6f3dSAnirudh Venkataramanan * This function fetches stats from the ring considering the atomic operations 3034fcea6f3dSAnirudh Venkataramanan * that needs to be performed to read u64 values in 32 bit machine. 3035fcea6f3dSAnirudh Venkataramanan */ 3036c8b7abddSBruce Allan static void 3037c8b7abddSBruce Allan ice_fetch_u64_stats_per_ring(struct ice_ring *ring, u64 *pkts, u64 *bytes) 3038fcea6f3dSAnirudh Venkataramanan { 3039fcea6f3dSAnirudh Venkataramanan unsigned int start; 3040fcea6f3dSAnirudh Venkataramanan *pkts = 0; 3041fcea6f3dSAnirudh Venkataramanan *bytes = 0; 3042fcea6f3dSAnirudh Venkataramanan 3043fcea6f3dSAnirudh Venkataramanan if (!ring) 3044fcea6f3dSAnirudh Venkataramanan return; 3045fcea6f3dSAnirudh Venkataramanan do { 3046fcea6f3dSAnirudh Venkataramanan start = u64_stats_fetch_begin_irq(&ring->syncp); 3047fcea6f3dSAnirudh Venkataramanan *pkts = ring->stats.pkts; 3048fcea6f3dSAnirudh Venkataramanan *bytes = ring->stats.bytes; 3049fcea6f3dSAnirudh Venkataramanan } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 3050fcea6f3dSAnirudh Venkataramanan } 3051fcea6f3dSAnirudh Venkataramanan 3052fcea6f3dSAnirudh Venkataramanan /** 3053fcea6f3dSAnirudh Venkataramanan * ice_update_vsi_ring_stats - Update VSI stats counters 3054fcea6f3dSAnirudh Venkataramanan * @vsi: the VSI to be updated 3055fcea6f3dSAnirudh Venkataramanan */ 3056fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) 3057fcea6f3dSAnirudh Venkataramanan { 3058fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats; 3059fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 3060fcea6f3dSAnirudh Venkataramanan u64 pkts, bytes; 3061fcea6f3dSAnirudh Venkataramanan int i; 3062fcea6f3dSAnirudh Venkataramanan 3063fcea6f3dSAnirudh Venkataramanan /* reset netdev stats */ 3064fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_packets = 0; 3065fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_bytes = 0; 3066fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_packets = 0; 3067fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_bytes = 0; 3068fcea6f3dSAnirudh Venkataramanan 3069fcea6f3dSAnirudh Venkataramanan /* reset non-netdev (extended) stats */ 3070fcea6f3dSAnirudh Venkataramanan vsi->tx_restart = 0; 3071fcea6f3dSAnirudh Venkataramanan vsi->tx_busy = 0; 3072fcea6f3dSAnirudh Venkataramanan vsi->tx_linearize = 0; 3073fcea6f3dSAnirudh Venkataramanan vsi->rx_buf_failed = 0; 3074fcea6f3dSAnirudh Venkataramanan vsi->rx_page_failed = 0; 3075fcea6f3dSAnirudh Venkataramanan 3076fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 3077fcea6f3dSAnirudh Venkataramanan 3078fcea6f3dSAnirudh Venkataramanan /* update Tx rings counters */ 3079fcea6f3dSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 3080fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[i]); 3081fcea6f3dSAnirudh Venkataramanan ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes); 3082fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_packets += pkts; 3083fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_bytes += bytes; 3084fcea6f3dSAnirudh Venkataramanan vsi->tx_restart += ring->tx_stats.restart_q; 3085fcea6f3dSAnirudh Venkataramanan vsi->tx_busy += ring->tx_stats.tx_busy; 3086fcea6f3dSAnirudh Venkataramanan vsi->tx_linearize += ring->tx_stats.tx_linearize; 3087fcea6f3dSAnirudh Venkataramanan } 3088fcea6f3dSAnirudh Venkataramanan 3089fcea6f3dSAnirudh Venkataramanan /* update Rx rings counters */ 3090fcea6f3dSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 3091fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[i]); 3092fcea6f3dSAnirudh Venkataramanan ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes); 3093fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_packets += pkts; 3094fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_bytes += bytes; 3095fcea6f3dSAnirudh Venkataramanan vsi->rx_buf_failed += ring->rx_stats.alloc_buf_failed; 3096fcea6f3dSAnirudh Venkataramanan vsi->rx_page_failed += ring->rx_stats.alloc_page_failed; 3097fcea6f3dSAnirudh Venkataramanan } 3098fcea6f3dSAnirudh Venkataramanan 3099fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 3100fcea6f3dSAnirudh Venkataramanan } 3101fcea6f3dSAnirudh Venkataramanan 3102fcea6f3dSAnirudh Venkataramanan /** 3103fcea6f3dSAnirudh Venkataramanan * ice_update_vsi_stats - Update VSI stats counters 3104fcea6f3dSAnirudh Venkataramanan * @vsi: the VSI to be updated 3105fcea6f3dSAnirudh Venkataramanan */ 3106fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi) 3107fcea6f3dSAnirudh Venkataramanan { 3108fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *cur_ns = &vsi->net_stats; 3109fcea6f3dSAnirudh Venkataramanan struct ice_eth_stats *cur_es = &vsi->eth_stats; 3110fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3111fcea6f3dSAnirudh Venkataramanan 3112fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state) || 3113fcea6f3dSAnirudh Venkataramanan test_bit(__ICE_CFG_BUSY, pf->state)) 3114fcea6f3dSAnirudh Venkataramanan return; 3115fcea6f3dSAnirudh Venkataramanan 3116fcea6f3dSAnirudh Venkataramanan /* get stats as recorded by Tx/Rx rings */ 3117fcea6f3dSAnirudh Venkataramanan ice_update_vsi_ring_stats(vsi); 3118fcea6f3dSAnirudh Venkataramanan 3119fcea6f3dSAnirudh Venkataramanan /* get VSI stats as recorded by the hardware */ 3120fcea6f3dSAnirudh Venkataramanan ice_update_eth_stats(vsi); 3121fcea6f3dSAnirudh Venkataramanan 3122fcea6f3dSAnirudh Venkataramanan cur_ns->tx_errors = cur_es->tx_errors; 3123fcea6f3dSAnirudh Venkataramanan cur_ns->rx_dropped = cur_es->rx_discards; 3124fcea6f3dSAnirudh Venkataramanan cur_ns->tx_dropped = cur_es->tx_discards; 3125fcea6f3dSAnirudh Venkataramanan cur_ns->multicast = cur_es->rx_multicast; 3126fcea6f3dSAnirudh Venkataramanan 3127fcea6f3dSAnirudh Venkataramanan /* update some more netdev stats if this is main VSI */ 3128fcea6f3dSAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 3129fcea6f3dSAnirudh Venkataramanan cur_ns->rx_crc_errors = pf->stats.crc_errors; 3130fcea6f3dSAnirudh Venkataramanan cur_ns->rx_errors = pf->stats.crc_errors + 3131fcea6f3dSAnirudh Venkataramanan pf->stats.illegal_bytes; 3132fcea6f3dSAnirudh Venkataramanan cur_ns->rx_length_errors = pf->stats.rx_len_errors; 3133fcea6f3dSAnirudh Venkataramanan } 3134fcea6f3dSAnirudh Venkataramanan } 3135fcea6f3dSAnirudh Venkataramanan 3136fcea6f3dSAnirudh Venkataramanan /** 3137fcea6f3dSAnirudh Venkataramanan * ice_update_pf_stats - Update PF port stats counters 3138fcea6f3dSAnirudh Venkataramanan * @pf: PF whose stats needs to be updated 3139fcea6f3dSAnirudh Venkataramanan */ 3140fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf) 3141fcea6f3dSAnirudh Venkataramanan { 3142fcea6f3dSAnirudh Venkataramanan struct ice_hw_port_stats *prev_ps, *cur_ps; 3143fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3144fcea6f3dSAnirudh Venkataramanan u8 pf_id; 3145fcea6f3dSAnirudh Venkataramanan 3146fcea6f3dSAnirudh Venkataramanan prev_ps = &pf->stats_prev; 3147fcea6f3dSAnirudh Venkataramanan cur_ps = &pf->stats; 3148fcea6f3dSAnirudh Venkataramanan pf_id = hw->pf_id; 3149fcea6f3dSAnirudh Venkataramanan 3150fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_GORCH(pf_id), GLPRT_GORCL(pf_id), 3151fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_bytes, 3152fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_bytes); 3153fcea6f3dSAnirudh Venkataramanan 3154fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_UPRCH(pf_id), GLPRT_UPRCL(pf_id), 3155fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_unicast, 3156fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_unicast); 3157fcea6f3dSAnirudh Venkataramanan 3158fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_MPRCH(pf_id), GLPRT_MPRCL(pf_id), 3159fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_multicast, 3160fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_multicast); 3161fcea6f3dSAnirudh Venkataramanan 3162fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_BPRCH(pf_id), GLPRT_BPRCL(pf_id), 3163fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_broadcast, 3164fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_broadcast); 3165fcea6f3dSAnirudh Venkataramanan 3166fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_GOTCH(pf_id), GLPRT_GOTCL(pf_id), 3167fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_bytes, 3168fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_bytes); 3169fcea6f3dSAnirudh Venkataramanan 3170fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_UPTCH(pf_id), GLPRT_UPTCL(pf_id), 3171fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_unicast, 3172fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_unicast); 3173fcea6f3dSAnirudh Venkataramanan 3174fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_MPTCH(pf_id), GLPRT_MPTCL(pf_id), 3175fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_multicast, 3176fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_multicast); 3177fcea6f3dSAnirudh Venkataramanan 3178fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_BPTCH(pf_id), GLPRT_BPTCL(pf_id), 3179fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_broadcast, 3180fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_broadcast); 3181fcea6f3dSAnirudh Venkataramanan 3182fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_TDOLD(pf_id), pf->stat_prev_loaded, 3183fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_dropped_link_down, 3184fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_dropped_link_down); 3185fcea6f3dSAnirudh Venkataramanan 3186fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC64H(pf_id), GLPRT_PRC64L(pf_id), 3187fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_64, 3188fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_64); 3189fcea6f3dSAnirudh Venkataramanan 3190fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC127H(pf_id), GLPRT_PRC127L(pf_id), 3191fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_127, 3192fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_127); 3193fcea6f3dSAnirudh Venkataramanan 3194fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC255H(pf_id), GLPRT_PRC255L(pf_id), 3195fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_255, 3196fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_255); 3197fcea6f3dSAnirudh Venkataramanan 3198fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC511H(pf_id), GLPRT_PRC511L(pf_id), 3199fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_511, 3200fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_511); 3201fcea6f3dSAnirudh Venkataramanan 3202fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC1023H(pf_id), 3203fcea6f3dSAnirudh Venkataramanan GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded, 3204fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_1023, &cur_ps->rx_size_1023); 3205fcea6f3dSAnirudh Venkataramanan 3206fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC1522H(pf_id), 3207fcea6f3dSAnirudh Venkataramanan GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded, 3208fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_1522, &cur_ps->rx_size_1522); 3209fcea6f3dSAnirudh Venkataramanan 3210fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC9522H(pf_id), 3211fcea6f3dSAnirudh Venkataramanan GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded, 3212fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_big, &cur_ps->rx_size_big); 3213fcea6f3dSAnirudh Venkataramanan 3214fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC64H(pf_id), GLPRT_PTC64L(pf_id), 3215fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_64, 3216fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_64); 3217fcea6f3dSAnirudh Venkataramanan 3218fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC127H(pf_id), GLPRT_PTC127L(pf_id), 3219fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_127, 3220fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_127); 3221fcea6f3dSAnirudh Venkataramanan 3222fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC255H(pf_id), GLPRT_PTC255L(pf_id), 3223fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_255, 3224fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_255); 3225fcea6f3dSAnirudh Venkataramanan 3226fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC511H(pf_id), GLPRT_PTC511L(pf_id), 3227fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_511, 3228fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_511); 3229fcea6f3dSAnirudh Venkataramanan 3230fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC1023H(pf_id), 3231fcea6f3dSAnirudh Venkataramanan GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded, 3232fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_1023, &cur_ps->tx_size_1023); 3233fcea6f3dSAnirudh Venkataramanan 3234fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC1522H(pf_id), 3235fcea6f3dSAnirudh Venkataramanan GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded, 3236fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_1522, &cur_ps->tx_size_1522); 3237fcea6f3dSAnirudh Venkataramanan 3238fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC9522H(pf_id), 3239fcea6f3dSAnirudh Venkataramanan GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded, 3240fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_big, &cur_ps->tx_size_big); 3241fcea6f3dSAnirudh Venkataramanan 3242fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXONRXC(pf_id), pf->stat_prev_loaded, 3243fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xon_rx, &cur_ps->link_xon_rx); 3244fcea6f3dSAnirudh Venkataramanan 3245fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXOFFRXC(pf_id), pf->stat_prev_loaded, 3246fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xoff_rx, &cur_ps->link_xoff_rx); 3247fcea6f3dSAnirudh Venkataramanan 3248fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXONTXC(pf_id), pf->stat_prev_loaded, 3249fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xon_tx, &cur_ps->link_xon_tx); 3250fcea6f3dSAnirudh Venkataramanan 3251fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXOFFTXC(pf_id), pf->stat_prev_loaded, 3252fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xoff_tx, &cur_ps->link_xoff_tx); 3253fcea6f3dSAnirudh Venkataramanan 3254fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_CRCERRS(pf_id), pf->stat_prev_loaded, 3255fcea6f3dSAnirudh Venkataramanan &prev_ps->crc_errors, &cur_ps->crc_errors); 3256fcea6f3dSAnirudh Venkataramanan 3257fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_ILLERRC(pf_id), pf->stat_prev_loaded, 3258fcea6f3dSAnirudh Venkataramanan &prev_ps->illegal_bytes, &cur_ps->illegal_bytes); 3259fcea6f3dSAnirudh Venkataramanan 3260fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_MLFC(pf_id), pf->stat_prev_loaded, 3261fcea6f3dSAnirudh Venkataramanan &prev_ps->mac_local_faults, 3262fcea6f3dSAnirudh Venkataramanan &cur_ps->mac_local_faults); 3263fcea6f3dSAnirudh Venkataramanan 3264fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_MRFC(pf_id), pf->stat_prev_loaded, 3265fcea6f3dSAnirudh Venkataramanan &prev_ps->mac_remote_faults, 3266fcea6f3dSAnirudh Venkataramanan &cur_ps->mac_remote_faults); 3267fcea6f3dSAnirudh Venkataramanan 3268fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RLEC(pf_id), pf->stat_prev_loaded, 3269fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_len_errors, &cur_ps->rx_len_errors); 3270fcea6f3dSAnirudh Venkataramanan 3271fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RUC(pf_id), pf->stat_prev_loaded, 3272fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_undersize, &cur_ps->rx_undersize); 3273fcea6f3dSAnirudh Venkataramanan 3274fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RFC(pf_id), pf->stat_prev_loaded, 3275fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_fragments, &cur_ps->rx_fragments); 3276fcea6f3dSAnirudh Venkataramanan 3277fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_ROC(pf_id), pf->stat_prev_loaded, 3278fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_oversize, &cur_ps->rx_oversize); 3279fcea6f3dSAnirudh Venkataramanan 3280fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RJC(pf_id), pf->stat_prev_loaded, 3281fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_jabber, &cur_ps->rx_jabber); 3282fcea6f3dSAnirudh Venkataramanan 3283fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded = true; 3284fcea6f3dSAnirudh Venkataramanan } 3285fcea6f3dSAnirudh Venkataramanan 3286fcea6f3dSAnirudh Venkataramanan /** 3287fcea6f3dSAnirudh Venkataramanan * ice_get_stats64 - get statistics for network device structure 3288fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3289fcea6f3dSAnirudh Venkataramanan * @stats: main device statistics structure 3290fcea6f3dSAnirudh Venkataramanan */ 3291fcea6f3dSAnirudh Venkataramanan static 3292fcea6f3dSAnirudh Venkataramanan void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) 3293fcea6f3dSAnirudh Venkataramanan { 3294fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3295fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *vsi_stats; 3296fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3297fcea6f3dSAnirudh Venkataramanan 3298fcea6f3dSAnirudh Venkataramanan vsi_stats = &vsi->net_stats; 3299fcea6f3dSAnirudh Venkataramanan 3300fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state) || !vsi->num_txq || !vsi->num_rxq) 3301fcea6f3dSAnirudh Venkataramanan return; 3302fcea6f3dSAnirudh Venkataramanan /* netdev packet/byte stats come from ring counter. These are obtained 3303fcea6f3dSAnirudh Venkataramanan * by summing up ring counters (done by ice_update_vsi_ring_stats). 3304fcea6f3dSAnirudh Venkataramanan */ 3305fcea6f3dSAnirudh Venkataramanan ice_update_vsi_ring_stats(vsi); 3306fcea6f3dSAnirudh Venkataramanan stats->tx_packets = vsi_stats->tx_packets; 3307fcea6f3dSAnirudh Venkataramanan stats->tx_bytes = vsi_stats->tx_bytes; 3308fcea6f3dSAnirudh Venkataramanan stats->rx_packets = vsi_stats->rx_packets; 3309fcea6f3dSAnirudh Venkataramanan stats->rx_bytes = vsi_stats->rx_bytes; 3310fcea6f3dSAnirudh Venkataramanan 3311fcea6f3dSAnirudh Venkataramanan /* The rest of the stats can be read from the hardware but instead we 3312fcea6f3dSAnirudh Venkataramanan * just return values that the watchdog task has already obtained from 3313fcea6f3dSAnirudh Venkataramanan * the hardware. 3314fcea6f3dSAnirudh Venkataramanan */ 3315fcea6f3dSAnirudh Venkataramanan stats->multicast = vsi_stats->multicast; 3316fcea6f3dSAnirudh Venkataramanan stats->tx_errors = vsi_stats->tx_errors; 3317fcea6f3dSAnirudh Venkataramanan stats->tx_dropped = vsi_stats->tx_dropped; 3318fcea6f3dSAnirudh Venkataramanan stats->rx_errors = vsi_stats->rx_errors; 3319fcea6f3dSAnirudh Venkataramanan stats->rx_dropped = vsi_stats->rx_dropped; 3320fcea6f3dSAnirudh Venkataramanan stats->rx_crc_errors = vsi_stats->rx_crc_errors; 3321fcea6f3dSAnirudh Venkataramanan stats->rx_length_errors = vsi_stats->rx_length_errors; 3322fcea6f3dSAnirudh Venkataramanan } 3323fcea6f3dSAnirudh Venkataramanan 3324fcea6f3dSAnirudh Venkataramanan /** 33252b245cb2SAnirudh Venkataramanan * ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI 33262b245cb2SAnirudh Venkataramanan * @vsi: VSI having NAPI disabled 33272b245cb2SAnirudh Venkataramanan */ 33282b245cb2SAnirudh Venkataramanan static void ice_napi_disable_all(struct ice_vsi *vsi) 33292b245cb2SAnirudh Venkataramanan { 33302b245cb2SAnirudh Venkataramanan int q_idx; 33312b245cb2SAnirudh Venkataramanan 33322b245cb2SAnirudh Venkataramanan if (!vsi->netdev) 33332b245cb2SAnirudh Venkataramanan return; 33342b245cb2SAnirudh Venkataramanan 3335eec90376SYoung Xiao for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) { 3336eec90376SYoung Xiao struct ice_q_vector *q_vector = vsi->q_vectors[q_idx]; 3337eec90376SYoung Xiao 3338eec90376SYoung Xiao if (q_vector->rx.ring || q_vector->tx.ring) 3339eec90376SYoung Xiao napi_disable(&q_vector->napi); 3340eec90376SYoung Xiao } 33412b245cb2SAnirudh Venkataramanan } 33422b245cb2SAnirudh Venkataramanan 33432b245cb2SAnirudh Venkataramanan /** 3344b6f934f0SBrett Creeley * ice_force_phys_link_state - Force the physical link state 3345b6f934f0SBrett Creeley * @vsi: VSI to force the physical link state to up/down 3346b6f934f0SBrett Creeley * @link_up: true/false indicates to set the physical link to up/down 3347b6f934f0SBrett Creeley * 3348b6f934f0SBrett Creeley * Force the physical link state by getting the current PHY capabilities from 3349b6f934f0SBrett Creeley * hardware and setting the PHY config based on the determined capabilities. If 3350b6f934f0SBrett Creeley * link changes a link event will be triggered because both the Enable Automatic 3351b6f934f0SBrett Creeley * Link Update and LESM Enable bits are set when setting the PHY capabilities. 3352b6f934f0SBrett Creeley * 3353b6f934f0SBrett Creeley * Returns 0 on success, negative on failure 3354b6f934f0SBrett Creeley */ 3355b6f934f0SBrett Creeley static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up) 3356b6f934f0SBrett Creeley { 3357b6f934f0SBrett Creeley struct ice_aqc_get_phy_caps_data *pcaps; 3358b6f934f0SBrett Creeley struct ice_aqc_set_phy_cfg_data *cfg; 3359b6f934f0SBrett Creeley struct ice_port_info *pi; 3360b6f934f0SBrett Creeley struct device *dev; 3361b6f934f0SBrett Creeley int retcode; 3362b6f934f0SBrett Creeley 3363b6f934f0SBrett Creeley if (!vsi || !vsi->port_info || !vsi->back) 3364b6f934f0SBrett Creeley return -EINVAL; 3365b6f934f0SBrett Creeley if (vsi->type != ICE_VSI_PF) 3366b6f934f0SBrett Creeley return 0; 3367b6f934f0SBrett Creeley 3368b6f934f0SBrett Creeley dev = &vsi->back->pdev->dev; 3369b6f934f0SBrett Creeley 3370b6f934f0SBrett Creeley pi = vsi->port_info; 3371b6f934f0SBrett Creeley 3372b6f934f0SBrett Creeley pcaps = devm_kzalloc(dev, sizeof(*pcaps), GFP_KERNEL); 3373b6f934f0SBrett Creeley if (!pcaps) 3374b6f934f0SBrett Creeley return -ENOMEM; 3375b6f934f0SBrett Creeley 3376b6f934f0SBrett Creeley retcode = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 3377b6f934f0SBrett Creeley NULL); 3378b6f934f0SBrett Creeley if (retcode) { 3379b6f934f0SBrett Creeley dev_err(dev, 3380b6f934f0SBrett Creeley "Failed to get phy capabilities, VSI %d error %d\n", 3381b6f934f0SBrett Creeley vsi->vsi_num, retcode); 3382b6f934f0SBrett Creeley retcode = -EIO; 3383b6f934f0SBrett Creeley goto out; 3384b6f934f0SBrett Creeley } 3385b6f934f0SBrett Creeley 3386b6f934f0SBrett Creeley /* No change in link */ 3387b6f934f0SBrett Creeley if (link_up == !!(pcaps->caps & ICE_AQC_PHY_EN_LINK) && 3388b6f934f0SBrett Creeley link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP)) 3389b6f934f0SBrett Creeley goto out; 3390b6f934f0SBrett Creeley 3391b6f934f0SBrett Creeley cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); 3392b6f934f0SBrett Creeley if (!cfg) { 3393b6f934f0SBrett Creeley retcode = -ENOMEM; 3394b6f934f0SBrett Creeley goto out; 3395b6f934f0SBrett Creeley } 3396b6f934f0SBrett Creeley 3397b6f934f0SBrett Creeley cfg->phy_type_low = pcaps->phy_type_low; 3398b6f934f0SBrett Creeley cfg->phy_type_high = pcaps->phy_type_high; 3399b6f934f0SBrett Creeley cfg->caps = pcaps->caps | ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 3400b6f934f0SBrett Creeley cfg->low_power_ctrl = pcaps->low_power_ctrl; 3401b6f934f0SBrett Creeley cfg->eee_cap = pcaps->eee_cap; 3402b6f934f0SBrett Creeley cfg->eeer_value = pcaps->eeer_value; 3403b6f934f0SBrett Creeley cfg->link_fec_opt = pcaps->link_fec_options; 3404b6f934f0SBrett Creeley if (link_up) 3405b6f934f0SBrett Creeley cfg->caps |= ICE_AQ_PHY_ENA_LINK; 3406b6f934f0SBrett Creeley else 3407b6f934f0SBrett Creeley cfg->caps &= ~ICE_AQ_PHY_ENA_LINK; 3408b6f934f0SBrett Creeley 3409b6f934f0SBrett Creeley retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi->lport, cfg, NULL); 3410b6f934f0SBrett Creeley if (retcode) { 3411b6f934f0SBrett Creeley dev_err(dev, "Failed to set phy config, VSI %d error %d\n", 3412b6f934f0SBrett Creeley vsi->vsi_num, retcode); 3413b6f934f0SBrett Creeley retcode = -EIO; 3414b6f934f0SBrett Creeley } 3415b6f934f0SBrett Creeley 3416b6f934f0SBrett Creeley devm_kfree(dev, cfg); 3417b6f934f0SBrett Creeley out: 3418b6f934f0SBrett Creeley devm_kfree(dev, pcaps); 3419b6f934f0SBrett Creeley return retcode; 3420b6f934f0SBrett Creeley } 3421b6f934f0SBrett Creeley 3422b6f934f0SBrett Creeley /** 3423cdedef59SAnirudh Venkataramanan * ice_down - Shutdown the connection 3424cdedef59SAnirudh Venkataramanan * @vsi: The VSI being stopped 3425cdedef59SAnirudh Venkataramanan */ 3426fcea6f3dSAnirudh Venkataramanan int ice_down(struct ice_vsi *vsi) 3427cdedef59SAnirudh Venkataramanan { 3428ab4ab73fSBruce Allan int i, tx_err, rx_err, link_err = 0; 3429cdedef59SAnirudh Venkataramanan 3430cdedef59SAnirudh Venkataramanan /* Caller of this function is expected to set the 3431cdedef59SAnirudh Venkataramanan * vsi->state __ICE_DOWN bit 3432cdedef59SAnirudh Venkataramanan */ 3433cdedef59SAnirudh Venkataramanan if (vsi->netdev) { 3434cdedef59SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 3435cdedef59SAnirudh Venkataramanan netif_tx_disable(vsi->netdev); 3436cdedef59SAnirudh Venkataramanan } 3437cdedef59SAnirudh Venkataramanan 3438cdedef59SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 343903f7a986SAnirudh Venkataramanan 344003f7a986SAnirudh Venkataramanan tx_err = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); 344172adf242SAnirudh Venkataramanan if (tx_err) 344272adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 344372adf242SAnirudh Venkataramanan "Failed stop Tx rings, VSI %d error %d\n", 344472adf242SAnirudh Venkataramanan vsi->vsi_num, tx_err); 344572adf242SAnirudh Venkataramanan 344672adf242SAnirudh Venkataramanan rx_err = ice_vsi_stop_rx_rings(vsi); 344772adf242SAnirudh Venkataramanan if (rx_err) 344872adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 344972adf242SAnirudh Venkataramanan "Failed stop Rx rings, VSI %d error %d\n", 345072adf242SAnirudh Venkataramanan vsi->vsi_num, rx_err); 345172adf242SAnirudh Venkataramanan 34522b245cb2SAnirudh Venkataramanan ice_napi_disable_all(vsi); 3453cdedef59SAnirudh Venkataramanan 3454ab4ab73fSBruce Allan if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) { 3455b6f934f0SBrett Creeley link_err = ice_force_phys_link_state(vsi, false); 3456b6f934f0SBrett Creeley if (link_err) 3457b6f934f0SBrett Creeley netdev_err(vsi->netdev, 3458b6f934f0SBrett Creeley "Failed to set physical link down, VSI %d error %d\n", 3459b6f934f0SBrett Creeley vsi->vsi_num, link_err); 3460ab4ab73fSBruce Allan } 3461b6f934f0SBrett Creeley 3462cdedef59SAnirudh Venkataramanan ice_for_each_txq(vsi, i) 3463cdedef59SAnirudh Venkataramanan ice_clean_tx_ring(vsi->tx_rings[i]); 3464cdedef59SAnirudh Venkataramanan 3465cdedef59SAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 3466cdedef59SAnirudh Venkataramanan ice_clean_rx_ring(vsi->rx_rings[i]); 3467cdedef59SAnirudh Venkataramanan 3468b6f934f0SBrett Creeley if (tx_err || rx_err || link_err) { 346972adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 347072adf242SAnirudh Venkataramanan "Failed to close VSI 0x%04X on switch 0x%04X\n", 3471cdedef59SAnirudh Venkataramanan vsi->vsi_num, vsi->vsw->sw_id); 347272adf242SAnirudh Venkataramanan return -EIO; 347372adf242SAnirudh Venkataramanan } 347472adf242SAnirudh Venkataramanan 347572adf242SAnirudh Venkataramanan return 0; 3476cdedef59SAnirudh Venkataramanan } 3477cdedef59SAnirudh Venkataramanan 3478cdedef59SAnirudh Venkataramanan /** 3479cdedef59SAnirudh Venkataramanan * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources 3480cdedef59SAnirudh Venkataramanan * @vsi: VSI having resources allocated 3481cdedef59SAnirudh Venkataramanan * 3482cdedef59SAnirudh Venkataramanan * Return 0 on success, negative on failure 3483cdedef59SAnirudh Venkataramanan */ 3484cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi) 3485cdedef59SAnirudh Venkataramanan { 3486dab0588fSJesse Brandeburg int i, err = 0; 3487cdedef59SAnirudh Venkataramanan 3488cdedef59SAnirudh Venkataramanan if (!vsi->num_txq) { 3489cdedef59SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Tx queues\n", 3490cdedef59SAnirudh Venkataramanan vsi->vsi_num); 3491cdedef59SAnirudh Venkataramanan return -EINVAL; 3492cdedef59SAnirudh Venkataramanan } 3493cdedef59SAnirudh Venkataramanan 3494cdedef59SAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 349572adf242SAnirudh Venkataramanan vsi->tx_rings[i]->netdev = vsi->netdev; 3496cdedef59SAnirudh Venkataramanan err = ice_setup_tx_ring(vsi->tx_rings[i]); 3497cdedef59SAnirudh Venkataramanan if (err) 3498cdedef59SAnirudh Venkataramanan break; 3499cdedef59SAnirudh Venkataramanan } 3500cdedef59SAnirudh Venkataramanan 3501cdedef59SAnirudh Venkataramanan return err; 3502cdedef59SAnirudh Venkataramanan } 3503cdedef59SAnirudh Venkataramanan 3504cdedef59SAnirudh Venkataramanan /** 3505cdedef59SAnirudh Venkataramanan * ice_vsi_setup_rx_rings - Allocate VSI Rx queue resources 3506cdedef59SAnirudh Venkataramanan * @vsi: VSI having resources allocated 3507cdedef59SAnirudh Venkataramanan * 3508cdedef59SAnirudh Venkataramanan * Return 0 on success, negative on failure 3509cdedef59SAnirudh Venkataramanan */ 3510cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi) 3511cdedef59SAnirudh Venkataramanan { 3512dab0588fSJesse Brandeburg int i, err = 0; 3513cdedef59SAnirudh Venkataramanan 3514cdedef59SAnirudh Venkataramanan if (!vsi->num_rxq) { 3515cdedef59SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Rx queues\n", 3516cdedef59SAnirudh Venkataramanan vsi->vsi_num); 3517cdedef59SAnirudh Venkataramanan return -EINVAL; 3518cdedef59SAnirudh Venkataramanan } 3519cdedef59SAnirudh Venkataramanan 3520cdedef59SAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 352172adf242SAnirudh Venkataramanan vsi->rx_rings[i]->netdev = vsi->netdev; 3522cdedef59SAnirudh Venkataramanan err = ice_setup_rx_ring(vsi->rx_rings[i]); 3523cdedef59SAnirudh Venkataramanan if (err) 3524cdedef59SAnirudh Venkataramanan break; 3525cdedef59SAnirudh Venkataramanan } 3526cdedef59SAnirudh Venkataramanan 3527cdedef59SAnirudh Venkataramanan return err; 3528cdedef59SAnirudh Venkataramanan } 3529cdedef59SAnirudh Venkataramanan 3530cdedef59SAnirudh Venkataramanan /** 3531cdedef59SAnirudh Venkataramanan * ice_vsi_req_irq - Request IRQ from the OS 3532cdedef59SAnirudh Venkataramanan * @vsi: The VSI IRQ is being requested for 3533cdedef59SAnirudh Venkataramanan * @basename: name for the vector 3534cdedef59SAnirudh Venkataramanan * 3535cdedef59SAnirudh Venkataramanan * Return 0 on success and a negative value on error 3536cdedef59SAnirudh Venkataramanan */ 3537cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq(struct ice_vsi *vsi, char *basename) 3538cdedef59SAnirudh Venkataramanan { 3539cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3540cdedef59SAnirudh Venkataramanan int err = -EINVAL; 3541cdedef59SAnirudh Venkataramanan 3542cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 3543cdedef59SAnirudh Venkataramanan err = ice_vsi_req_irq_msix(vsi, basename); 3544cdedef59SAnirudh Venkataramanan 3545cdedef59SAnirudh Venkataramanan return err; 3546cdedef59SAnirudh Venkataramanan } 3547cdedef59SAnirudh Venkataramanan 3548cdedef59SAnirudh Venkataramanan /** 3549cdedef59SAnirudh Venkataramanan * ice_vsi_open - Called when a network interface is made active 3550cdedef59SAnirudh Venkataramanan * @vsi: the VSI to open 3551cdedef59SAnirudh Venkataramanan * 3552cdedef59SAnirudh Venkataramanan * Initialization of the VSI 3553cdedef59SAnirudh Venkataramanan * 3554cdedef59SAnirudh Venkataramanan * Returns 0 on success, negative value on error 3555cdedef59SAnirudh Venkataramanan */ 3556cdedef59SAnirudh Venkataramanan static int ice_vsi_open(struct ice_vsi *vsi) 3557cdedef59SAnirudh Venkataramanan { 3558cdedef59SAnirudh Venkataramanan char int_name[ICE_INT_NAME_STR_LEN]; 3559cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3560cdedef59SAnirudh Venkataramanan int err; 3561cdedef59SAnirudh Venkataramanan 3562cdedef59SAnirudh Venkataramanan /* allocate descriptors */ 3563cdedef59SAnirudh Venkataramanan err = ice_vsi_setup_tx_rings(vsi); 3564cdedef59SAnirudh Venkataramanan if (err) 3565cdedef59SAnirudh Venkataramanan goto err_setup_tx; 3566cdedef59SAnirudh Venkataramanan 3567cdedef59SAnirudh Venkataramanan err = ice_vsi_setup_rx_rings(vsi); 3568cdedef59SAnirudh Venkataramanan if (err) 3569cdedef59SAnirudh Venkataramanan goto err_setup_rx; 3570cdedef59SAnirudh Venkataramanan 3571cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg(vsi); 3572cdedef59SAnirudh Venkataramanan if (err) 3573cdedef59SAnirudh Venkataramanan goto err_setup_rx; 3574cdedef59SAnirudh Venkataramanan 3575cdedef59SAnirudh Venkataramanan snprintf(int_name, sizeof(int_name) - 1, "%s-%s", 3576cdedef59SAnirudh Venkataramanan dev_driver_string(&pf->pdev->dev), vsi->netdev->name); 3577cdedef59SAnirudh Venkataramanan err = ice_vsi_req_irq(vsi, int_name); 3578cdedef59SAnirudh Venkataramanan if (err) 3579cdedef59SAnirudh Venkataramanan goto err_setup_rx; 3580cdedef59SAnirudh Venkataramanan 3581cdedef59SAnirudh Venkataramanan /* Notify the stack of the actual queue counts. */ 3582cdedef59SAnirudh Venkataramanan err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq); 3583cdedef59SAnirudh Venkataramanan if (err) 3584cdedef59SAnirudh Venkataramanan goto err_set_qs; 3585cdedef59SAnirudh Venkataramanan 3586cdedef59SAnirudh Venkataramanan err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq); 3587cdedef59SAnirudh Venkataramanan if (err) 3588cdedef59SAnirudh Venkataramanan goto err_set_qs; 3589cdedef59SAnirudh Venkataramanan 3590cdedef59SAnirudh Venkataramanan err = ice_up_complete(vsi); 3591cdedef59SAnirudh Venkataramanan if (err) 3592cdedef59SAnirudh Venkataramanan goto err_up_complete; 3593cdedef59SAnirudh Venkataramanan 3594cdedef59SAnirudh Venkataramanan return 0; 3595cdedef59SAnirudh Venkataramanan 3596cdedef59SAnirudh Venkataramanan err_up_complete: 3597cdedef59SAnirudh Venkataramanan ice_down(vsi); 3598cdedef59SAnirudh Venkataramanan err_set_qs: 3599cdedef59SAnirudh Venkataramanan ice_vsi_free_irq(vsi); 3600cdedef59SAnirudh Venkataramanan err_setup_rx: 3601cdedef59SAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 3602cdedef59SAnirudh Venkataramanan err_setup_tx: 3603cdedef59SAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 3604cdedef59SAnirudh Venkataramanan 3605cdedef59SAnirudh Venkataramanan return err; 3606cdedef59SAnirudh Venkataramanan } 3607cdedef59SAnirudh Venkataramanan 3608cdedef59SAnirudh Venkataramanan /** 36090f9d5027SAnirudh Venkataramanan * ice_vsi_release_all - Delete all VSIs 36100f9d5027SAnirudh Venkataramanan * @pf: PF from which all VSIs are being removed 36110f9d5027SAnirudh Venkataramanan */ 36120f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf) 36130f9d5027SAnirudh Venkataramanan { 36140f9d5027SAnirudh Venkataramanan int err, i; 36150f9d5027SAnirudh Venkataramanan 36160f9d5027SAnirudh Venkataramanan if (!pf->vsi) 36170f9d5027SAnirudh Venkataramanan return; 36180f9d5027SAnirudh Venkataramanan 361980ed404aSBrett Creeley ice_for_each_vsi(pf, i) { 36200f9d5027SAnirudh Venkataramanan if (!pf->vsi[i]) 36210f9d5027SAnirudh Venkataramanan continue; 36220f9d5027SAnirudh Venkataramanan 36230f9d5027SAnirudh Venkataramanan err = ice_vsi_release(pf->vsi[i]); 36240f9d5027SAnirudh Venkataramanan if (err) 36250f9d5027SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 36260f9d5027SAnirudh Venkataramanan "Failed to release pf->vsi[%d], err %d, vsi_num = %d\n", 36270f9d5027SAnirudh Venkataramanan i, err, pf->vsi[i]->vsi_num); 36280f9d5027SAnirudh Venkataramanan } 36290f9d5027SAnirudh Venkataramanan } 36300f9d5027SAnirudh Venkataramanan 36310f9d5027SAnirudh Venkataramanan /** 36320b28b702SAnirudh Venkataramanan * ice_ena_vsi - resume a VSI 36330b28b702SAnirudh Venkataramanan * @vsi: the VSI being resume 36347b9ffc76SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 36350b28b702SAnirudh Venkataramanan */ 36367b9ffc76SAnirudh Venkataramanan static int ice_ena_vsi(struct ice_vsi *vsi, bool locked) 36370b28b702SAnirudh Venkataramanan { 36380f9d5027SAnirudh Venkataramanan int err = 0; 36390b28b702SAnirudh Venkataramanan 36407b9ffc76SAnirudh Venkataramanan if (!test_bit(__ICE_NEEDS_RESTART, vsi->state)) 36417b9ffc76SAnirudh Venkataramanan return err; 36427b9ffc76SAnirudh Venkataramanan 36437b9ffc76SAnirudh Venkataramanan clear_bit(__ICE_NEEDS_RESTART, vsi->state); 36447b9ffc76SAnirudh Venkataramanan 36457b9ffc76SAnirudh Venkataramanan if (vsi->netdev && vsi->type == ICE_VSI_PF) { 36467b9ffc76SAnirudh Venkataramanan struct net_device *netd = vsi->netdev; 36477b9ffc76SAnirudh Venkataramanan 3648124cd547SDave Ertman if (netif_running(vsi->netdev)) { 36497b9ffc76SAnirudh Venkataramanan if (locked) { 36507b9ffc76SAnirudh Venkataramanan err = netd->netdev_ops->ndo_open(netd); 36517b9ffc76SAnirudh Venkataramanan } else { 36520f9d5027SAnirudh Venkataramanan rtnl_lock(); 36537b9ffc76SAnirudh Venkataramanan err = netd->netdev_ops->ndo_open(netd); 36540f9d5027SAnirudh Venkataramanan rtnl_unlock(); 36557b9ffc76SAnirudh Venkataramanan } 3656124cd547SDave Ertman } else { 3657124cd547SDave Ertman err = ice_vsi_open(vsi); 3658124cd547SDave Ertman } 36590f9d5027SAnirudh Venkataramanan } 36600f9d5027SAnirudh Venkataramanan 36610f9d5027SAnirudh Venkataramanan return err; 36620b28b702SAnirudh Venkataramanan } 36630b28b702SAnirudh Venkataramanan 36640b28b702SAnirudh Venkataramanan /** 36650b28b702SAnirudh Venkataramanan * ice_pf_ena_all_vsi - Resume all VSIs on a PF 36660b28b702SAnirudh Venkataramanan * @pf: the PF 36677b9ffc76SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 36680b28b702SAnirudh Venkataramanan */ 36697b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 36707b9ffc76SAnirudh Venkataramanan int ice_pf_ena_all_vsi(struct ice_pf *pf, bool locked) 36717b9ffc76SAnirudh Venkataramanan #else 36727b9ffc76SAnirudh Venkataramanan static int ice_pf_ena_all_vsi(struct ice_pf *pf, bool locked) 36737b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 36740b28b702SAnirudh Venkataramanan { 36750b28b702SAnirudh Venkataramanan int v; 36760b28b702SAnirudh Venkataramanan 36770b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) 36780b28b702SAnirudh Venkataramanan if (pf->vsi[v]) 36797b9ffc76SAnirudh Venkataramanan if (ice_ena_vsi(pf->vsi[v], locked)) 36800f9d5027SAnirudh Venkataramanan return -EIO; 36810f9d5027SAnirudh Venkataramanan 36820f9d5027SAnirudh Venkataramanan return 0; 36830f9d5027SAnirudh Venkataramanan } 36840f9d5027SAnirudh Venkataramanan 36850f9d5027SAnirudh Venkataramanan /** 36860f9d5027SAnirudh Venkataramanan * ice_vsi_rebuild_all - rebuild all VSIs in pf 36870f9d5027SAnirudh Venkataramanan * @pf: the PF 36880f9d5027SAnirudh Venkataramanan */ 36890f9d5027SAnirudh Venkataramanan static int ice_vsi_rebuild_all(struct ice_pf *pf) 36900f9d5027SAnirudh Venkataramanan { 36910f9d5027SAnirudh Venkataramanan int i; 36920f9d5027SAnirudh Venkataramanan 36930f9d5027SAnirudh Venkataramanan /* loop through pf->vsi array and reinit the VSI if found */ 369480ed404aSBrett Creeley ice_for_each_vsi(pf, i) { 36950f9d5027SAnirudh Venkataramanan int err; 36960f9d5027SAnirudh Venkataramanan 36970f9d5027SAnirudh Venkataramanan if (!pf->vsi[i]) 36980f9d5027SAnirudh Venkataramanan continue; 36990f9d5027SAnirudh Venkataramanan 37000f9d5027SAnirudh Venkataramanan err = ice_vsi_rebuild(pf->vsi[i]); 37010f9d5027SAnirudh Venkataramanan if (err) { 37020f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 37030f9d5027SAnirudh Venkataramanan "VSI at index %d rebuild failed\n", 37040f9d5027SAnirudh Venkataramanan pf->vsi[i]->idx); 37050f9d5027SAnirudh Venkataramanan return err; 37060f9d5027SAnirudh Venkataramanan } 37070f9d5027SAnirudh Venkataramanan 37080f9d5027SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 37090f9d5027SAnirudh Venkataramanan "VSI at index %d rebuilt. vsi_num = 0x%x\n", 37100f9d5027SAnirudh Venkataramanan pf->vsi[i]->idx, pf->vsi[i]->vsi_num); 37110f9d5027SAnirudh Venkataramanan } 37120f9d5027SAnirudh Venkataramanan 37130f9d5027SAnirudh Venkataramanan return 0; 37140b28b702SAnirudh Venkataramanan } 37150b28b702SAnirudh Venkataramanan 37160b28b702SAnirudh Venkataramanan /** 3717334cb062SAnirudh Venkataramanan * ice_vsi_replay_all - replay all VSIs configuration in the PF 3718334cb062SAnirudh Venkataramanan * @pf: the PF 3719334cb062SAnirudh Venkataramanan */ 3720334cb062SAnirudh Venkataramanan static int ice_vsi_replay_all(struct ice_pf *pf) 3721334cb062SAnirudh Venkataramanan { 3722334cb062SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3723334cb062SAnirudh Venkataramanan enum ice_status ret; 3724334cb062SAnirudh Venkataramanan int i; 3725334cb062SAnirudh Venkataramanan 3726334cb062SAnirudh Venkataramanan /* loop through pf->vsi array and replay the VSI if found */ 372780ed404aSBrett Creeley ice_for_each_vsi(pf, i) { 3728334cb062SAnirudh Venkataramanan if (!pf->vsi[i]) 3729334cb062SAnirudh Venkataramanan continue; 3730334cb062SAnirudh Venkataramanan 3731334cb062SAnirudh Venkataramanan ret = ice_replay_vsi(hw, pf->vsi[i]->idx); 3732334cb062SAnirudh Venkataramanan if (ret) { 3733334cb062SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3734334cb062SAnirudh Venkataramanan "VSI at index %d replay failed %d\n", 3735334cb062SAnirudh Venkataramanan pf->vsi[i]->idx, ret); 3736334cb062SAnirudh Venkataramanan return -EIO; 3737334cb062SAnirudh Venkataramanan } 3738334cb062SAnirudh Venkataramanan 3739334cb062SAnirudh Venkataramanan /* Re-map HW VSI number, using VSI handle that has been 3740334cb062SAnirudh Venkataramanan * previously validated in ice_replay_vsi() call above 3741334cb062SAnirudh Venkataramanan */ 3742334cb062SAnirudh Venkataramanan pf->vsi[i]->vsi_num = ice_get_hw_vsi_num(hw, pf->vsi[i]->idx); 3743334cb062SAnirudh Venkataramanan 3744334cb062SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 3745334cb062SAnirudh Venkataramanan "VSI at index %d filter replayed successfully - vsi_num %i\n", 3746334cb062SAnirudh Venkataramanan pf->vsi[i]->idx, pf->vsi[i]->vsi_num); 3747334cb062SAnirudh Venkataramanan } 3748334cb062SAnirudh Venkataramanan 3749334cb062SAnirudh Venkataramanan /* Clean up replay filter after successful re-configuration */ 3750334cb062SAnirudh Venkataramanan ice_replay_post(hw); 3751334cb062SAnirudh Venkataramanan return 0; 3752334cb062SAnirudh Venkataramanan } 3753334cb062SAnirudh Venkataramanan 3754334cb062SAnirudh Venkataramanan /** 37550b28b702SAnirudh Venkataramanan * ice_rebuild - rebuild after reset 37560b28b702SAnirudh Venkataramanan * @pf: pf to rebuild 37570b28b702SAnirudh Venkataramanan */ 37580b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf) 37590b28b702SAnirudh Venkataramanan { 37600b28b702SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 37610b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 37620b28b702SAnirudh Venkataramanan enum ice_status ret; 3763ce317dd9SAnirudh Venkataramanan int err, i; 37640b28b702SAnirudh Venkataramanan 37650b28b702SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state)) 37660b28b702SAnirudh Venkataramanan goto clear_recovery; 37670b28b702SAnirudh Venkataramanan 37680b28b702SAnirudh Venkataramanan dev_dbg(dev, "rebuilding pf\n"); 37690b28b702SAnirudh Venkataramanan 37700b28b702SAnirudh Venkataramanan ret = ice_init_all_ctrlq(hw); 37710b28b702SAnirudh Venkataramanan if (ret) { 37720b28b702SAnirudh Venkataramanan dev_err(dev, "control queues init failed %d\n", ret); 37730f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 37740b28b702SAnirudh Venkataramanan } 37750b28b702SAnirudh Venkataramanan 37760b28b702SAnirudh Venkataramanan ret = ice_clear_pf_cfg(hw); 37770b28b702SAnirudh Venkataramanan if (ret) { 37780b28b702SAnirudh Venkataramanan dev_err(dev, "clear PF configuration failed %d\n", ret); 37790f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 37800b28b702SAnirudh Venkataramanan } 37810b28b702SAnirudh Venkataramanan 37820b28b702SAnirudh Venkataramanan ice_clear_pxe_mode(hw); 37830b28b702SAnirudh Venkataramanan 37840b28b702SAnirudh Venkataramanan ret = ice_get_caps(hw); 37850b28b702SAnirudh Venkataramanan if (ret) { 37860b28b702SAnirudh Venkataramanan dev_err(dev, "ice_get_caps failed %d\n", ret); 37870f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 37880b28b702SAnirudh Venkataramanan } 37890b28b702SAnirudh Venkataramanan 37900f9d5027SAnirudh Venkataramanan err = ice_sched_init_port(hw->port_info); 37910f9d5027SAnirudh Venkataramanan if (err) 37920f9d5027SAnirudh Venkataramanan goto err_sched_init_port; 37930f9d5027SAnirudh Venkataramanan 3794eb0208ecSPreethi Banala /* reset search_hint of irq_trackers to 0 since interrupts are 3795eb0208ecSPreethi Banala * reclaimed and could be allocated from beginning during VSI rebuild 3796eb0208ecSPreethi Banala */ 3797eb0208ecSPreethi Banala pf->sw_irq_tracker->search_hint = 0; 3798eb0208ecSPreethi Banala pf->hw_irq_tracker->search_hint = 0; 3799eb0208ecSPreethi Banala 38000f9d5027SAnirudh Venkataramanan err = ice_vsi_rebuild_all(pf); 38010b28b702SAnirudh Venkataramanan if (err) { 38020f9d5027SAnirudh Venkataramanan dev_err(dev, "ice_vsi_rebuild_all failed\n"); 38030f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 38040f9d5027SAnirudh Venkataramanan } 38050f9d5027SAnirudh Venkataramanan 38065755143dSDave Ertman err = ice_update_link_info(hw->port_info); 38075755143dSDave Ertman if (err) 38085755143dSDave Ertman dev_err(&pf->pdev->dev, "Get link status error %d\n", err); 38095755143dSDave Ertman 3810334cb062SAnirudh Venkataramanan /* Replay all VSIs Configuration, including filters after reset */ 3811334cb062SAnirudh Venkataramanan if (ice_vsi_replay_all(pf)) { 38120f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3813334cb062SAnirudh Venkataramanan "error replaying VSI configurations with switch filter rules\n"); 38140f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 38150b28b702SAnirudh Venkataramanan } 38160b28b702SAnirudh Venkataramanan 38170b28b702SAnirudh Venkataramanan /* start misc vector */ 38180b28b702SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 38190b28b702SAnirudh Venkataramanan err = ice_req_irq_msix_misc(pf); 38200b28b702SAnirudh Venkataramanan if (err) { 38210b28b702SAnirudh Venkataramanan dev_err(dev, "misc vector setup failed: %d\n", err); 38220f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 38230b28b702SAnirudh Venkataramanan } 38240b28b702SAnirudh Venkataramanan } 38250b28b702SAnirudh Venkataramanan 38260b28b702SAnirudh Venkataramanan /* restart the VSIs that were rebuilt and running before the reset */ 38277b9ffc76SAnirudh Venkataramanan err = ice_pf_ena_all_vsi(pf, false); 38280f9d5027SAnirudh Venkataramanan if (err) { 38290f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "error enabling VSIs\n"); 38300f9d5027SAnirudh Venkataramanan /* no need to disable VSIs in tear down path in ice_rebuild() 38310f9d5027SAnirudh Venkataramanan * since its already taken care in ice_vsi_open() 38320f9d5027SAnirudh Venkataramanan */ 38330f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 38340f9d5027SAnirudh Venkataramanan } 38350b28b702SAnirudh Venkataramanan 383680ed404aSBrett Creeley ice_for_each_vsi(pf, i) { 3837ce317dd9SAnirudh Venkataramanan bool link_up; 3838ce317dd9SAnirudh Venkataramanan 3839ce317dd9SAnirudh Venkataramanan if (!pf->vsi[i] || pf->vsi[i]->type != ICE_VSI_PF) 3840ce317dd9SAnirudh Venkataramanan continue; 3841ce317dd9SAnirudh Venkataramanan ice_get_link_status(pf->vsi[i]->port_info, &link_up); 3842ce317dd9SAnirudh Venkataramanan if (link_up) { 3843ce317dd9SAnirudh Venkataramanan netif_carrier_on(pf->vsi[i]->netdev); 3844ce317dd9SAnirudh Venkataramanan netif_tx_wake_all_queues(pf->vsi[i]->netdev); 3845ce317dd9SAnirudh Venkataramanan } else { 3846ce317dd9SAnirudh Venkataramanan netif_carrier_off(pf->vsi[i]->netdev); 3847ce317dd9SAnirudh Venkataramanan netif_tx_stop_all_queues(pf->vsi[i]->netdev); 3848ce317dd9SAnirudh Venkataramanan } 3849ce317dd9SAnirudh Venkataramanan } 3850ce317dd9SAnirudh Venkataramanan 38510f9d5027SAnirudh Venkataramanan /* if we get here, reset flow is successful */ 38520f9d5027SAnirudh Venkataramanan clear_bit(__ICE_RESET_FAILED, pf->state); 38530b28b702SAnirudh Venkataramanan return; 38540b28b702SAnirudh Venkataramanan 38550f9d5027SAnirudh Venkataramanan err_vsi_rebuild: 38560f9d5027SAnirudh Venkataramanan ice_vsi_release_all(pf); 38570f9d5027SAnirudh Venkataramanan err_sched_init_port: 38580f9d5027SAnirudh Venkataramanan ice_sched_cleanup_all(hw); 38590f9d5027SAnirudh Venkataramanan err_init_ctrlq: 38600b28b702SAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 38610b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 38620b28b702SAnirudh Venkataramanan clear_recovery: 38630f9d5027SAnirudh Venkataramanan /* set this bit in PF state to control service task scheduling */ 38640f9d5027SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, pf->state); 38650f9d5027SAnirudh Venkataramanan dev_err(dev, "Rebuild failed, unload and reload driver\n"); 38660b28b702SAnirudh Venkataramanan } 38670b28b702SAnirudh Venkataramanan 38680b28b702SAnirudh Venkataramanan /** 3869e94d4478SAnirudh Venkataramanan * ice_change_mtu - NDO callback to change the MTU 3870e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 3871e94d4478SAnirudh Venkataramanan * @new_mtu: new value for maximum frame size 3872e94d4478SAnirudh Venkataramanan * 3873e94d4478SAnirudh Venkataramanan * Returns 0 on success, negative on failure 3874e94d4478SAnirudh Venkataramanan */ 3875e94d4478SAnirudh Venkataramanan static int ice_change_mtu(struct net_device *netdev, int new_mtu) 3876e94d4478SAnirudh Venkataramanan { 3877e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3878e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3879e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3880e94d4478SAnirudh Venkataramanan u8 count = 0; 3881e94d4478SAnirudh Venkataramanan 3882e94d4478SAnirudh Venkataramanan if (new_mtu == netdev->mtu) { 38833968540bSAnirudh Venkataramanan netdev_warn(netdev, "mtu is already %u\n", netdev->mtu); 3884e94d4478SAnirudh Venkataramanan return 0; 3885e94d4478SAnirudh Venkataramanan } 3886e94d4478SAnirudh Venkataramanan 3887e94d4478SAnirudh Venkataramanan if (new_mtu < netdev->min_mtu) { 3888e94d4478SAnirudh Venkataramanan netdev_err(netdev, "new mtu invalid. min_mtu is %d\n", 3889e94d4478SAnirudh Venkataramanan netdev->min_mtu); 3890e94d4478SAnirudh Venkataramanan return -EINVAL; 3891e94d4478SAnirudh Venkataramanan } else if (new_mtu > netdev->max_mtu) { 3892e94d4478SAnirudh Venkataramanan netdev_err(netdev, "new mtu invalid. max_mtu is %d\n", 3893e94d4478SAnirudh Venkataramanan netdev->min_mtu); 3894e94d4478SAnirudh Venkataramanan return -EINVAL; 3895e94d4478SAnirudh Venkataramanan } 3896e94d4478SAnirudh Venkataramanan /* if a reset is in progress, wait for some time for it to complete */ 3897e94d4478SAnirudh Venkataramanan do { 38985df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) { 3899e94d4478SAnirudh Venkataramanan count++; 3900e94d4478SAnirudh Venkataramanan usleep_range(1000, 2000); 3901e94d4478SAnirudh Venkataramanan } else { 3902e94d4478SAnirudh Venkataramanan break; 3903e94d4478SAnirudh Venkataramanan } 3904e94d4478SAnirudh Venkataramanan 3905e94d4478SAnirudh Venkataramanan } while (count < 100); 3906e94d4478SAnirudh Venkataramanan 3907e94d4478SAnirudh Venkataramanan if (count == 100) { 3908e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't change mtu. Device is busy\n"); 3909e94d4478SAnirudh Venkataramanan return -EBUSY; 3910e94d4478SAnirudh Venkataramanan } 3911e94d4478SAnirudh Venkataramanan 3912e94d4478SAnirudh Venkataramanan netdev->mtu = new_mtu; 3913e94d4478SAnirudh Venkataramanan 3914e94d4478SAnirudh Venkataramanan /* if VSI is up, bring it down and then back up */ 3915e94d4478SAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 3916e94d4478SAnirudh Venkataramanan int err; 3917e94d4478SAnirudh Venkataramanan 3918e94d4478SAnirudh Venkataramanan err = ice_down(vsi); 3919e94d4478SAnirudh Venkataramanan if (err) { 3920e94d4478SAnirudh Venkataramanan netdev_err(netdev, "change mtu if_up err %d\n", err); 3921e94d4478SAnirudh Venkataramanan return err; 3922e94d4478SAnirudh Venkataramanan } 3923e94d4478SAnirudh Venkataramanan 3924e94d4478SAnirudh Venkataramanan err = ice_up(vsi); 3925e94d4478SAnirudh Venkataramanan if (err) { 3926e94d4478SAnirudh Venkataramanan netdev_err(netdev, "change mtu if_up err %d\n", err); 3927e94d4478SAnirudh Venkataramanan return err; 3928e94d4478SAnirudh Venkataramanan } 3929e94d4478SAnirudh Venkataramanan } 3930e94d4478SAnirudh Venkataramanan 3931e94d4478SAnirudh Venkataramanan netdev_dbg(netdev, "changed mtu to %d\n", new_mtu); 3932e94d4478SAnirudh Venkataramanan return 0; 3933e94d4478SAnirudh Venkataramanan } 3934e94d4478SAnirudh Venkataramanan 3935e94d4478SAnirudh Venkataramanan /** 3936d76a60baSAnirudh Venkataramanan * ice_set_rss - Set RSS keys and lut 3937d76a60baSAnirudh Venkataramanan * @vsi: Pointer to VSI structure 3938d76a60baSAnirudh Venkataramanan * @seed: RSS hash seed 3939d76a60baSAnirudh Venkataramanan * @lut: Lookup table 3940d76a60baSAnirudh Venkataramanan * @lut_size: Lookup table size 3941d76a60baSAnirudh Venkataramanan * 3942d76a60baSAnirudh Venkataramanan * Returns 0 on success, negative on failure 3943d76a60baSAnirudh Venkataramanan */ 3944d76a60baSAnirudh Venkataramanan int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) 3945d76a60baSAnirudh Venkataramanan { 3946d76a60baSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3947d76a60baSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3948d76a60baSAnirudh Venkataramanan enum ice_status status; 3949d76a60baSAnirudh Venkataramanan 3950d76a60baSAnirudh Venkataramanan if (seed) { 3951d76a60baSAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *buf = 3952d76a60baSAnirudh Venkataramanan (struct ice_aqc_get_set_rss_keys *)seed; 3953d76a60baSAnirudh Venkataramanan 39544fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(hw, vsi->idx, buf); 3955d76a60baSAnirudh Venkataramanan 3956d76a60baSAnirudh Venkataramanan if (status) { 3957d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3958d76a60baSAnirudh Venkataramanan "Cannot set RSS key, err %d aq_err %d\n", 3959d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3960d76a60baSAnirudh Venkataramanan return -EIO; 3961d76a60baSAnirudh Venkataramanan } 3962d76a60baSAnirudh Venkataramanan } 3963d76a60baSAnirudh Venkataramanan 3964d76a60baSAnirudh Venkataramanan if (lut) { 39654fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type, 39664fb33f31SAnirudh Venkataramanan lut, lut_size); 3967d76a60baSAnirudh Venkataramanan if (status) { 3968d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3969d76a60baSAnirudh Venkataramanan "Cannot set RSS lut, err %d aq_err %d\n", 3970d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3971d76a60baSAnirudh Venkataramanan return -EIO; 3972d76a60baSAnirudh Venkataramanan } 3973d76a60baSAnirudh Venkataramanan } 3974d76a60baSAnirudh Venkataramanan 3975d76a60baSAnirudh Venkataramanan return 0; 3976d76a60baSAnirudh Venkataramanan } 3977d76a60baSAnirudh Venkataramanan 3978d76a60baSAnirudh Venkataramanan /** 3979d76a60baSAnirudh Venkataramanan * ice_get_rss - Get RSS keys and lut 3980d76a60baSAnirudh Venkataramanan * @vsi: Pointer to VSI structure 3981d76a60baSAnirudh Venkataramanan * @seed: Buffer to store the keys 3982d76a60baSAnirudh Venkataramanan * @lut: Buffer to store the lookup table entries 3983d76a60baSAnirudh Venkataramanan * @lut_size: Size of buffer to store the lookup table entries 3984d76a60baSAnirudh Venkataramanan * 3985d76a60baSAnirudh Venkataramanan * Returns 0 on success, negative on failure 3986d76a60baSAnirudh Venkataramanan */ 3987d76a60baSAnirudh Venkataramanan int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) 3988d76a60baSAnirudh Venkataramanan { 3989d76a60baSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3990d76a60baSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3991d76a60baSAnirudh Venkataramanan enum ice_status status; 3992d76a60baSAnirudh Venkataramanan 3993d76a60baSAnirudh Venkataramanan if (seed) { 3994d76a60baSAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *buf = 3995d76a60baSAnirudh Venkataramanan (struct ice_aqc_get_set_rss_keys *)seed; 3996d76a60baSAnirudh Venkataramanan 39974fb33f31SAnirudh Venkataramanan status = ice_aq_get_rss_key(hw, vsi->idx, buf); 3998d76a60baSAnirudh Venkataramanan if (status) { 3999d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 4000d76a60baSAnirudh Venkataramanan "Cannot get RSS key, err %d aq_err %d\n", 4001d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 4002d76a60baSAnirudh Venkataramanan return -EIO; 4003d76a60baSAnirudh Venkataramanan } 4004d76a60baSAnirudh Venkataramanan } 4005d76a60baSAnirudh Venkataramanan 4006d76a60baSAnirudh Venkataramanan if (lut) { 40074fb33f31SAnirudh Venkataramanan status = ice_aq_get_rss_lut(hw, vsi->idx, vsi->rss_lut_type, 40084fb33f31SAnirudh Venkataramanan lut, lut_size); 4009d76a60baSAnirudh Venkataramanan if (status) { 4010d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 4011d76a60baSAnirudh Venkataramanan "Cannot get RSS lut, err %d aq_err %d\n", 4012d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 4013d76a60baSAnirudh Venkataramanan return -EIO; 4014d76a60baSAnirudh Venkataramanan } 4015d76a60baSAnirudh Venkataramanan } 4016d76a60baSAnirudh Venkataramanan 4017d76a60baSAnirudh Venkataramanan return 0; 4018d76a60baSAnirudh Venkataramanan } 4019d76a60baSAnirudh Venkataramanan 4020d76a60baSAnirudh Venkataramanan /** 4021b1edc14aSMd Fahad Iqbal Polash * ice_bridge_getlink - Get the hardware bridge mode 4022b1edc14aSMd Fahad Iqbal Polash * @skb: skb buff 4023f9867df6SAnirudh Venkataramanan * @pid: process ID 4024b1edc14aSMd Fahad Iqbal Polash * @seq: RTNL message seq 4025b1edc14aSMd Fahad Iqbal Polash * @dev: the netdev being configured 4026b1edc14aSMd Fahad Iqbal Polash * @filter_mask: filter mask passed in 4027b1edc14aSMd Fahad Iqbal Polash * @nlflags: netlink flags passed in 4028b1edc14aSMd Fahad Iqbal Polash * 4029b1edc14aSMd Fahad Iqbal Polash * Return the bridge mode (VEB/VEPA) 4030b1edc14aSMd Fahad Iqbal Polash */ 4031b1edc14aSMd Fahad Iqbal Polash static int 4032b1edc14aSMd Fahad Iqbal Polash ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 4033b1edc14aSMd Fahad Iqbal Polash struct net_device *dev, u32 filter_mask, int nlflags) 4034b1edc14aSMd Fahad Iqbal Polash { 4035b1edc14aSMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(dev); 4036b1edc14aSMd Fahad Iqbal Polash struct ice_vsi *vsi = np->vsi; 4037b1edc14aSMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 4038b1edc14aSMd Fahad Iqbal Polash u16 bmode; 4039b1edc14aSMd Fahad Iqbal Polash 4040b1edc14aSMd Fahad Iqbal Polash bmode = pf->first_sw->bridge_mode; 4041b1edc14aSMd Fahad Iqbal Polash 4042b1edc14aSMd Fahad Iqbal Polash return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags, 4043b1edc14aSMd Fahad Iqbal Polash filter_mask, NULL); 4044b1edc14aSMd Fahad Iqbal Polash } 4045b1edc14aSMd Fahad Iqbal Polash 4046b1edc14aSMd Fahad Iqbal Polash /** 4047b1edc14aSMd Fahad Iqbal Polash * ice_vsi_update_bridge_mode - Update VSI for switching bridge mode (VEB/VEPA) 4048b1edc14aSMd Fahad Iqbal Polash * @vsi: Pointer to VSI structure 4049b1edc14aSMd Fahad Iqbal Polash * @bmode: Hardware bridge mode (VEB/VEPA) 4050b1edc14aSMd Fahad Iqbal Polash * 4051b1edc14aSMd Fahad Iqbal Polash * Returns 0 on success, negative on failure 4052b1edc14aSMd Fahad Iqbal Polash */ 4053b1edc14aSMd Fahad Iqbal Polash static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode) 4054b1edc14aSMd Fahad Iqbal Polash { 4055b1edc14aSMd Fahad Iqbal Polash struct device *dev = &vsi->back->pdev->dev; 4056b1edc14aSMd Fahad Iqbal Polash struct ice_aqc_vsi_props *vsi_props; 4057b1edc14aSMd Fahad Iqbal Polash struct ice_hw *hw = &vsi->back->hw; 4058198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 4059b1edc14aSMd Fahad Iqbal Polash enum ice_status status; 4060198a666aSBruce Allan int ret = 0; 4061b1edc14aSMd Fahad Iqbal Polash 4062b1edc14aSMd Fahad Iqbal Polash vsi_props = &vsi->info; 4063198a666aSBruce Allan 4064198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 4065198a666aSBruce Allan if (!ctxt) 4066198a666aSBruce Allan return -ENOMEM; 4067198a666aSBruce Allan 4068198a666aSBruce Allan ctxt->info = vsi->info; 4069b1edc14aSMd Fahad Iqbal Polash 4070b1edc14aSMd Fahad Iqbal Polash if (bmode == BRIDGE_MODE_VEB) 4071b1edc14aSMd Fahad Iqbal Polash /* change from VEPA to VEB mode */ 4072198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 4073b1edc14aSMd Fahad Iqbal Polash else 4074b1edc14aSMd Fahad Iqbal Polash /* change from VEB to VEPA mode */ 4075198a666aSBruce Allan ctxt->info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 4076198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); 40775726ca0eSAnirudh Venkataramanan 4078198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 4079b1edc14aSMd Fahad Iqbal Polash if (status) { 4080b1edc14aSMd Fahad Iqbal Polash dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n", 4081b1edc14aSMd Fahad Iqbal Polash bmode, status, hw->adminq.sq_last_status); 4082198a666aSBruce Allan ret = -EIO; 4083198a666aSBruce Allan goto out; 4084b1edc14aSMd Fahad Iqbal Polash } 4085b1edc14aSMd Fahad Iqbal Polash /* Update sw flags for book keeping */ 4086198a666aSBruce Allan vsi_props->sw_flags = ctxt->info.sw_flags; 4087b1edc14aSMd Fahad Iqbal Polash 4088198a666aSBruce Allan out: 4089198a666aSBruce Allan devm_kfree(dev, ctxt); 4090198a666aSBruce Allan return ret; 4091b1edc14aSMd Fahad Iqbal Polash } 4092b1edc14aSMd Fahad Iqbal Polash 4093b1edc14aSMd Fahad Iqbal Polash /** 4094b1edc14aSMd Fahad Iqbal Polash * ice_bridge_setlink - Set the hardware bridge mode 4095b1edc14aSMd Fahad Iqbal Polash * @dev: the netdev being configured 4096b1edc14aSMd Fahad Iqbal Polash * @nlh: RTNL message 4097b1edc14aSMd Fahad Iqbal Polash * @flags: bridge setlink flags 40982fd527b7SPetr Machata * @extack: netlink extended ack 4099b1edc14aSMd Fahad Iqbal Polash * 4100b1edc14aSMd Fahad Iqbal Polash * Sets the bridge mode (VEB/VEPA) of the switch to which the netdev (VSI) is 4101b1edc14aSMd Fahad Iqbal Polash * hooked up to. Iterates through the PF VSI list and sets the loopback mode (if 4102b1edc14aSMd Fahad Iqbal Polash * not already set for all VSIs connected to this switch. And also update the 4103b1edc14aSMd Fahad Iqbal Polash * unicast switch filter rules for the corresponding switch of the netdev. 4104b1edc14aSMd Fahad Iqbal Polash */ 4105b1edc14aSMd Fahad Iqbal Polash static int 4106b1edc14aSMd Fahad Iqbal Polash ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, 41073d505147SBruce Allan u16 __always_unused flags, 41083d505147SBruce Allan struct netlink_ext_ack __always_unused *extack) 4109b1edc14aSMd Fahad Iqbal Polash { 4110b1edc14aSMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(dev); 4111b1edc14aSMd Fahad Iqbal Polash struct ice_pf *pf = np->vsi->back; 4112b1edc14aSMd Fahad Iqbal Polash struct nlattr *attr, *br_spec; 4113b1edc14aSMd Fahad Iqbal Polash struct ice_hw *hw = &pf->hw; 4114b1edc14aSMd Fahad Iqbal Polash enum ice_status status; 4115b1edc14aSMd Fahad Iqbal Polash struct ice_sw *pf_sw; 4116b1edc14aSMd Fahad Iqbal Polash int rem, v, err = 0; 4117b1edc14aSMd Fahad Iqbal Polash 4118b1edc14aSMd Fahad Iqbal Polash pf_sw = pf->first_sw; 4119b1edc14aSMd Fahad Iqbal Polash /* find the attribute in the netlink message */ 4120b1edc14aSMd Fahad Iqbal Polash br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); 4121b1edc14aSMd Fahad Iqbal Polash 4122b1edc14aSMd Fahad Iqbal Polash nla_for_each_nested(attr, br_spec, rem) { 4123b1edc14aSMd Fahad Iqbal Polash __u16 mode; 4124b1edc14aSMd Fahad Iqbal Polash 4125b1edc14aSMd Fahad Iqbal Polash if (nla_type(attr) != IFLA_BRIDGE_MODE) 4126b1edc14aSMd Fahad Iqbal Polash continue; 4127b1edc14aSMd Fahad Iqbal Polash mode = nla_get_u16(attr); 4128b1edc14aSMd Fahad Iqbal Polash if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) 4129b1edc14aSMd Fahad Iqbal Polash return -EINVAL; 4130b1edc14aSMd Fahad Iqbal Polash /* Continue if bridge mode is not being flipped */ 4131b1edc14aSMd Fahad Iqbal Polash if (mode == pf_sw->bridge_mode) 4132b1edc14aSMd Fahad Iqbal Polash continue; 4133b1edc14aSMd Fahad Iqbal Polash /* Iterates through the PF VSI list and update the loopback 4134b1edc14aSMd Fahad Iqbal Polash * mode of the VSI 4135b1edc14aSMd Fahad Iqbal Polash */ 4136b1edc14aSMd Fahad Iqbal Polash ice_for_each_vsi(pf, v) { 4137b1edc14aSMd Fahad Iqbal Polash if (!pf->vsi[v]) 4138b1edc14aSMd Fahad Iqbal Polash continue; 4139b1edc14aSMd Fahad Iqbal Polash err = ice_vsi_update_bridge_mode(pf->vsi[v], mode); 4140b1edc14aSMd Fahad Iqbal Polash if (err) 4141b1edc14aSMd Fahad Iqbal Polash return err; 4142b1edc14aSMd Fahad Iqbal Polash } 4143b1edc14aSMd Fahad Iqbal Polash 4144b1edc14aSMd Fahad Iqbal Polash hw->evb_veb = (mode == BRIDGE_MODE_VEB); 4145b1edc14aSMd Fahad Iqbal Polash /* Update the unicast switch filter rules for the corresponding 4146b1edc14aSMd Fahad Iqbal Polash * switch of the netdev 4147b1edc14aSMd Fahad Iqbal Polash */ 4148b1edc14aSMd Fahad Iqbal Polash status = ice_update_sw_rule_bridge_mode(hw); 4149b1edc14aSMd Fahad Iqbal Polash if (status) { 4150df17b7e0SAnirudh Venkataramanan netdev_err(dev, "switch rule update failed, mode = %d err %d aq_err %d\n", 4151b1edc14aSMd Fahad Iqbal Polash mode, status, hw->adminq.sq_last_status); 4152b1edc14aSMd Fahad Iqbal Polash /* revert hw->evb_veb */ 4153b1edc14aSMd Fahad Iqbal Polash hw->evb_veb = (pf_sw->bridge_mode == BRIDGE_MODE_VEB); 4154b1edc14aSMd Fahad Iqbal Polash return -EIO; 4155b1edc14aSMd Fahad Iqbal Polash } 4156b1edc14aSMd Fahad Iqbal Polash 4157b1edc14aSMd Fahad Iqbal Polash pf_sw->bridge_mode = mode; 4158b1edc14aSMd Fahad Iqbal Polash } 4159b1edc14aSMd Fahad Iqbal Polash 4160b1edc14aSMd Fahad Iqbal Polash return 0; 4161b1edc14aSMd Fahad Iqbal Polash } 4162b1edc14aSMd Fahad Iqbal Polash 4163b1edc14aSMd Fahad Iqbal Polash /** 4164b3969fd7SSudheer Mogilappagari * ice_tx_timeout - Respond to a Tx Hang 4165b3969fd7SSudheer Mogilappagari * @netdev: network interface device structure 4166b3969fd7SSudheer Mogilappagari */ 4167b3969fd7SSudheer Mogilappagari static void ice_tx_timeout(struct net_device *netdev) 4168b3969fd7SSudheer Mogilappagari { 4169b3969fd7SSudheer Mogilappagari struct ice_netdev_priv *np = netdev_priv(netdev); 4170b3969fd7SSudheer Mogilappagari struct ice_ring *tx_ring = NULL; 4171b3969fd7SSudheer Mogilappagari struct ice_vsi *vsi = np->vsi; 4172b3969fd7SSudheer Mogilappagari struct ice_pf *pf = vsi->back; 4173b3969fd7SSudheer Mogilappagari int hung_queue = -1; 4174807bc98dSBrett Creeley u32 i; 4175b3969fd7SSudheer Mogilappagari 4176b3969fd7SSudheer Mogilappagari pf->tx_timeout_count++; 4177b3969fd7SSudheer Mogilappagari 4178bc0c6fabSBruce Allan /* find the stopped queue the same way dev_watchdog() does */ 4179b3969fd7SSudheer Mogilappagari for (i = 0; i < netdev->num_tx_queues; i++) { 4180b3969fd7SSudheer Mogilappagari unsigned long trans_start; 4181bc0c6fabSBruce Allan struct netdev_queue *q; 4182b3969fd7SSudheer Mogilappagari 4183b3969fd7SSudheer Mogilappagari q = netdev_get_tx_queue(netdev, i); 4184b3969fd7SSudheer Mogilappagari trans_start = q->trans_start; 4185b3969fd7SSudheer Mogilappagari if (netif_xmit_stopped(q) && 4186b3969fd7SSudheer Mogilappagari time_after(jiffies, 4187bc0c6fabSBruce Allan trans_start + netdev->watchdog_timeo)) { 4188b3969fd7SSudheer Mogilappagari hung_queue = i; 4189b3969fd7SSudheer Mogilappagari break; 4190b3969fd7SSudheer Mogilappagari } 4191b3969fd7SSudheer Mogilappagari } 4192b3969fd7SSudheer Mogilappagari 4193bc0c6fabSBruce Allan if (i == netdev->num_tx_queues) 4194b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout: no netdev hung queue found\n"); 4195bc0c6fabSBruce Allan else 4196b3969fd7SSudheer Mogilappagari /* now that we have an index, find the tx_ring struct */ 4197bc0c6fabSBruce Allan for (i = 0; i < vsi->num_txq; i++) 4198bc0c6fabSBruce Allan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 4199bc0c6fabSBruce Allan if (hung_queue == vsi->tx_rings[i]->q_index) { 4200b3969fd7SSudheer Mogilappagari tx_ring = vsi->tx_rings[i]; 4201b3969fd7SSudheer Mogilappagari break; 4202b3969fd7SSudheer Mogilappagari } 4203b3969fd7SSudheer Mogilappagari 4204b3969fd7SSudheer Mogilappagari /* Reset recovery level if enough time has elapsed after last timeout. 4205b3969fd7SSudheer Mogilappagari * Also ensure no new reset action happens before next timeout period. 4206b3969fd7SSudheer Mogilappagari */ 4207b3969fd7SSudheer Mogilappagari if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ * 20))) 4208b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level = 1; 4209b3969fd7SSudheer Mogilappagari else if (time_before(jiffies, (pf->tx_timeout_last_recovery + 4210b3969fd7SSudheer Mogilappagari netdev->watchdog_timeo))) 4211b3969fd7SSudheer Mogilappagari return; 4212b3969fd7SSudheer Mogilappagari 4213b3969fd7SSudheer Mogilappagari if (tx_ring) { 4214807bc98dSBrett Creeley struct ice_hw *hw = &pf->hw; 4215807bc98dSBrett Creeley u32 head, val = 0; 4216807bc98dSBrett Creeley 4217807bc98dSBrett Creeley head = (rd32(hw, QTX_COMM_HEAD(vsi->txq_map[hung_queue])) & 4218807bc98dSBrett Creeley QTX_COMM_HEAD_HEAD_M) >> QTX_COMM_HEAD_HEAD_S; 4219b3969fd7SSudheer Mogilappagari /* Read interrupt register */ 4220b3969fd7SSudheer Mogilappagari if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 4221807bc98dSBrett Creeley val = rd32(hw, 4222b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL(tx_ring->q_vector->v_idx + 4223eb0208ecSPreethi Banala tx_ring->vsi->hw_base_vector)); 4224b3969fd7SSudheer Mogilappagari 4225807bc98dSBrett Creeley netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HW_HEAD: 0x%x, NTU: 0x%x, INT: 0x%x\n", 4226b3969fd7SSudheer Mogilappagari vsi->vsi_num, hung_queue, tx_ring->next_to_clean, 4227807bc98dSBrett Creeley head, tx_ring->next_to_use, val); 4228b3969fd7SSudheer Mogilappagari } 4229b3969fd7SSudheer Mogilappagari 4230b3969fd7SSudheer Mogilappagari pf->tx_timeout_last_recovery = jiffies; 4231b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n", 4232b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level, hung_queue); 4233b3969fd7SSudheer Mogilappagari 4234b3969fd7SSudheer Mogilappagari switch (pf->tx_timeout_recovery_level) { 4235b3969fd7SSudheer Mogilappagari case 1: 4236b3969fd7SSudheer Mogilappagari set_bit(__ICE_PFR_REQ, pf->state); 4237b3969fd7SSudheer Mogilappagari break; 4238b3969fd7SSudheer Mogilappagari case 2: 4239b3969fd7SSudheer Mogilappagari set_bit(__ICE_CORER_REQ, pf->state); 4240b3969fd7SSudheer Mogilappagari break; 4241b3969fd7SSudheer Mogilappagari case 3: 4242b3969fd7SSudheer Mogilappagari set_bit(__ICE_GLOBR_REQ, pf->state); 4243b3969fd7SSudheer Mogilappagari break; 4244b3969fd7SSudheer Mogilappagari default: 4245b3969fd7SSudheer Mogilappagari netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in unrecoverable state.\n"); 4246b3969fd7SSudheer Mogilappagari set_bit(__ICE_DOWN, pf->state); 4247b3969fd7SSudheer Mogilappagari set_bit(__ICE_NEEDS_RESTART, vsi->state); 42488d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 4249b3969fd7SSudheer Mogilappagari break; 4250b3969fd7SSudheer Mogilappagari } 4251b3969fd7SSudheer Mogilappagari 4252b3969fd7SSudheer Mogilappagari ice_service_task_schedule(pf); 4253b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level++; 4254b3969fd7SSudheer Mogilappagari } 4255b3969fd7SSudheer Mogilappagari 4256b3969fd7SSudheer Mogilappagari /** 4257cdedef59SAnirudh Venkataramanan * ice_open - Called when a network interface becomes active 4258cdedef59SAnirudh Venkataramanan * @netdev: network interface device structure 4259cdedef59SAnirudh Venkataramanan * 4260cdedef59SAnirudh Venkataramanan * The open entry point is called when a network interface is made 4261cdedef59SAnirudh Venkataramanan * active by the system (IFF_UP). At this point all resources needed 4262cdedef59SAnirudh Venkataramanan * for transmit and receive operations are allocated, the interrupt 4263cdedef59SAnirudh Venkataramanan * handler is registered with the OS, the netdev watchdog is enabled, 4264cdedef59SAnirudh Venkataramanan * and the stack is notified that the interface is ready. 4265cdedef59SAnirudh Venkataramanan * 4266cdedef59SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 4267cdedef59SAnirudh Venkataramanan */ 4268cdedef59SAnirudh Venkataramanan static int ice_open(struct net_device *netdev) 4269cdedef59SAnirudh Venkataramanan { 4270cdedef59SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 4271cdedef59SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 4272cdedef59SAnirudh Venkataramanan int err; 4273cdedef59SAnirudh Venkataramanan 42740f9d5027SAnirudh Venkataramanan if (test_bit(__ICE_NEEDS_RESTART, vsi->back->state)) { 42750f9d5027SAnirudh Venkataramanan netdev_err(netdev, "driver needs to be unloaded and reloaded\n"); 42760f9d5027SAnirudh Venkataramanan return -EIO; 42770f9d5027SAnirudh Venkataramanan } 42780f9d5027SAnirudh Venkataramanan 4279cdedef59SAnirudh Venkataramanan netif_carrier_off(netdev); 4280cdedef59SAnirudh Venkataramanan 4281b6f934f0SBrett Creeley err = ice_force_phys_link_state(vsi, true); 4282b6f934f0SBrett Creeley if (err) { 4283b6f934f0SBrett Creeley netdev_err(netdev, 4284b6f934f0SBrett Creeley "Failed to set physical link up, error %d\n", err); 4285b6f934f0SBrett Creeley return err; 4286b6f934f0SBrett Creeley } 4287cdedef59SAnirudh Venkataramanan 4288b6f934f0SBrett Creeley err = ice_vsi_open(vsi); 4289cdedef59SAnirudh Venkataramanan if (err) 4290cdedef59SAnirudh Venkataramanan netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n", 4291cdedef59SAnirudh Venkataramanan vsi->vsi_num, vsi->vsw->sw_id); 4292cdedef59SAnirudh Venkataramanan return err; 4293cdedef59SAnirudh Venkataramanan } 4294cdedef59SAnirudh Venkataramanan 4295cdedef59SAnirudh Venkataramanan /** 4296cdedef59SAnirudh Venkataramanan * ice_stop - Disables a network interface 4297cdedef59SAnirudh Venkataramanan * @netdev: network interface device structure 4298cdedef59SAnirudh Venkataramanan * 4299cdedef59SAnirudh Venkataramanan * The stop entry point is called when an interface is de-activated by the OS, 4300cdedef59SAnirudh Venkataramanan * and the netdevice enters the DOWN state. The hardware is still under the 4301cdedef59SAnirudh Venkataramanan * driver's control, but the netdev interface is disabled. 4302cdedef59SAnirudh Venkataramanan * 4303cdedef59SAnirudh Venkataramanan * Returns success only - not allowed to fail 4304cdedef59SAnirudh Venkataramanan */ 4305cdedef59SAnirudh Venkataramanan static int ice_stop(struct net_device *netdev) 4306cdedef59SAnirudh Venkataramanan { 4307cdedef59SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 4308cdedef59SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 4309cdedef59SAnirudh Venkataramanan 4310cdedef59SAnirudh Venkataramanan ice_vsi_close(vsi); 4311cdedef59SAnirudh Venkataramanan 4312cdedef59SAnirudh Venkataramanan return 0; 4313cdedef59SAnirudh Venkataramanan } 4314cdedef59SAnirudh Venkataramanan 4315e94d4478SAnirudh Venkataramanan /** 4316e94d4478SAnirudh Venkataramanan * ice_features_check - Validate encapsulated packet conforms to limits 4317e94d4478SAnirudh Venkataramanan * @skb: skb buffer 4318e94d4478SAnirudh Venkataramanan * @netdev: This port's netdev 4319e94d4478SAnirudh Venkataramanan * @features: Offload features that the stack believes apply 4320e94d4478SAnirudh Venkataramanan */ 4321e94d4478SAnirudh Venkataramanan static netdev_features_t 4322e94d4478SAnirudh Venkataramanan ice_features_check(struct sk_buff *skb, 4323e94d4478SAnirudh Venkataramanan struct net_device __always_unused *netdev, 4324e94d4478SAnirudh Venkataramanan netdev_features_t features) 4325e94d4478SAnirudh Venkataramanan { 4326e94d4478SAnirudh Venkataramanan size_t len; 4327e94d4478SAnirudh Venkataramanan 4328e94d4478SAnirudh Venkataramanan /* No point in doing any of this if neither checksum nor GSO are 4329e94d4478SAnirudh Venkataramanan * being requested for this frame. We can rule out both by just 4330e94d4478SAnirudh Venkataramanan * checking for CHECKSUM_PARTIAL 4331e94d4478SAnirudh Venkataramanan */ 4332e94d4478SAnirudh Venkataramanan if (skb->ip_summed != CHECKSUM_PARTIAL) 4333e94d4478SAnirudh Venkataramanan return features; 4334e94d4478SAnirudh Venkataramanan 4335e94d4478SAnirudh Venkataramanan /* We cannot support GSO if the MSS is going to be less than 4336e94d4478SAnirudh Venkataramanan * 64 bytes. If it is then we need to drop support for GSO. 4337e94d4478SAnirudh Venkataramanan */ 4338e94d4478SAnirudh Venkataramanan if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) 4339e94d4478SAnirudh Venkataramanan features &= ~NETIF_F_GSO_MASK; 4340e94d4478SAnirudh Venkataramanan 4341e94d4478SAnirudh Venkataramanan len = skb_network_header(skb) - skb->data; 4342e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_MACLEN_MAX)) 4343e94d4478SAnirudh Venkataramanan goto out_rm_features; 4344e94d4478SAnirudh Venkataramanan 4345e94d4478SAnirudh Venkataramanan len = skb_transport_header(skb) - skb_network_header(skb); 4346e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_IPLEN_MAX)) 4347e94d4478SAnirudh Venkataramanan goto out_rm_features; 4348e94d4478SAnirudh Venkataramanan 4349e94d4478SAnirudh Venkataramanan if (skb->encapsulation) { 4350e94d4478SAnirudh Venkataramanan len = skb_inner_network_header(skb) - skb_transport_header(skb); 4351e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_L4LEN_MAX)) 4352e94d4478SAnirudh Venkataramanan goto out_rm_features; 4353e94d4478SAnirudh Venkataramanan 4354e94d4478SAnirudh Venkataramanan len = skb_inner_transport_header(skb) - 4355e94d4478SAnirudh Venkataramanan skb_inner_network_header(skb); 4356e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_IPLEN_MAX)) 4357e94d4478SAnirudh Venkataramanan goto out_rm_features; 4358e94d4478SAnirudh Venkataramanan } 4359e94d4478SAnirudh Venkataramanan 4360e94d4478SAnirudh Venkataramanan return features; 4361e94d4478SAnirudh Venkataramanan out_rm_features: 4362e94d4478SAnirudh Venkataramanan return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); 4363e94d4478SAnirudh Venkataramanan } 4364e94d4478SAnirudh Venkataramanan 4365cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops = { 4366cdedef59SAnirudh Venkataramanan .ndo_open = ice_open, 4367cdedef59SAnirudh Venkataramanan .ndo_stop = ice_stop, 43682b245cb2SAnirudh Venkataramanan .ndo_start_xmit = ice_start_xmit, 4369e94d4478SAnirudh Venkataramanan .ndo_features_check = ice_features_check, 4370e94d4478SAnirudh Venkataramanan .ndo_set_rx_mode = ice_set_rx_mode, 4371e94d4478SAnirudh Venkataramanan .ndo_set_mac_address = ice_set_mac_address, 4372e94d4478SAnirudh Venkataramanan .ndo_validate_addr = eth_validate_addr, 4373e94d4478SAnirudh Venkataramanan .ndo_change_mtu = ice_change_mtu, 4374fcea6f3dSAnirudh Venkataramanan .ndo_get_stats64 = ice_get_stats64, 43757c710869SAnirudh Venkataramanan .ndo_set_vf_spoofchk = ice_set_vf_spoofchk, 43767c710869SAnirudh Venkataramanan .ndo_set_vf_mac = ice_set_vf_mac, 43777c710869SAnirudh Venkataramanan .ndo_get_vf_config = ice_get_vf_cfg, 43787c710869SAnirudh Venkataramanan .ndo_set_vf_trust = ice_set_vf_trust, 43797c710869SAnirudh Venkataramanan .ndo_set_vf_vlan = ice_set_vf_port_vlan, 43807c710869SAnirudh Venkataramanan .ndo_set_vf_link_state = ice_set_vf_link_state, 4381d76a60baSAnirudh Venkataramanan .ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid, 4382d76a60baSAnirudh Venkataramanan .ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid, 4383d76a60baSAnirudh Venkataramanan .ndo_set_features = ice_set_features, 4384b1edc14aSMd Fahad Iqbal Polash .ndo_bridge_getlink = ice_bridge_getlink, 4385b1edc14aSMd Fahad Iqbal Polash .ndo_bridge_setlink = ice_bridge_setlink, 4386e94d4478SAnirudh Venkataramanan .ndo_fdb_add = ice_fdb_add, 4387e94d4478SAnirudh Venkataramanan .ndo_fdb_del = ice_fdb_del, 4388b3969fd7SSudheer Mogilappagari .ndo_tx_timeout = ice_tx_timeout, 4389cdedef59SAnirudh Venkataramanan }; 4390