1837f08fdSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 2837f08fdSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 3837f08fdSAnirudh Venkataramanan 4837f08fdSAnirudh Venkataramanan /* Intel(R) Ethernet Connection E800 Series Linux Driver */ 5837f08fdSAnirudh Venkataramanan 6837f08fdSAnirudh Venkataramanan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7837f08fdSAnirudh Venkataramanan 8837f08fdSAnirudh Venkataramanan #include "ice.h" 945d3d428SAnirudh Venkataramanan #include "ice_lib.h" 10837f08fdSAnirudh Venkataramanan 119ea47d81SAnirudh Venkataramanan #define DRV_VERSION "0.7.1-k" 12837f08fdSAnirudh Venkataramanan #define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver" 13fcea6f3dSAnirudh Venkataramanan const char ice_drv_ver[] = DRV_VERSION; 14837f08fdSAnirudh Venkataramanan static const char ice_driver_string[] = DRV_SUMMARY; 15837f08fdSAnirudh Venkataramanan static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation."; 16837f08fdSAnirudh Venkataramanan 17837f08fdSAnirudh Venkataramanan MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); 18837f08fdSAnirudh Venkataramanan MODULE_DESCRIPTION(DRV_SUMMARY); 1998674ebeSJesse Brandeburg MODULE_LICENSE("GPL v2"); 20837f08fdSAnirudh Venkataramanan MODULE_VERSION(DRV_VERSION); 21837f08fdSAnirudh Venkataramanan 22837f08fdSAnirudh Venkataramanan static int debug = -1; 23837f08fdSAnirudh Venkataramanan module_param(debug, int, 0644); 247ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 257ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXXXXX)"); 267ec59eeaSAnirudh Venkataramanan #else 277ec59eeaSAnirudh Venkataramanan MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)"); 287ec59eeaSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 29837f08fdSAnirudh Venkataramanan 30940b61afSAnirudh Venkataramanan static struct workqueue_struct *ice_wq; 31cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops; 32940b61afSAnirudh Venkataramanan 330b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf); 340b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf); 3528c2a645SAnirudh Venkataramanan 360f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf); 37fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi); 38fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf); 393a858ba3SAnirudh Venkataramanan 403a858ba3SAnirudh Venkataramanan /** 41b3969fd7SSudheer Mogilappagari * ice_get_tx_pending - returns number of Tx descriptors not processed 42b3969fd7SSudheer Mogilappagari * @ring: the ring of descriptors 43b3969fd7SSudheer Mogilappagari */ 44b3969fd7SSudheer Mogilappagari static u32 ice_get_tx_pending(struct ice_ring *ring) 45b3969fd7SSudheer Mogilappagari { 46b3969fd7SSudheer Mogilappagari u32 head, tail; 47b3969fd7SSudheer Mogilappagari 48b3969fd7SSudheer Mogilappagari head = ring->next_to_clean; 49b3969fd7SSudheer Mogilappagari tail = readl(ring->tail); 50b3969fd7SSudheer Mogilappagari 51b3969fd7SSudheer Mogilappagari if (head != tail) 52b3969fd7SSudheer Mogilappagari return (head < tail) ? 53b3969fd7SSudheer Mogilappagari tail - head : (tail + ring->count - head); 54b3969fd7SSudheer Mogilappagari return 0; 55b3969fd7SSudheer Mogilappagari } 56b3969fd7SSudheer Mogilappagari 57b3969fd7SSudheer Mogilappagari /** 58b3969fd7SSudheer Mogilappagari * ice_check_for_hang_subtask - check for and recover hung queues 59b3969fd7SSudheer Mogilappagari * @pf: pointer to PF struct 60b3969fd7SSudheer Mogilappagari */ 61b3969fd7SSudheer Mogilappagari static void ice_check_for_hang_subtask(struct ice_pf *pf) 62b3969fd7SSudheer Mogilappagari { 63b3969fd7SSudheer Mogilappagari struct ice_vsi *vsi = NULL; 64b3969fd7SSudheer Mogilappagari unsigned int i; 65b3969fd7SSudheer Mogilappagari u32 v, v_idx; 66b3969fd7SSudheer Mogilappagari int packets; 67b3969fd7SSudheer Mogilappagari 68b3969fd7SSudheer Mogilappagari ice_for_each_vsi(pf, v) 69b3969fd7SSudheer Mogilappagari if (pf->vsi[v] && pf->vsi[v]->type == ICE_VSI_PF) { 70b3969fd7SSudheer Mogilappagari vsi = pf->vsi[v]; 71b3969fd7SSudheer Mogilappagari break; 72b3969fd7SSudheer Mogilappagari } 73b3969fd7SSudheer Mogilappagari 74b3969fd7SSudheer Mogilappagari if (!vsi || test_bit(__ICE_DOWN, vsi->state)) 75b3969fd7SSudheer Mogilappagari return; 76b3969fd7SSudheer Mogilappagari 77b3969fd7SSudheer Mogilappagari if (!(vsi->netdev && netif_carrier_ok(vsi->netdev))) 78b3969fd7SSudheer Mogilappagari return; 79b3969fd7SSudheer Mogilappagari 80b3969fd7SSudheer Mogilappagari for (i = 0; i < vsi->num_txq; i++) { 81b3969fd7SSudheer Mogilappagari struct ice_ring *tx_ring = vsi->tx_rings[i]; 82b3969fd7SSudheer Mogilappagari 83b3969fd7SSudheer Mogilappagari if (tx_ring && tx_ring->desc) { 84b3969fd7SSudheer Mogilappagari int itr = ICE_ITR_NONE; 85b3969fd7SSudheer Mogilappagari 86b3969fd7SSudheer Mogilappagari /* If packet counter has not changed the queue is 87b3969fd7SSudheer Mogilappagari * likely stalled, so force an interrupt for this 88b3969fd7SSudheer Mogilappagari * queue. 89b3969fd7SSudheer Mogilappagari * 90b3969fd7SSudheer Mogilappagari * prev_pkt would be negative if there was no 91b3969fd7SSudheer Mogilappagari * pending work. 92b3969fd7SSudheer Mogilappagari */ 93b3969fd7SSudheer Mogilappagari packets = tx_ring->stats.pkts & INT_MAX; 94b3969fd7SSudheer Mogilappagari if (tx_ring->tx_stats.prev_pkt == packets) { 95b3969fd7SSudheer Mogilappagari /* Trigger sw interrupt to revive the queue */ 96b3969fd7SSudheer Mogilappagari v_idx = tx_ring->q_vector->v_idx; 97b3969fd7SSudheer Mogilappagari wr32(&vsi->back->hw, 98b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL(vsi->base_vector + v_idx), 99b3969fd7SSudheer Mogilappagari (itr << GLINT_DYN_CTL_ITR_INDX_S) | 100b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL_SWINT_TRIG_M | 101b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL_INTENA_MSK_M); 102b3969fd7SSudheer Mogilappagari continue; 103b3969fd7SSudheer Mogilappagari } 104b3969fd7SSudheer Mogilappagari 105b3969fd7SSudheer Mogilappagari /* Memory barrier between read of packet count and call 106b3969fd7SSudheer Mogilappagari * to ice_get_tx_pending() 107b3969fd7SSudheer Mogilappagari */ 108b3969fd7SSudheer Mogilappagari smp_rmb(); 109b3969fd7SSudheer Mogilappagari tx_ring->tx_stats.prev_pkt = 110b3969fd7SSudheer Mogilappagari ice_get_tx_pending(tx_ring) ? packets : -1; 111b3969fd7SSudheer Mogilappagari } 112b3969fd7SSudheer Mogilappagari } 113b3969fd7SSudheer Mogilappagari } 114b3969fd7SSudheer Mogilappagari 115b3969fd7SSudheer Mogilappagari /** 116e94d4478SAnirudh Venkataramanan * ice_add_mac_to_sync_list - creates list of mac addresses to be synced 117e94d4478SAnirudh Venkataramanan * @netdev: the net device on which the sync is happening 118e94d4478SAnirudh Venkataramanan * @addr: mac address to sync 119e94d4478SAnirudh Venkataramanan * 120e94d4478SAnirudh Venkataramanan * This is a callback function which is called by the in kernel device sync 121e94d4478SAnirudh Venkataramanan * functions (like __dev_uc_sync, __dev_mc_sync, etc). This function only 122e94d4478SAnirudh Venkataramanan * populates the tmp_sync_list, which is later used by ice_add_mac to add the 123e94d4478SAnirudh Venkataramanan * mac filters from the hardware. 124e94d4478SAnirudh Venkataramanan */ 125e94d4478SAnirudh Venkataramanan static int ice_add_mac_to_sync_list(struct net_device *netdev, const u8 *addr) 126e94d4478SAnirudh Venkataramanan { 127e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 128e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 129e94d4478SAnirudh Venkataramanan 130e94d4478SAnirudh Venkataramanan if (ice_add_mac_to_list(vsi, &vsi->tmp_sync_list, addr)) 131e94d4478SAnirudh Venkataramanan return -EINVAL; 132e94d4478SAnirudh Venkataramanan 133e94d4478SAnirudh Venkataramanan return 0; 134e94d4478SAnirudh Venkataramanan } 135e94d4478SAnirudh Venkataramanan 136e94d4478SAnirudh Venkataramanan /** 137e94d4478SAnirudh Venkataramanan * ice_add_mac_to_unsync_list - creates list of mac addresses to be unsynced 138e94d4478SAnirudh Venkataramanan * @netdev: the net device on which the unsync is happening 139e94d4478SAnirudh Venkataramanan * @addr: mac address to unsync 140e94d4478SAnirudh Venkataramanan * 141e94d4478SAnirudh Venkataramanan * This is a callback function which is called by the in kernel device unsync 142e94d4478SAnirudh Venkataramanan * functions (like __dev_uc_unsync, __dev_mc_unsync, etc). This function only 143e94d4478SAnirudh Venkataramanan * populates the tmp_unsync_list, which is later used by ice_remove_mac to 144e94d4478SAnirudh Venkataramanan * delete the mac filters from the hardware. 145e94d4478SAnirudh Venkataramanan */ 146e94d4478SAnirudh Venkataramanan static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr) 147e94d4478SAnirudh Venkataramanan { 148e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 149e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 150e94d4478SAnirudh Venkataramanan 151e94d4478SAnirudh Venkataramanan if (ice_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr)) 152e94d4478SAnirudh Venkataramanan return -EINVAL; 153e94d4478SAnirudh Venkataramanan 154e94d4478SAnirudh Venkataramanan return 0; 155e94d4478SAnirudh Venkataramanan } 156e94d4478SAnirudh Venkataramanan 157e94d4478SAnirudh Venkataramanan /** 158e94d4478SAnirudh Venkataramanan * ice_vsi_fltr_changed - check if filter state changed 159e94d4478SAnirudh Venkataramanan * @vsi: VSI to be checked 160e94d4478SAnirudh Venkataramanan * 161e94d4478SAnirudh Venkataramanan * returns true if filter state has changed, false otherwise. 162e94d4478SAnirudh Venkataramanan */ 163e94d4478SAnirudh Venkataramanan static bool ice_vsi_fltr_changed(struct ice_vsi *vsi) 164e94d4478SAnirudh Venkataramanan { 165e94d4478SAnirudh Venkataramanan return test_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags) || 166e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags) || 167e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 168e94d4478SAnirudh Venkataramanan } 169e94d4478SAnirudh Venkataramanan 170e94d4478SAnirudh Venkataramanan /** 171e94d4478SAnirudh Venkataramanan * ice_vsi_sync_fltr - Update the VSI filter list to the HW 172e94d4478SAnirudh Venkataramanan * @vsi: ptr to the VSI 173e94d4478SAnirudh Venkataramanan * 174e94d4478SAnirudh Venkataramanan * Push any outstanding VSI filter changes through the AdminQ. 175e94d4478SAnirudh Venkataramanan */ 176e94d4478SAnirudh Venkataramanan static int ice_vsi_sync_fltr(struct ice_vsi *vsi) 177e94d4478SAnirudh Venkataramanan { 178e94d4478SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 179e94d4478SAnirudh Venkataramanan struct net_device *netdev = vsi->netdev; 180e94d4478SAnirudh Venkataramanan bool promisc_forced_on = false; 181e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 182e94d4478SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 183e94d4478SAnirudh Venkataramanan enum ice_status status = 0; 184e94d4478SAnirudh Venkataramanan u32 changed_flags = 0; 185e94d4478SAnirudh Venkataramanan int err = 0; 186e94d4478SAnirudh Venkataramanan 187e94d4478SAnirudh Venkataramanan if (!vsi->netdev) 188e94d4478SAnirudh Venkataramanan return -EINVAL; 189e94d4478SAnirudh Venkataramanan 190e94d4478SAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, vsi->state)) 191e94d4478SAnirudh Venkataramanan usleep_range(1000, 2000); 192e94d4478SAnirudh Venkataramanan 193e94d4478SAnirudh Venkataramanan changed_flags = vsi->current_netdev_flags ^ vsi->netdev->flags; 194e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags = vsi->netdev->flags; 195e94d4478SAnirudh Venkataramanan 196e94d4478SAnirudh Venkataramanan INIT_LIST_HEAD(&vsi->tmp_sync_list); 197e94d4478SAnirudh Venkataramanan INIT_LIST_HEAD(&vsi->tmp_unsync_list); 198e94d4478SAnirudh Venkataramanan 199e94d4478SAnirudh Venkataramanan if (ice_vsi_fltr_changed(vsi)) { 200e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 201e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 202e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags); 203e94d4478SAnirudh Venkataramanan 204e94d4478SAnirudh Venkataramanan /* grab the netdev's addr_list_lock */ 205e94d4478SAnirudh Venkataramanan netif_addr_lock_bh(netdev); 206e94d4478SAnirudh Venkataramanan __dev_uc_sync(netdev, ice_add_mac_to_sync_list, 207e94d4478SAnirudh Venkataramanan ice_add_mac_to_unsync_list); 208e94d4478SAnirudh Venkataramanan __dev_mc_sync(netdev, ice_add_mac_to_sync_list, 209e94d4478SAnirudh Venkataramanan ice_add_mac_to_unsync_list); 210e94d4478SAnirudh Venkataramanan /* our temp lists are populated. release lock */ 211e94d4478SAnirudh Venkataramanan netif_addr_unlock_bh(netdev); 212e94d4478SAnirudh Venkataramanan } 213e94d4478SAnirudh Venkataramanan 214e94d4478SAnirudh Venkataramanan /* Remove mac addresses in the unsync list */ 215e94d4478SAnirudh Venkataramanan status = ice_remove_mac(hw, &vsi->tmp_unsync_list); 216e94d4478SAnirudh Venkataramanan ice_free_fltr_list(dev, &vsi->tmp_unsync_list); 217e94d4478SAnirudh Venkataramanan if (status) { 218e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Failed to delete MAC filters\n"); 219e94d4478SAnirudh Venkataramanan /* if we failed because of alloc failures, just bail */ 220e94d4478SAnirudh Venkataramanan if (status == ICE_ERR_NO_MEMORY) { 221e94d4478SAnirudh Venkataramanan err = -ENOMEM; 222e94d4478SAnirudh Venkataramanan goto out; 223e94d4478SAnirudh Venkataramanan } 224e94d4478SAnirudh Venkataramanan } 225e94d4478SAnirudh Venkataramanan 226e94d4478SAnirudh Venkataramanan /* Add mac addresses in the sync list */ 227e94d4478SAnirudh Venkataramanan status = ice_add_mac(hw, &vsi->tmp_sync_list); 228e94d4478SAnirudh Venkataramanan ice_free_fltr_list(dev, &vsi->tmp_sync_list); 229e94d4478SAnirudh Venkataramanan if (status) { 230e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Failed to add MAC filters\n"); 231e94d4478SAnirudh Venkataramanan /* If there is no more space for new umac filters, vsi 232e94d4478SAnirudh Venkataramanan * should go into promiscuous mode. There should be some 233e94d4478SAnirudh Venkataramanan * space reserved for promiscuous filters. 234e94d4478SAnirudh Venkataramanan */ 235e94d4478SAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOSPC && 236e94d4478SAnirudh Venkataramanan !test_and_set_bit(__ICE_FLTR_OVERFLOW_PROMISC, 237e94d4478SAnirudh Venkataramanan vsi->state)) { 238e94d4478SAnirudh Venkataramanan promisc_forced_on = true; 239e94d4478SAnirudh Venkataramanan netdev_warn(netdev, 240e94d4478SAnirudh Venkataramanan "Reached MAC filter limit, forcing promisc mode on VSI %d\n", 241e94d4478SAnirudh Venkataramanan vsi->vsi_num); 242e94d4478SAnirudh Venkataramanan } else { 243e94d4478SAnirudh Venkataramanan err = -EIO; 244e94d4478SAnirudh Venkataramanan goto out; 245e94d4478SAnirudh Venkataramanan } 246e94d4478SAnirudh Venkataramanan } 247e94d4478SAnirudh Venkataramanan /* check for changes in promiscuous modes */ 248e94d4478SAnirudh Venkataramanan if (changed_flags & IFF_ALLMULTI) 249e94d4478SAnirudh Venkataramanan netdev_warn(netdev, "Unsupported configuration\n"); 250e94d4478SAnirudh Venkataramanan 251e94d4478SAnirudh Venkataramanan if (((changed_flags & IFF_PROMISC) || promisc_forced_on) || 252e94d4478SAnirudh Venkataramanan test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) { 253e94d4478SAnirudh Venkataramanan clear_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags); 254e94d4478SAnirudh Venkataramanan if (vsi->current_netdev_flags & IFF_PROMISC) { 255e94d4478SAnirudh Venkataramanan /* Apply TX filter rule to get traffic from VMs */ 2564fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, true, 257e94d4478SAnirudh Venkataramanan ICE_FLTR_TX); 258e94d4478SAnirudh Venkataramanan if (status) { 259e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error setting default VSI %i tx rule\n", 260e94d4478SAnirudh Venkataramanan vsi->vsi_num); 261e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags &= ~IFF_PROMISC; 262e94d4478SAnirudh Venkataramanan err = -EIO; 263e94d4478SAnirudh Venkataramanan goto out_promisc; 264e94d4478SAnirudh Venkataramanan } 265e94d4478SAnirudh Venkataramanan /* Apply RX filter rule to get traffic from wire */ 2664fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, true, 267e94d4478SAnirudh Venkataramanan ICE_FLTR_RX); 268e94d4478SAnirudh Venkataramanan if (status) { 269e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error setting default VSI %i rx rule\n", 270e94d4478SAnirudh Venkataramanan vsi->vsi_num); 271e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags &= ~IFF_PROMISC; 272e94d4478SAnirudh Venkataramanan err = -EIO; 273e94d4478SAnirudh Venkataramanan goto out_promisc; 274e94d4478SAnirudh Venkataramanan } 275e94d4478SAnirudh Venkataramanan } else { 276e94d4478SAnirudh Venkataramanan /* Clear TX filter rule to stop traffic from VMs */ 2774fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, false, 278e94d4478SAnirudh Venkataramanan ICE_FLTR_TX); 279e94d4478SAnirudh Venkataramanan if (status) { 280e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error clearing default VSI %i tx rule\n", 281e94d4478SAnirudh Venkataramanan vsi->vsi_num); 282e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags |= IFF_PROMISC; 283e94d4478SAnirudh Venkataramanan err = -EIO; 284e94d4478SAnirudh Venkataramanan goto out_promisc; 285e94d4478SAnirudh Venkataramanan } 2864fb33f31SAnirudh Venkataramanan /* Clear RX filter to remove traffic from wire */ 2874fb33f31SAnirudh Venkataramanan status = ice_cfg_dflt_vsi(hw, vsi->idx, false, 288e94d4478SAnirudh Venkataramanan ICE_FLTR_RX); 289e94d4478SAnirudh Venkataramanan if (status) { 290e94d4478SAnirudh Venkataramanan netdev_err(netdev, "Error clearing default VSI %i rx rule\n", 291e94d4478SAnirudh Venkataramanan vsi->vsi_num); 292e94d4478SAnirudh Venkataramanan vsi->current_netdev_flags |= IFF_PROMISC; 293e94d4478SAnirudh Venkataramanan err = -EIO; 294e94d4478SAnirudh Venkataramanan goto out_promisc; 295e94d4478SAnirudh Venkataramanan } 296e94d4478SAnirudh Venkataramanan } 297e94d4478SAnirudh Venkataramanan } 298e94d4478SAnirudh Venkataramanan goto exit; 299e94d4478SAnirudh Venkataramanan 300e94d4478SAnirudh Venkataramanan out_promisc: 301e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags); 302e94d4478SAnirudh Venkataramanan goto exit; 303e94d4478SAnirudh Venkataramanan out: 304e94d4478SAnirudh Venkataramanan /* if something went wrong then set the changed flag so we try again */ 305e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 306e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 307e94d4478SAnirudh Venkataramanan exit: 308e94d4478SAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, vsi->state); 309e94d4478SAnirudh Venkataramanan return err; 310e94d4478SAnirudh Venkataramanan } 311e94d4478SAnirudh Venkataramanan 312e94d4478SAnirudh Venkataramanan /** 313e94d4478SAnirudh Venkataramanan * ice_sync_fltr_subtask - Sync the VSI filter list with HW 314e94d4478SAnirudh Venkataramanan * @pf: board private structure 315e94d4478SAnirudh Venkataramanan */ 316e94d4478SAnirudh Venkataramanan static void ice_sync_fltr_subtask(struct ice_pf *pf) 317e94d4478SAnirudh Venkataramanan { 318e94d4478SAnirudh Venkataramanan int v; 319e94d4478SAnirudh Venkataramanan 320e94d4478SAnirudh Venkataramanan if (!pf || !(test_bit(ICE_FLAG_FLTR_SYNC, pf->flags))) 321e94d4478SAnirudh Venkataramanan return; 322e94d4478SAnirudh Venkataramanan 323e94d4478SAnirudh Venkataramanan clear_bit(ICE_FLAG_FLTR_SYNC, pf->flags); 324e94d4478SAnirudh Venkataramanan 325e94d4478SAnirudh Venkataramanan for (v = 0; v < pf->num_alloc_vsi; v++) 326e94d4478SAnirudh Venkataramanan if (pf->vsi[v] && ice_vsi_fltr_changed(pf->vsi[v]) && 327e94d4478SAnirudh Venkataramanan ice_vsi_sync_fltr(pf->vsi[v])) { 328e94d4478SAnirudh Venkataramanan /* come back and try again later */ 329e94d4478SAnirudh Venkataramanan set_bit(ICE_FLAG_FLTR_SYNC, pf->flags); 330e94d4478SAnirudh Venkataramanan break; 331e94d4478SAnirudh Venkataramanan } 332e94d4478SAnirudh Venkataramanan } 333e94d4478SAnirudh Venkataramanan 334e94d4478SAnirudh Venkataramanan /** 3350b28b702SAnirudh Venkataramanan * ice_prepare_for_reset - prep for the core to reset 3360b28b702SAnirudh Venkataramanan * @pf: board private structure 3370b28b702SAnirudh Venkataramanan * 3380b28b702SAnirudh Venkataramanan * Inform or close all dependent features in prep for reset. 3390b28b702SAnirudh Venkataramanan */ 3400b28b702SAnirudh Venkataramanan static void 3410b28b702SAnirudh Venkataramanan ice_prepare_for_reset(struct ice_pf *pf) 3420b28b702SAnirudh Venkataramanan { 3430b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3440b28b702SAnirudh Venkataramanan 3450b28b702SAnirudh Venkataramanan /* disable the VSIs and their queues that are not already DOWN */ 3460b28b702SAnirudh Venkataramanan ice_pf_dis_all_vsi(pf); 3470b28b702SAnirudh Venkataramanan 3480b28b702SAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 3490f9d5027SAnirudh Venkataramanan 3500f9d5027SAnirudh Venkataramanan set_bit(__ICE_PREPARED_FOR_RESET, pf->state); 3510b28b702SAnirudh Venkataramanan } 3520b28b702SAnirudh Venkataramanan 3530b28b702SAnirudh Venkataramanan /** 3540b28b702SAnirudh Venkataramanan * ice_do_reset - Initiate one of many types of resets 3550b28b702SAnirudh Venkataramanan * @pf: board private structure 3560b28b702SAnirudh Venkataramanan * @reset_type: reset type requested 3570b28b702SAnirudh Venkataramanan * before this function was called. 3580b28b702SAnirudh Venkataramanan */ 3590b28b702SAnirudh Venkataramanan static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type) 3600b28b702SAnirudh Venkataramanan { 3610b28b702SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 3620b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3630b28b702SAnirudh Venkataramanan 3640b28b702SAnirudh Venkataramanan dev_dbg(dev, "reset_type 0x%x requested\n", reset_type); 3650b28b702SAnirudh Venkataramanan WARN_ON(in_interrupt()); 3660b28b702SAnirudh Venkataramanan 3670b28b702SAnirudh Venkataramanan ice_prepare_for_reset(pf); 3680b28b702SAnirudh Venkataramanan 3690b28b702SAnirudh Venkataramanan /* trigger the reset */ 3700b28b702SAnirudh Venkataramanan if (ice_reset(hw, reset_type)) { 3710b28b702SAnirudh Venkataramanan dev_err(dev, "reset %d failed\n", reset_type); 3720b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 3735df7e45dSDave Ertman clear_bit(__ICE_RESET_OICR_RECV, pf->state); 3740f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 3755df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 3765df7e45dSDave Ertman clear_bit(__ICE_CORER_REQ, pf->state); 3775df7e45dSDave Ertman clear_bit(__ICE_GLOBR_REQ, pf->state); 3780b28b702SAnirudh Venkataramanan return; 3790b28b702SAnirudh Venkataramanan } 3800b28b702SAnirudh Venkataramanan 3810f9d5027SAnirudh Venkataramanan /* PFR is a bit of a special case because it doesn't result in an OICR 3820f9d5027SAnirudh Venkataramanan * interrupt. So for PFR, rebuild after the reset and clear the reset- 3830f9d5027SAnirudh Venkataramanan * associated state bits. 3840f9d5027SAnirudh Venkataramanan */ 3850b28b702SAnirudh Venkataramanan if (reset_type == ICE_RESET_PFR) { 3860b28b702SAnirudh Venkataramanan pf->pfr_count++; 3870b28b702SAnirudh Venkataramanan ice_rebuild(pf); 3880f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 3895df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 3900b28b702SAnirudh Venkataramanan } 3910b28b702SAnirudh Venkataramanan } 3920b28b702SAnirudh Venkataramanan 3930b28b702SAnirudh Venkataramanan /** 3940b28b702SAnirudh Venkataramanan * ice_reset_subtask - Set up for resetting the device and driver 3950b28b702SAnirudh Venkataramanan * @pf: board private structure 3960b28b702SAnirudh Venkataramanan */ 3970b28b702SAnirudh Venkataramanan static void ice_reset_subtask(struct ice_pf *pf) 3980b28b702SAnirudh Venkataramanan { 3990f9d5027SAnirudh Venkataramanan enum ice_reset_req reset_type = ICE_RESET_INVAL; 4000b28b702SAnirudh Venkataramanan 4010b28b702SAnirudh Venkataramanan /* When a CORER/GLOBR/EMPR is about to happen, the hardware triggers an 4020f9d5027SAnirudh Venkataramanan * OICR interrupt. The OICR handler (ice_misc_intr) determines what type 4030f9d5027SAnirudh Venkataramanan * of reset is pending and sets bits in pf->state indicating the reset 4045df7e45dSDave Ertman * type and __ICE_RESET_OICR_RECV. So, if the latter bit is set 4050f9d5027SAnirudh Venkataramanan * prepare for pending reset if not already (for PF software-initiated 4060f9d5027SAnirudh Venkataramanan * global resets the software should already be prepared for it as 4070f9d5027SAnirudh Venkataramanan * indicated by __ICE_PREPARED_FOR_RESET; for global resets initiated 4080f9d5027SAnirudh Venkataramanan * by firmware or software on other PFs, that bit is not set so prepare 4090f9d5027SAnirudh Venkataramanan * for the reset now), poll for reset done, rebuild and return. 4100b28b702SAnirudh Venkataramanan */ 4115df7e45dSDave Ertman if (test_bit(__ICE_RESET_OICR_RECV, pf->state)) { 4120b28b702SAnirudh Venkataramanan clear_bit(__ICE_GLOBR_RECV, pf->state); 4130b28b702SAnirudh Venkataramanan clear_bit(__ICE_CORER_RECV, pf->state); 4140f9d5027SAnirudh Venkataramanan if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) 4150b28b702SAnirudh Venkataramanan ice_prepare_for_reset(pf); 4160b28b702SAnirudh Venkataramanan 4170b28b702SAnirudh Venkataramanan /* make sure we are ready to rebuild */ 418fd2a9817SAnirudh Venkataramanan if (ice_check_reset(&pf->hw)) { 4190b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 420fd2a9817SAnirudh Venkataramanan } else { 421fd2a9817SAnirudh Venkataramanan /* done with reset. start rebuild */ 422fd2a9817SAnirudh Venkataramanan pf->hw.reset_ongoing = false; 4230b28b702SAnirudh Venkataramanan ice_rebuild(pf); 4240f9d5027SAnirudh Venkataramanan /* clear bit to resume normal operations, but 4250f9d5027SAnirudh Venkataramanan * ICE_NEEDS_RESTART bit is set incase rebuild failed 4260f9d5027SAnirudh Venkataramanan */ 4275df7e45dSDave Ertman clear_bit(__ICE_RESET_OICR_RECV, pf->state); 4280f9d5027SAnirudh Venkataramanan clear_bit(__ICE_PREPARED_FOR_RESET, pf->state); 4295df7e45dSDave Ertman clear_bit(__ICE_PFR_REQ, pf->state); 4305df7e45dSDave Ertman clear_bit(__ICE_CORER_REQ, pf->state); 4315df7e45dSDave Ertman clear_bit(__ICE_GLOBR_REQ, pf->state); 4320f9d5027SAnirudh Venkataramanan } 4330f9d5027SAnirudh Venkataramanan 4340f9d5027SAnirudh Venkataramanan return; 4350b28b702SAnirudh Venkataramanan } 4360b28b702SAnirudh Venkataramanan 4370b28b702SAnirudh Venkataramanan /* No pending resets to finish processing. Check for new resets */ 4385df7e45dSDave Ertman if (test_bit(__ICE_PFR_REQ, pf->state)) 4390f9d5027SAnirudh Venkataramanan reset_type = ICE_RESET_PFR; 4405df7e45dSDave Ertman if (test_bit(__ICE_CORER_REQ, pf->state)) 4410f9d5027SAnirudh Venkataramanan reset_type = ICE_RESET_CORER; 4425df7e45dSDave Ertman if (test_bit(__ICE_GLOBR_REQ, pf->state)) 4430b28b702SAnirudh Venkataramanan reset_type = ICE_RESET_GLOBR; 4440f9d5027SAnirudh Venkataramanan /* If no valid reset type requested just return */ 4450f9d5027SAnirudh Venkataramanan if (reset_type == ICE_RESET_INVAL) 4460f9d5027SAnirudh Venkataramanan return; 4470b28b702SAnirudh Venkataramanan 4480f9d5027SAnirudh Venkataramanan /* reset if not already down or busy */ 4490b28b702SAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 4500b28b702SAnirudh Venkataramanan !test_bit(__ICE_CFG_BUSY, pf->state)) { 4510b28b702SAnirudh Venkataramanan ice_do_reset(pf, reset_type); 4520b28b702SAnirudh Venkataramanan } 4530b28b702SAnirudh Venkataramanan } 4540b28b702SAnirudh Venkataramanan 4550b28b702SAnirudh Venkataramanan /** 456fcea6f3dSAnirudh Venkataramanan * ice_watchdog_subtask - periodic tasks not using event driven scheduling 457fcea6f3dSAnirudh Venkataramanan * @pf: board private structure 458fcea6f3dSAnirudh Venkataramanan */ 459fcea6f3dSAnirudh Venkataramanan static void ice_watchdog_subtask(struct ice_pf *pf) 460fcea6f3dSAnirudh Venkataramanan { 461fcea6f3dSAnirudh Venkataramanan int i; 462fcea6f3dSAnirudh Venkataramanan 463fcea6f3dSAnirudh Venkataramanan /* if interface is down do nothing */ 464fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state) || 465fcea6f3dSAnirudh Venkataramanan test_bit(__ICE_CFG_BUSY, pf->state)) 466fcea6f3dSAnirudh Venkataramanan return; 467fcea6f3dSAnirudh Venkataramanan 468fcea6f3dSAnirudh Venkataramanan /* make sure we don't do these things too often */ 469fcea6f3dSAnirudh Venkataramanan if (time_before(jiffies, 470fcea6f3dSAnirudh Venkataramanan pf->serv_tmr_prev + pf->serv_tmr_period)) 471fcea6f3dSAnirudh Venkataramanan return; 472fcea6f3dSAnirudh Venkataramanan 473fcea6f3dSAnirudh Venkataramanan pf->serv_tmr_prev = jiffies; 474fcea6f3dSAnirudh Venkataramanan 475fcea6f3dSAnirudh Venkataramanan /* Update the stats for active netdevs so the network stack 476fcea6f3dSAnirudh Venkataramanan * can look at updated numbers whenever it cares to 477fcea6f3dSAnirudh Venkataramanan */ 478fcea6f3dSAnirudh Venkataramanan ice_update_pf_stats(pf); 479fcea6f3dSAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) 480fcea6f3dSAnirudh Venkataramanan if (pf->vsi[i] && pf->vsi[i]->netdev) 481fcea6f3dSAnirudh Venkataramanan ice_update_vsi_stats(pf->vsi[i]); 482fcea6f3dSAnirudh Venkataramanan } 483fcea6f3dSAnirudh Venkataramanan 484fcea6f3dSAnirudh Venkataramanan /** 485cdedef59SAnirudh Venkataramanan * ice_print_link_msg - print link up or down message 486cdedef59SAnirudh Venkataramanan * @vsi: the VSI whose link status is being queried 487cdedef59SAnirudh Venkataramanan * @isup: boolean for if the link is now up or down 488cdedef59SAnirudh Venkataramanan */ 489fcea6f3dSAnirudh Venkataramanan void ice_print_link_msg(struct ice_vsi *vsi, bool isup) 490cdedef59SAnirudh Venkataramanan { 491cdedef59SAnirudh Venkataramanan const char *speed; 492cdedef59SAnirudh Venkataramanan const char *fc; 493cdedef59SAnirudh Venkataramanan 494cdedef59SAnirudh Venkataramanan if (vsi->current_isup == isup) 495cdedef59SAnirudh Venkataramanan return; 496cdedef59SAnirudh Venkataramanan 497cdedef59SAnirudh Venkataramanan vsi->current_isup = isup; 498cdedef59SAnirudh Venkataramanan 499cdedef59SAnirudh Venkataramanan if (!isup) { 500cdedef59SAnirudh Venkataramanan netdev_info(vsi->netdev, "NIC Link is Down\n"); 501cdedef59SAnirudh Venkataramanan return; 502cdedef59SAnirudh Venkataramanan } 503cdedef59SAnirudh Venkataramanan 504cdedef59SAnirudh Venkataramanan switch (vsi->port_info->phy.link_info.link_speed) { 505cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_40GB: 506cdedef59SAnirudh Venkataramanan speed = "40 G"; 507cdedef59SAnirudh Venkataramanan break; 508cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 509cdedef59SAnirudh Venkataramanan speed = "25 G"; 510cdedef59SAnirudh Venkataramanan break; 511cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_20GB: 512cdedef59SAnirudh Venkataramanan speed = "20 G"; 513cdedef59SAnirudh Venkataramanan break; 514cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_10GB: 515cdedef59SAnirudh Venkataramanan speed = "10 G"; 516cdedef59SAnirudh Venkataramanan break; 517cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_5GB: 518cdedef59SAnirudh Venkataramanan speed = "5 G"; 519cdedef59SAnirudh Venkataramanan break; 520cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_2500MB: 521cdedef59SAnirudh Venkataramanan speed = "2.5 G"; 522cdedef59SAnirudh Venkataramanan break; 523cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_1000MB: 524cdedef59SAnirudh Venkataramanan speed = "1 G"; 525cdedef59SAnirudh Venkataramanan break; 526cdedef59SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100MB: 527cdedef59SAnirudh Venkataramanan speed = "100 M"; 528cdedef59SAnirudh Venkataramanan break; 529cdedef59SAnirudh Venkataramanan default: 530cdedef59SAnirudh Venkataramanan speed = "Unknown"; 531cdedef59SAnirudh Venkataramanan break; 532cdedef59SAnirudh Venkataramanan } 533cdedef59SAnirudh Venkataramanan 534cdedef59SAnirudh Venkataramanan switch (vsi->port_info->fc.current_mode) { 535cdedef59SAnirudh Venkataramanan case ICE_FC_FULL: 536cdedef59SAnirudh Venkataramanan fc = "RX/TX"; 537cdedef59SAnirudh Venkataramanan break; 538cdedef59SAnirudh Venkataramanan case ICE_FC_TX_PAUSE: 539cdedef59SAnirudh Venkataramanan fc = "TX"; 540cdedef59SAnirudh Venkataramanan break; 541cdedef59SAnirudh Venkataramanan case ICE_FC_RX_PAUSE: 542cdedef59SAnirudh Venkataramanan fc = "RX"; 543cdedef59SAnirudh Venkataramanan break; 544cdedef59SAnirudh Venkataramanan default: 545cdedef59SAnirudh Venkataramanan fc = "Unknown"; 546cdedef59SAnirudh Venkataramanan break; 547cdedef59SAnirudh Venkataramanan } 548cdedef59SAnirudh Venkataramanan 549cdedef59SAnirudh Venkataramanan netdev_info(vsi->netdev, "NIC Link is up %sbps, Flow Control: %s\n", 550cdedef59SAnirudh Venkataramanan speed, fc); 551cdedef59SAnirudh Venkataramanan } 552cdedef59SAnirudh Venkataramanan 553cdedef59SAnirudh Venkataramanan /** 5540b28b702SAnirudh Venkataramanan * ice_init_link_events - enable/initialize link events 5550b28b702SAnirudh Venkataramanan * @pi: pointer to the port_info instance 5560b28b702SAnirudh Venkataramanan * 5570b28b702SAnirudh Venkataramanan * Returns -EIO on failure, 0 on success 5580b28b702SAnirudh Venkataramanan */ 5590b28b702SAnirudh Venkataramanan static int ice_init_link_events(struct ice_port_info *pi) 5600b28b702SAnirudh Venkataramanan { 5610b28b702SAnirudh Venkataramanan u16 mask; 5620b28b702SAnirudh Venkataramanan 5630b28b702SAnirudh Venkataramanan mask = ~((u16)(ICE_AQ_LINK_EVENT_UPDOWN | ICE_AQ_LINK_EVENT_MEDIA_NA | 5640b28b702SAnirudh Venkataramanan ICE_AQ_LINK_EVENT_MODULE_QUAL_FAIL)); 5650b28b702SAnirudh Venkataramanan 5660b28b702SAnirudh Venkataramanan if (ice_aq_set_event_mask(pi->hw, pi->lport, mask, NULL)) { 5670b28b702SAnirudh Venkataramanan dev_dbg(ice_hw_to_dev(pi->hw), 5680b28b702SAnirudh Venkataramanan "Failed to set link event mask for port %d\n", 5690b28b702SAnirudh Venkataramanan pi->lport); 5700b28b702SAnirudh Venkataramanan return -EIO; 5710b28b702SAnirudh Venkataramanan } 5720b28b702SAnirudh Venkataramanan 5730b28b702SAnirudh Venkataramanan if (ice_aq_get_link_info(pi, true, NULL, NULL)) { 5740b28b702SAnirudh Venkataramanan dev_dbg(ice_hw_to_dev(pi->hw), 5750b28b702SAnirudh Venkataramanan "Failed to enable link events for port %d\n", 5760b28b702SAnirudh Venkataramanan pi->lport); 5770b28b702SAnirudh Venkataramanan return -EIO; 5780b28b702SAnirudh Venkataramanan } 5790b28b702SAnirudh Venkataramanan 5800b28b702SAnirudh Venkataramanan return 0; 5810b28b702SAnirudh Venkataramanan } 5820b28b702SAnirudh Venkataramanan 5830b28b702SAnirudh Venkataramanan /** 5840b28b702SAnirudh Venkataramanan * ice_vsi_link_event - update the vsi's netdev 5850b28b702SAnirudh Venkataramanan * @vsi: the vsi on which the link event occurred 5860b28b702SAnirudh Venkataramanan * @link_up: whether or not the vsi needs to be set up or down 5870b28b702SAnirudh Venkataramanan */ 5880b28b702SAnirudh Venkataramanan static void ice_vsi_link_event(struct ice_vsi *vsi, bool link_up) 5890b28b702SAnirudh Venkataramanan { 5900b28b702SAnirudh Venkataramanan if (!vsi || test_bit(__ICE_DOWN, vsi->state)) 5910b28b702SAnirudh Venkataramanan return; 5920b28b702SAnirudh Venkataramanan 5930b28b702SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 5940b28b702SAnirudh Venkataramanan if (!vsi->netdev) { 5950b28b702SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, 5960b28b702SAnirudh Venkataramanan "vsi->netdev is not initialized!\n"); 5970b28b702SAnirudh Venkataramanan return; 5980b28b702SAnirudh Venkataramanan } 5990b28b702SAnirudh Venkataramanan if (link_up) { 6000b28b702SAnirudh Venkataramanan netif_carrier_on(vsi->netdev); 6010b28b702SAnirudh Venkataramanan netif_tx_wake_all_queues(vsi->netdev); 6020b28b702SAnirudh Venkataramanan } else { 6030b28b702SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 6040b28b702SAnirudh Venkataramanan netif_tx_stop_all_queues(vsi->netdev); 6050b28b702SAnirudh Venkataramanan } 6060b28b702SAnirudh Venkataramanan } 6070b28b702SAnirudh Venkataramanan } 6080b28b702SAnirudh Venkataramanan 6090b28b702SAnirudh Venkataramanan /** 6100b28b702SAnirudh Venkataramanan * ice_link_event - process the link event 6110b28b702SAnirudh Venkataramanan * @pf: pf that the link event is associated with 6120b28b702SAnirudh Venkataramanan * @pi: port_info for the port that the link event is associated with 6130b28b702SAnirudh Venkataramanan * 6140b28b702SAnirudh Venkataramanan * Returns -EIO if ice_get_link_status() fails 6150b28b702SAnirudh Venkataramanan * Returns 0 on success 6160b28b702SAnirudh Venkataramanan */ 6170b28b702SAnirudh Venkataramanan static int 6180b28b702SAnirudh Venkataramanan ice_link_event(struct ice_pf *pf, struct ice_port_info *pi) 6190b28b702SAnirudh Venkataramanan { 6200b28b702SAnirudh Venkataramanan u8 new_link_speed, old_link_speed; 6210b28b702SAnirudh Venkataramanan struct ice_phy_info *phy_info; 6220b28b702SAnirudh Venkataramanan bool new_link_same_as_old; 6230b28b702SAnirudh Venkataramanan bool new_link, old_link; 6240b28b702SAnirudh Venkataramanan u8 lport; 6250b28b702SAnirudh Venkataramanan u16 v; 6260b28b702SAnirudh Venkataramanan 6270b28b702SAnirudh Venkataramanan phy_info = &pi->phy; 6280b28b702SAnirudh Venkataramanan phy_info->link_info_old = phy_info->link_info; 6290b28b702SAnirudh Venkataramanan /* Force ice_get_link_status() to update link info */ 6300b28b702SAnirudh Venkataramanan phy_info->get_link_info = true; 6310b28b702SAnirudh Venkataramanan 6320b28b702SAnirudh Venkataramanan old_link = (phy_info->link_info_old.link_info & ICE_AQ_LINK_UP); 6330b28b702SAnirudh Venkataramanan old_link_speed = phy_info->link_info_old.link_speed; 6340b28b702SAnirudh Venkataramanan 6350b28b702SAnirudh Venkataramanan lport = pi->lport; 6360b28b702SAnirudh Venkataramanan if (ice_get_link_status(pi, &new_link)) { 6370b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 6380b28b702SAnirudh Venkataramanan "Could not get link status for port %d\n", lport); 6390b28b702SAnirudh Venkataramanan return -EIO; 6400b28b702SAnirudh Venkataramanan } 6410b28b702SAnirudh Venkataramanan 6420b28b702SAnirudh Venkataramanan new_link_speed = phy_info->link_info.link_speed; 6430b28b702SAnirudh Venkataramanan 6440b28b702SAnirudh Venkataramanan new_link_same_as_old = (new_link == old_link && 6450b28b702SAnirudh Venkataramanan new_link_speed == old_link_speed); 6460b28b702SAnirudh Venkataramanan 6470b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) { 6480b28b702SAnirudh Venkataramanan struct ice_vsi *vsi = pf->vsi[v]; 6490b28b702SAnirudh Venkataramanan 6500b28b702SAnirudh Venkataramanan if (!vsi || !vsi->port_info) 6510b28b702SAnirudh Venkataramanan continue; 6520b28b702SAnirudh Venkataramanan 6530b28b702SAnirudh Venkataramanan if (new_link_same_as_old && 6540b28b702SAnirudh Venkataramanan (test_bit(__ICE_DOWN, vsi->state) || 6550b28b702SAnirudh Venkataramanan new_link == netif_carrier_ok(vsi->netdev))) 6560b28b702SAnirudh Venkataramanan continue; 6570b28b702SAnirudh Venkataramanan 6580b28b702SAnirudh Venkataramanan if (vsi->port_info->lport == lport) { 6590b28b702SAnirudh Venkataramanan ice_print_link_msg(vsi, new_link); 6600b28b702SAnirudh Venkataramanan ice_vsi_link_event(vsi, new_link); 6610b28b702SAnirudh Venkataramanan } 6620b28b702SAnirudh Venkataramanan } 6630b28b702SAnirudh Venkataramanan 6640b28b702SAnirudh Venkataramanan return 0; 6650b28b702SAnirudh Venkataramanan } 6660b28b702SAnirudh Venkataramanan 6670b28b702SAnirudh Venkataramanan /** 6680b28b702SAnirudh Venkataramanan * ice_handle_link_event - handle link event via ARQ 6690b28b702SAnirudh Venkataramanan * @pf: pf that the link event is associated with 6700b28b702SAnirudh Venkataramanan * 6710b28b702SAnirudh Venkataramanan * Return -EINVAL if port_info is null 6720b28b702SAnirudh Venkataramanan * Return status on succes 6730b28b702SAnirudh Venkataramanan */ 6740b28b702SAnirudh Venkataramanan static int ice_handle_link_event(struct ice_pf *pf) 6750b28b702SAnirudh Venkataramanan { 6760b28b702SAnirudh Venkataramanan struct ice_port_info *port_info; 6770b28b702SAnirudh Venkataramanan int status; 6780b28b702SAnirudh Venkataramanan 6790b28b702SAnirudh Venkataramanan port_info = pf->hw.port_info; 6800b28b702SAnirudh Venkataramanan if (!port_info) 6810b28b702SAnirudh Venkataramanan return -EINVAL; 6820b28b702SAnirudh Venkataramanan 6830b28b702SAnirudh Venkataramanan status = ice_link_event(pf, port_info); 6840b28b702SAnirudh Venkataramanan if (status) 6850b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 6860b28b702SAnirudh Venkataramanan "Could not process link event, error %d\n", status); 6870b28b702SAnirudh Venkataramanan 6880b28b702SAnirudh Venkataramanan return status; 6890b28b702SAnirudh Venkataramanan } 6900b28b702SAnirudh Venkataramanan 6910b28b702SAnirudh Venkataramanan /** 692940b61afSAnirudh Venkataramanan * __ice_clean_ctrlq - helper function to clean controlq rings 693940b61afSAnirudh Venkataramanan * @pf: ptr to struct ice_pf 694940b61afSAnirudh Venkataramanan * @q_type: specific Control queue type 695940b61afSAnirudh Venkataramanan */ 696940b61afSAnirudh Venkataramanan static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) 697940b61afSAnirudh Venkataramanan { 698940b61afSAnirudh Venkataramanan struct ice_rq_event_info event; 699940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 700940b61afSAnirudh Venkataramanan struct ice_ctl_q_info *cq; 701940b61afSAnirudh Venkataramanan u16 pending, i = 0; 702940b61afSAnirudh Venkataramanan const char *qtype; 703940b61afSAnirudh Venkataramanan u32 oldval, val; 704940b61afSAnirudh Venkataramanan 7050b28b702SAnirudh Venkataramanan /* Do not clean control queue if/when PF reset fails */ 7060b28b702SAnirudh Venkataramanan if (test_bit(__ICE_RESET_FAILED, pf->state)) 7070b28b702SAnirudh Venkataramanan return 0; 7080b28b702SAnirudh Venkataramanan 709940b61afSAnirudh Venkataramanan switch (q_type) { 710940b61afSAnirudh Venkataramanan case ICE_CTL_Q_ADMIN: 711940b61afSAnirudh Venkataramanan cq = &hw->adminq; 712940b61afSAnirudh Venkataramanan qtype = "Admin"; 713940b61afSAnirudh Venkataramanan break; 714940b61afSAnirudh Venkataramanan default: 715940b61afSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown control queue type 0x%x\n", 716940b61afSAnirudh Venkataramanan q_type); 717940b61afSAnirudh Venkataramanan return 0; 718940b61afSAnirudh Venkataramanan } 719940b61afSAnirudh Venkataramanan 720940b61afSAnirudh Venkataramanan /* check for error indications - PF_xx_AxQLEN register layout for 721940b61afSAnirudh Venkataramanan * FW/MBX/SB are identical so just use defines for PF_FW_AxQLEN. 722940b61afSAnirudh Venkataramanan */ 723940b61afSAnirudh Venkataramanan val = rd32(hw, cq->rq.len); 724940b61afSAnirudh Venkataramanan if (val & (PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M | 725940b61afSAnirudh Venkataramanan PF_FW_ARQLEN_ARQCRIT_M)) { 726940b61afSAnirudh Venkataramanan oldval = val; 727940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQVFE_M) 728940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 729940b61afSAnirudh Venkataramanan "%s Receive Queue VF Error detected\n", qtype); 730940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQOVFL_M) { 731940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 732940b61afSAnirudh Venkataramanan "%s Receive Queue Overflow Error detected\n", 733940b61afSAnirudh Venkataramanan qtype); 734940b61afSAnirudh Venkataramanan } 735940b61afSAnirudh Venkataramanan if (val & PF_FW_ARQLEN_ARQCRIT_M) 736940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 737940b61afSAnirudh Venkataramanan "%s Receive Queue Critical Error detected\n", 738940b61afSAnirudh Venkataramanan qtype); 739940b61afSAnirudh Venkataramanan val &= ~(PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M | 740940b61afSAnirudh Venkataramanan PF_FW_ARQLEN_ARQCRIT_M); 741940b61afSAnirudh Venkataramanan if (oldval != val) 742940b61afSAnirudh Venkataramanan wr32(hw, cq->rq.len, val); 743940b61afSAnirudh Venkataramanan } 744940b61afSAnirudh Venkataramanan 745940b61afSAnirudh Venkataramanan val = rd32(hw, cq->sq.len); 746940b61afSAnirudh Venkataramanan if (val & (PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M | 747940b61afSAnirudh Venkataramanan PF_FW_ATQLEN_ATQCRIT_M)) { 748940b61afSAnirudh Venkataramanan oldval = val; 749940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQVFE_M) 750940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 751940b61afSAnirudh Venkataramanan "%s Send Queue VF Error detected\n", qtype); 752940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQOVFL_M) { 753940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 754940b61afSAnirudh Venkataramanan "%s Send Queue Overflow Error detected\n", 755940b61afSAnirudh Venkataramanan qtype); 756940b61afSAnirudh Venkataramanan } 757940b61afSAnirudh Venkataramanan if (val & PF_FW_ATQLEN_ATQCRIT_M) 758940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 759940b61afSAnirudh Venkataramanan "%s Send Queue Critical Error detected\n", 760940b61afSAnirudh Venkataramanan qtype); 761940b61afSAnirudh Venkataramanan val &= ~(PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M | 762940b61afSAnirudh Venkataramanan PF_FW_ATQLEN_ATQCRIT_M); 763940b61afSAnirudh Venkataramanan if (oldval != val) 764940b61afSAnirudh Venkataramanan wr32(hw, cq->sq.len, val); 765940b61afSAnirudh Venkataramanan } 766940b61afSAnirudh Venkataramanan 767940b61afSAnirudh Venkataramanan event.buf_len = cq->rq_buf_size; 768940b61afSAnirudh Venkataramanan event.msg_buf = devm_kzalloc(&pf->pdev->dev, event.buf_len, 769940b61afSAnirudh Venkataramanan GFP_KERNEL); 770940b61afSAnirudh Venkataramanan if (!event.msg_buf) 771940b61afSAnirudh Venkataramanan return 0; 772940b61afSAnirudh Venkataramanan 773940b61afSAnirudh Venkataramanan do { 774940b61afSAnirudh Venkataramanan enum ice_status ret; 7750b28b702SAnirudh Venkataramanan u16 opcode; 776940b61afSAnirudh Venkataramanan 777940b61afSAnirudh Venkataramanan ret = ice_clean_rq_elem(hw, cq, &event, &pending); 778940b61afSAnirudh Venkataramanan if (ret == ICE_ERR_AQ_NO_WORK) 779940b61afSAnirudh Venkataramanan break; 780940b61afSAnirudh Venkataramanan if (ret) { 781940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 782940b61afSAnirudh Venkataramanan "%s Receive Queue event error %d\n", qtype, 783940b61afSAnirudh Venkataramanan ret); 784940b61afSAnirudh Venkataramanan break; 785940b61afSAnirudh Venkataramanan } 7860b28b702SAnirudh Venkataramanan 7870b28b702SAnirudh Venkataramanan opcode = le16_to_cpu(event.desc.opcode); 7880b28b702SAnirudh Venkataramanan 7890b28b702SAnirudh Venkataramanan switch (opcode) { 7900b28b702SAnirudh Venkataramanan case ice_aqc_opc_get_link_status: 7910b28b702SAnirudh Venkataramanan if (ice_handle_link_event(pf)) 7920b28b702SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 7933968540bSAnirudh Venkataramanan "Could not handle link event\n"); 7940b28b702SAnirudh Venkataramanan break; 7958b97ceb1SHieu Tran case ice_aqc_opc_fw_logging: 7968b97ceb1SHieu Tran ice_output_fw_log(hw, &event.desc, event.msg_buf); 7978b97ceb1SHieu Tran break; 7980b28b702SAnirudh Venkataramanan default: 7990b28b702SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 8000b28b702SAnirudh Venkataramanan "%s Receive Queue unknown event 0x%04x ignored\n", 8010b28b702SAnirudh Venkataramanan qtype, opcode); 8020b28b702SAnirudh Venkataramanan break; 8030b28b702SAnirudh Venkataramanan } 804940b61afSAnirudh Venkataramanan } while (pending && (i++ < ICE_DFLT_IRQ_WORK)); 805940b61afSAnirudh Venkataramanan 806940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, event.msg_buf); 807940b61afSAnirudh Venkataramanan 808940b61afSAnirudh Venkataramanan return pending && (i == ICE_DFLT_IRQ_WORK); 809940b61afSAnirudh Venkataramanan } 810940b61afSAnirudh Venkataramanan 811940b61afSAnirudh Venkataramanan /** 8123d6b640eSAnirudh Venkataramanan * ice_ctrlq_pending - check if there is a difference between ntc and ntu 8133d6b640eSAnirudh Venkataramanan * @hw: pointer to hardware info 8143d6b640eSAnirudh Venkataramanan * @cq: control queue information 8153d6b640eSAnirudh Venkataramanan * 8163d6b640eSAnirudh Venkataramanan * returns true if there are pending messages in a queue, false if there aren't 8173d6b640eSAnirudh Venkataramanan */ 8183d6b640eSAnirudh Venkataramanan static bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq) 8193d6b640eSAnirudh Venkataramanan { 8203d6b640eSAnirudh Venkataramanan u16 ntu; 8213d6b640eSAnirudh Venkataramanan 8223d6b640eSAnirudh Venkataramanan ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask); 8233d6b640eSAnirudh Venkataramanan return cq->rq.next_to_clean != ntu; 8243d6b640eSAnirudh Venkataramanan } 8253d6b640eSAnirudh Venkataramanan 8263d6b640eSAnirudh Venkataramanan /** 827940b61afSAnirudh Venkataramanan * ice_clean_adminq_subtask - clean the AdminQ rings 828940b61afSAnirudh Venkataramanan * @pf: board private structure 829940b61afSAnirudh Venkataramanan */ 830940b61afSAnirudh Venkataramanan static void ice_clean_adminq_subtask(struct ice_pf *pf) 831940b61afSAnirudh Venkataramanan { 832940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 833940b61afSAnirudh Venkataramanan 834940b61afSAnirudh Venkataramanan if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) 835940b61afSAnirudh Venkataramanan return; 836940b61afSAnirudh Venkataramanan 837940b61afSAnirudh Venkataramanan if (__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN)) 838940b61afSAnirudh Venkataramanan return; 839940b61afSAnirudh Venkataramanan 840940b61afSAnirudh Venkataramanan clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); 841940b61afSAnirudh Venkataramanan 8423d6b640eSAnirudh Venkataramanan /* There might be a situation where new messages arrive to a control 8433d6b640eSAnirudh Venkataramanan * queue between processing the last message and clearing the 8443d6b640eSAnirudh Venkataramanan * EVENT_PENDING bit. So before exiting, check queue head again (using 8453d6b640eSAnirudh Venkataramanan * ice_ctrlq_pending) and process new messages if any. 8463d6b640eSAnirudh Venkataramanan */ 8473d6b640eSAnirudh Venkataramanan if (ice_ctrlq_pending(hw, &hw->adminq)) 8483d6b640eSAnirudh Venkataramanan __ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN); 849940b61afSAnirudh Venkataramanan 850940b61afSAnirudh Venkataramanan ice_flush(hw); 851940b61afSAnirudh Venkataramanan } 852940b61afSAnirudh Venkataramanan 853940b61afSAnirudh Venkataramanan /** 854940b61afSAnirudh Venkataramanan * ice_service_task_schedule - schedule the service task to wake up 855940b61afSAnirudh Venkataramanan * @pf: board private structure 856940b61afSAnirudh Venkataramanan * 857940b61afSAnirudh Venkataramanan * If not already scheduled, this puts the task into the work queue. 858940b61afSAnirudh Venkataramanan */ 859940b61afSAnirudh Venkataramanan static void ice_service_task_schedule(struct ice_pf *pf) 860940b61afSAnirudh Venkataramanan { 8618d81fa55SAkeem G Abodunrin if (!test_bit(__ICE_SERVICE_DIS, pf->state) && 8620f9d5027SAnirudh Venkataramanan !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) && 8630f9d5027SAnirudh Venkataramanan !test_bit(__ICE_NEEDS_RESTART, pf->state)) 864940b61afSAnirudh Venkataramanan queue_work(ice_wq, &pf->serv_task); 865940b61afSAnirudh Venkataramanan } 866940b61afSAnirudh Venkataramanan 867940b61afSAnirudh Venkataramanan /** 868940b61afSAnirudh Venkataramanan * ice_service_task_complete - finish up the service task 869940b61afSAnirudh Venkataramanan * @pf: board private structure 870940b61afSAnirudh Venkataramanan */ 871940b61afSAnirudh Venkataramanan static void ice_service_task_complete(struct ice_pf *pf) 872940b61afSAnirudh Venkataramanan { 873940b61afSAnirudh Venkataramanan WARN_ON(!test_bit(__ICE_SERVICE_SCHED, pf->state)); 874940b61afSAnirudh Venkataramanan 875940b61afSAnirudh Venkataramanan /* force memory (pf->state) to sync before next service task */ 876940b61afSAnirudh Venkataramanan smp_mb__before_atomic(); 877940b61afSAnirudh Venkataramanan clear_bit(__ICE_SERVICE_SCHED, pf->state); 878940b61afSAnirudh Venkataramanan } 879940b61afSAnirudh Venkataramanan 880940b61afSAnirudh Venkataramanan /** 8818d81fa55SAkeem G Abodunrin * ice_service_task_stop - stop service task and cancel works 8828d81fa55SAkeem G Abodunrin * @pf: board private structure 8838d81fa55SAkeem G Abodunrin */ 8848d81fa55SAkeem G Abodunrin static void ice_service_task_stop(struct ice_pf *pf) 8858d81fa55SAkeem G Abodunrin { 8868d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 8878d81fa55SAkeem G Abodunrin 8888d81fa55SAkeem G Abodunrin if (pf->serv_tmr.function) 8898d81fa55SAkeem G Abodunrin del_timer_sync(&pf->serv_tmr); 8908d81fa55SAkeem G Abodunrin if (pf->serv_task.func) 8918d81fa55SAkeem G Abodunrin cancel_work_sync(&pf->serv_task); 8928d81fa55SAkeem G Abodunrin 8938d81fa55SAkeem G Abodunrin clear_bit(__ICE_SERVICE_SCHED, pf->state); 8948d81fa55SAkeem G Abodunrin } 8958d81fa55SAkeem G Abodunrin 8968d81fa55SAkeem G Abodunrin /** 897940b61afSAnirudh Venkataramanan * ice_service_timer - timer callback to schedule service task 898940b61afSAnirudh Venkataramanan * @t: pointer to timer_list 899940b61afSAnirudh Venkataramanan */ 900940b61afSAnirudh Venkataramanan static void ice_service_timer(struct timer_list *t) 901940b61afSAnirudh Venkataramanan { 902940b61afSAnirudh Venkataramanan struct ice_pf *pf = from_timer(pf, t, serv_tmr); 903940b61afSAnirudh Venkataramanan 904940b61afSAnirudh Venkataramanan mod_timer(&pf->serv_tmr, round_jiffies(pf->serv_tmr_period + jiffies)); 905940b61afSAnirudh Venkataramanan ice_service_task_schedule(pf); 906940b61afSAnirudh Venkataramanan } 907940b61afSAnirudh Venkataramanan 908940b61afSAnirudh Venkataramanan /** 909b3969fd7SSudheer Mogilappagari * ice_handle_mdd_event - handle malicious driver detect event 910b3969fd7SSudheer Mogilappagari * @pf: pointer to the PF structure 911b3969fd7SSudheer Mogilappagari * 912b3969fd7SSudheer Mogilappagari * Called from service task. OICR interrupt handler indicates MDD event 913b3969fd7SSudheer Mogilappagari */ 914b3969fd7SSudheer Mogilappagari static void ice_handle_mdd_event(struct ice_pf *pf) 915b3969fd7SSudheer Mogilappagari { 916b3969fd7SSudheer Mogilappagari struct ice_hw *hw = &pf->hw; 917b3969fd7SSudheer Mogilappagari bool mdd_detected = false; 918b3969fd7SSudheer Mogilappagari u32 reg; 919b3969fd7SSudheer Mogilappagari 920b3969fd7SSudheer Mogilappagari if (!test_bit(__ICE_MDD_EVENT_PENDING, pf->state)) 921b3969fd7SSudheer Mogilappagari return; 922b3969fd7SSudheer Mogilappagari 923b3969fd7SSudheer Mogilappagari /* find what triggered the MDD event */ 924b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_TX_PQM); 925b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_TX_PQM_VALID_M) { 926b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >> 927b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_PF_NUM_S; 928b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >> 929b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_VF_NUM_S; 930b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >> 931b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_MAL_TYPE_S; 932b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >> 933b3969fd7SSudheer Mogilappagari GL_MDET_TX_PQM_QNUM_S); 934b3969fd7SSudheer Mogilappagari 935b3969fd7SSudheer Mogilappagari if (netif_msg_tx_err(pf)) 936b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", 937b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 938b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_TX_PQM, 0xffffffff); 939b3969fd7SSudheer Mogilappagari mdd_detected = true; 940b3969fd7SSudheer Mogilappagari } 941b3969fd7SSudheer Mogilappagari 942b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_TX_TCLAN); 943b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_TX_TCLAN_VALID_M) { 944b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >> 945b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_PF_NUM_S; 946b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >> 947b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_VF_NUM_S; 948b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >> 949b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_MAL_TYPE_S; 950b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >> 951b3969fd7SSudheer Mogilappagari GL_MDET_TX_TCLAN_QNUM_S); 952b3969fd7SSudheer Mogilappagari 953b3969fd7SSudheer Mogilappagari if (netif_msg_rx_err(pf)) 954b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", 955b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 956b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff); 957b3969fd7SSudheer Mogilappagari mdd_detected = true; 958b3969fd7SSudheer Mogilappagari } 959b3969fd7SSudheer Mogilappagari 960b3969fd7SSudheer Mogilappagari reg = rd32(hw, GL_MDET_RX); 961b3969fd7SSudheer Mogilappagari if (reg & GL_MDET_RX_VALID_M) { 962b3969fd7SSudheer Mogilappagari u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >> 963b3969fd7SSudheer Mogilappagari GL_MDET_RX_PF_NUM_S; 964b3969fd7SSudheer Mogilappagari u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >> 965b3969fd7SSudheer Mogilappagari GL_MDET_RX_VF_NUM_S; 966b3969fd7SSudheer Mogilappagari u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >> 967b3969fd7SSudheer Mogilappagari GL_MDET_RX_MAL_TYPE_S; 968b3969fd7SSudheer Mogilappagari u16 queue = ((reg & GL_MDET_RX_QNUM_M) >> 969b3969fd7SSudheer Mogilappagari GL_MDET_RX_QNUM_S); 970b3969fd7SSudheer Mogilappagari 971b3969fd7SSudheer Mogilappagari if (netif_msg_rx_err(pf)) 972b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n", 973b3969fd7SSudheer Mogilappagari event, queue, pf_num, vf_num); 974b3969fd7SSudheer Mogilappagari wr32(hw, GL_MDET_RX, 0xffffffff); 975b3969fd7SSudheer Mogilappagari mdd_detected = true; 976b3969fd7SSudheer Mogilappagari } 977b3969fd7SSudheer Mogilappagari 978b3969fd7SSudheer Mogilappagari if (mdd_detected) { 979b3969fd7SSudheer Mogilappagari bool pf_mdd_detected = false; 980b3969fd7SSudheer Mogilappagari 981b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_TX_PQM); 982b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_TX_PQM_VALID_M) { 983b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_TX_PQM, 0xFFFF); 984b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n"); 985b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 986b3969fd7SSudheer Mogilappagari } 987b3969fd7SSudheer Mogilappagari 988b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_TX_TCLAN); 989b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_TX_TCLAN_VALID_M) { 990b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF); 991b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n"); 992b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 993b3969fd7SSudheer Mogilappagari } 994b3969fd7SSudheer Mogilappagari 995b3969fd7SSudheer Mogilappagari reg = rd32(hw, PF_MDET_RX); 996b3969fd7SSudheer Mogilappagari if (reg & PF_MDET_RX_VALID_M) { 997b3969fd7SSudheer Mogilappagari wr32(hw, PF_MDET_RX, 0xFFFF); 998b3969fd7SSudheer Mogilappagari dev_info(&pf->pdev->dev, "RX driver issue detected, PF reset issued\n"); 999b3969fd7SSudheer Mogilappagari pf_mdd_detected = true; 1000b3969fd7SSudheer Mogilappagari } 1001b3969fd7SSudheer Mogilappagari /* Queue belongs to the PF initiate a reset */ 1002b3969fd7SSudheer Mogilappagari if (pf_mdd_detected) { 1003b3969fd7SSudheer Mogilappagari set_bit(__ICE_NEEDS_RESTART, pf->state); 1004b3969fd7SSudheer Mogilappagari ice_service_task_schedule(pf); 1005b3969fd7SSudheer Mogilappagari } 1006b3969fd7SSudheer Mogilappagari } 1007b3969fd7SSudheer Mogilappagari 1008b3969fd7SSudheer Mogilappagari /* re-enable MDD interrupt cause */ 1009b3969fd7SSudheer Mogilappagari clear_bit(__ICE_MDD_EVENT_PENDING, pf->state); 1010b3969fd7SSudheer Mogilappagari reg = rd32(hw, PFINT_OICR_ENA); 1011b3969fd7SSudheer Mogilappagari reg |= PFINT_OICR_MAL_DETECT_M; 1012b3969fd7SSudheer Mogilappagari wr32(hw, PFINT_OICR_ENA, reg); 1013b3969fd7SSudheer Mogilappagari ice_flush(hw); 1014b3969fd7SSudheer Mogilappagari } 1015b3969fd7SSudheer Mogilappagari 1016b3969fd7SSudheer Mogilappagari /** 1017940b61afSAnirudh Venkataramanan * ice_service_task - manage and run subtasks 1018940b61afSAnirudh Venkataramanan * @work: pointer to work_struct contained by the PF struct 1019940b61afSAnirudh Venkataramanan */ 1020940b61afSAnirudh Venkataramanan static void ice_service_task(struct work_struct *work) 1021940b61afSAnirudh Venkataramanan { 1022940b61afSAnirudh Venkataramanan struct ice_pf *pf = container_of(work, struct ice_pf, serv_task); 1023940b61afSAnirudh Venkataramanan unsigned long start_time = jiffies; 1024940b61afSAnirudh Venkataramanan 1025940b61afSAnirudh Venkataramanan /* subtasks */ 10260b28b702SAnirudh Venkataramanan 10270b28b702SAnirudh Venkataramanan /* process reset requests first */ 10280b28b702SAnirudh Venkataramanan ice_reset_subtask(pf); 10290b28b702SAnirudh Venkataramanan 10300f9d5027SAnirudh Venkataramanan /* bail if a reset/recovery cycle is pending or rebuild failed */ 10315df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state) || 10320f9d5027SAnirudh Venkataramanan test_bit(__ICE_SUSPENDED, pf->state) || 10330f9d5027SAnirudh Venkataramanan test_bit(__ICE_NEEDS_RESTART, pf->state)) { 10340b28b702SAnirudh Venkataramanan ice_service_task_complete(pf); 10350b28b702SAnirudh Venkataramanan return; 10360b28b702SAnirudh Venkataramanan } 10370b28b702SAnirudh Venkataramanan 1038b3969fd7SSudheer Mogilappagari ice_check_for_hang_subtask(pf); 1039e94d4478SAnirudh Venkataramanan ice_sync_fltr_subtask(pf); 1040b3969fd7SSudheer Mogilappagari ice_handle_mdd_event(pf); 1041fcea6f3dSAnirudh Venkataramanan ice_watchdog_subtask(pf); 1042940b61afSAnirudh Venkataramanan ice_clean_adminq_subtask(pf); 1043940b61afSAnirudh Venkataramanan 1044940b61afSAnirudh Venkataramanan /* Clear __ICE_SERVICE_SCHED flag to allow scheduling next event */ 1045940b61afSAnirudh Venkataramanan ice_service_task_complete(pf); 1046940b61afSAnirudh Venkataramanan 1047940b61afSAnirudh Venkataramanan /* If the tasks have taken longer than one service timer period 1048940b61afSAnirudh Venkataramanan * or there is more work to be done, reset the service timer to 1049940b61afSAnirudh Venkataramanan * schedule the service task now. 1050940b61afSAnirudh Venkataramanan */ 1051940b61afSAnirudh Venkataramanan if (time_after(jiffies, (start_time + pf->serv_tmr_period)) || 1052b3969fd7SSudheer Mogilappagari test_bit(__ICE_MDD_EVENT_PENDING, pf->state) || 1053940b61afSAnirudh Venkataramanan test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) 1054940b61afSAnirudh Venkataramanan mod_timer(&pf->serv_tmr, jiffies); 1055940b61afSAnirudh Venkataramanan } 1056940b61afSAnirudh Venkataramanan 1057837f08fdSAnirudh Venkataramanan /** 1058f31e4b6fSAnirudh Venkataramanan * ice_set_ctrlq_len - helper function to set controlq length 1059f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw instance 1060f31e4b6fSAnirudh Venkataramanan */ 1061f31e4b6fSAnirudh Venkataramanan static void ice_set_ctrlq_len(struct ice_hw *hw) 1062f31e4b6fSAnirudh Venkataramanan { 1063f31e4b6fSAnirudh Venkataramanan hw->adminq.num_rq_entries = ICE_AQ_LEN; 1064f31e4b6fSAnirudh Venkataramanan hw->adminq.num_sq_entries = ICE_AQ_LEN; 1065f31e4b6fSAnirudh Venkataramanan hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN; 1066f31e4b6fSAnirudh Venkataramanan hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN; 1067f31e4b6fSAnirudh Venkataramanan } 1068f31e4b6fSAnirudh Venkataramanan 1069f31e4b6fSAnirudh Venkataramanan /** 1070cdedef59SAnirudh Venkataramanan * ice_irq_affinity_notify - Callback for affinity changes 1071cdedef59SAnirudh Venkataramanan * @notify: context as to what irq was changed 1072cdedef59SAnirudh Venkataramanan * @mask: the new affinity mask 1073cdedef59SAnirudh Venkataramanan * 1074cdedef59SAnirudh Venkataramanan * This is a callback function used by the irq_set_affinity_notifier function 1075cdedef59SAnirudh Venkataramanan * so that we may register to receive changes to the irq affinity masks. 1076cdedef59SAnirudh Venkataramanan */ 1077cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_notify(struct irq_affinity_notify *notify, 1078cdedef59SAnirudh Venkataramanan const cpumask_t *mask) 1079cdedef59SAnirudh Venkataramanan { 1080cdedef59SAnirudh Venkataramanan struct ice_q_vector *q_vector = 1081cdedef59SAnirudh Venkataramanan container_of(notify, struct ice_q_vector, affinity_notify); 1082cdedef59SAnirudh Venkataramanan 1083cdedef59SAnirudh Venkataramanan cpumask_copy(&q_vector->affinity_mask, mask); 1084cdedef59SAnirudh Venkataramanan } 1085cdedef59SAnirudh Venkataramanan 1086cdedef59SAnirudh Venkataramanan /** 1087cdedef59SAnirudh Venkataramanan * ice_irq_affinity_release - Callback for affinity notifier release 1088cdedef59SAnirudh Venkataramanan * @ref: internal core kernel usage 1089cdedef59SAnirudh Venkataramanan * 1090cdedef59SAnirudh Venkataramanan * This is a callback function used by the irq_set_affinity_notifier function 1091cdedef59SAnirudh Venkataramanan * to inform the current notification subscriber that they will no longer 1092cdedef59SAnirudh Venkataramanan * receive notifications. 1093cdedef59SAnirudh Venkataramanan */ 1094cdedef59SAnirudh Venkataramanan static void ice_irq_affinity_release(struct kref __always_unused *ref) {} 1095cdedef59SAnirudh Venkataramanan 1096cdedef59SAnirudh Venkataramanan /** 1097cdedef59SAnirudh Venkataramanan * ice_vsi_ena_irq - Enable IRQ for the given VSI 1098cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 1099cdedef59SAnirudh Venkataramanan */ 1100cdedef59SAnirudh Venkataramanan static int ice_vsi_ena_irq(struct ice_vsi *vsi) 1101cdedef59SAnirudh Venkataramanan { 1102cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1103cdedef59SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1104cdedef59SAnirudh Venkataramanan 1105cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 1106cdedef59SAnirudh Venkataramanan int i; 1107cdedef59SAnirudh Venkataramanan 1108cdedef59SAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++) 1109cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]); 1110cdedef59SAnirudh Venkataramanan } 1111cdedef59SAnirudh Venkataramanan 1112cdedef59SAnirudh Venkataramanan ice_flush(hw); 1113cdedef59SAnirudh Venkataramanan return 0; 1114cdedef59SAnirudh Venkataramanan } 1115cdedef59SAnirudh Venkataramanan 1116cdedef59SAnirudh Venkataramanan /** 1117cdedef59SAnirudh Venkataramanan * ice_vsi_req_irq_msix - get MSI-X vectors from the OS for the VSI 1118cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 1119cdedef59SAnirudh Venkataramanan * @basename: name for the vector 1120cdedef59SAnirudh Venkataramanan */ 1121cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) 1122cdedef59SAnirudh Venkataramanan { 1123cdedef59SAnirudh Venkataramanan int q_vectors = vsi->num_q_vectors; 1124cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1125cdedef59SAnirudh Venkataramanan int base = vsi->base_vector; 1126cdedef59SAnirudh Venkataramanan int rx_int_idx = 0; 1127cdedef59SAnirudh Venkataramanan int tx_int_idx = 0; 1128cdedef59SAnirudh Venkataramanan int vector, err; 1129cdedef59SAnirudh Venkataramanan int irq_num; 1130cdedef59SAnirudh Venkataramanan 1131cdedef59SAnirudh Venkataramanan for (vector = 0; vector < q_vectors; vector++) { 1132cdedef59SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[vector]; 1133cdedef59SAnirudh Venkataramanan 1134cdedef59SAnirudh Venkataramanan irq_num = pf->msix_entries[base + vector].vector; 1135cdedef59SAnirudh Venkataramanan 1136cdedef59SAnirudh Venkataramanan if (q_vector->tx.ring && q_vector->rx.ring) { 1137cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1138cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "TxRx", rx_int_idx++); 1139cdedef59SAnirudh Venkataramanan tx_int_idx++; 1140cdedef59SAnirudh Venkataramanan } else if (q_vector->rx.ring) { 1141cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1142cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "rx", rx_int_idx++); 1143cdedef59SAnirudh Venkataramanan } else if (q_vector->tx.ring) { 1144cdedef59SAnirudh Venkataramanan snprintf(q_vector->name, sizeof(q_vector->name) - 1, 1145cdedef59SAnirudh Venkataramanan "%s-%s-%d", basename, "tx", tx_int_idx++); 1146cdedef59SAnirudh Venkataramanan } else { 1147cdedef59SAnirudh Venkataramanan /* skip this unused q_vector */ 1148cdedef59SAnirudh Venkataramanan continue; 1149cdedef59SAnirudh Venkataramanan } 1150cdedef59SAnirudh Venkataramanan err = devm_request_irq(&pf->pdev->dev, 1151cdedef59SAnirudh Venkataramanan pf->msix_entries[base + vector].vector, 1152cdedef59SAnirudh Venkataramanan vsi->irq_handler, 0, q_vector->name, 1153cdedef59SAnirudh Venkataramanan q_vector); 1154cdedef59SAnirudh Venkataramanan if (err) { 1155cdedef59SAnirudh Venkataramanan netdev_err(vsi->netdev, 1156cdedef59SAnirudh Venkataramanan "MSIX request_irq failed, error: %d\n", err); 1157cdedef59SAnirudh Venkataramanan goto free_q_irqs; 1158cdedef59SAnirudh Venkataramanan } 1159cdedef59SAnirudh Venkataramanan 1160cdedef59SAnirudh Venkataramanan /* register for affinity change notifications */ 1161cdedef59SAnirudh Venkataramanan q_vector->affinity_notify.notify = ice_irq_affinity_notify; 1162cdedef59SAnirudh Venkataramanan q_vector->affinity_notify.release = ice_irq_affinity_release; 1163cdedef59SAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify); 1164cdedef59SAnirudh Venkataramanan 1165cdedef59SAnirudh Venkataramanan /* assign the mask for this irq */ 1166cdedef59SAnirudh Venkataramanan irq_set_affinity_hint(irq_num, &q_vector->affinity_mask); 1167cdedef59SAnirudh Venkataramanan } 1168cdedef59SAnirudh Venkataramanan 1169cdedef59SAnirudh Venkataramanan vsi->irqs_ready = true; 1170cdedef59SAnirudh Venkataramanan return 0; 1171cdedef59SAnirudh Venkataramanan 1172cdedef59SAnirudh Venkataramanan free_q_irqs: 1173cdedef59SAnirudh Venkataramanan while (vector) { 1174cdedef59SAnirudh Venkataramanan vector--; 1175cdedef59SAnirudh Venkataramanan irq_num = pf->msix_entries[base + vector].vector, 1176cdedef59SAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 1177cdedef59SAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 1178cdedef59SAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, &vsi->q_vectors[vector]); 1179cdedef59SAnirudh Venkataramanan } 1180cdedef59SAnirudh Venkataramanan return err; 1181cdedef59SAnirudh Venkataramanan } 1182cdedef59SAnirudh Venkataramanan 1183cdedef59SAnirudh Venkataramanan /** 1184940b61afSAnirudh Venkataramanan * ice_ena_misc_vector - enable the non-queue interrupts 1185940b61afSAnirudh Venkataramanan * @pf: board private structure 1186940b61afSAnirudh Venkataramanan */ 1187940b61afSAnirudh Venkataramanan static void ice_ena_misc_vector(struct ice_pf *pf) 1188940b61afSAnirudh Venkataramanan { 1189940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1190940b61afSAnirudh Venkataramanan u32 val; 1191940b61afSAnirudh Venkataramanan 1192940b61afSAnirudh Venkataramanan /* clear things first */ 1193940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, 0); /* disable all */ 1194940b61afSAnirudh Venkataramanan rd32(hw, PFINT_OICR); /* read to clear */ 1195940b61afSAnirudh Venkataramanan 11963bcd7fa3SBruce Allan val = (PFINT_OICR_ECC_ERR_M | 1197940b61afSAnirudh Venkataramanan PFINT_OICR_MAL_DETECT_M | 1198940b61afSAnirudh Venkataramanan PFINT_OICR_GRST_M | 1199940b61afSAnirudh Venkataramanan PFINT_OICR_PCI_EXCEPTION_M | 12003bcd7fa3SBruce Allan PFINT_OICR_HMC_ERR_M | 12013bcd7fa3SBruce Allan PFINT_OICR_PE_CRITERR_M); 1202940b61afSAnirudh Venkataramanan 1203940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, val); 1204940b61afSAnirudh Venkataramanan 1205940b61afSAnirudh Venkataramanan /* SW_ITR_IDX = 0, but don't change INTENA */ 1206940b61afSAnirudh Venkataramanan wr32(hw, GLINT_DYN_CTL(pf->oicr_idx), 1207940b61afSAnirudh Venkataramanan GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); 1208940b61afSAnirudh Venkataramanan } 1209940b61afSAnirudh Venkataramanan 1210940b61afSAnirudh Venkataramanan /** 1211940b61afSAnirudh Venkataramanan * ice_misc_intr - misc interrupt handler 1212940b61afSAnirudh Venkataramanan * @irq: interrupt number 1213940b61afSAnirudh Venkataramanan * @data: pointer to a q_vector 1214940b61afSAnirudh Venkataramanan */ 1215940b61afSAnirudh Venkataramanan static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) 1216940b61afSAnirudh Venkataramanan { 1217940b61afSAnirudh Venkataramanan struct ice_pf *pf = (struct ice_pf *)data; 1218940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1219940b61afSAnirudh Venkataramanan irqreturn_t ret = IRQ_NONE; 1220940b61afSAnirudh Venkataramanan u32 oicr, ena_mask; 1221940b61afSAnirudh Venkataramanan 1222940b61afSAnirudh Venkataramanan set_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); 1223940b61afSAnirudh Venkataramanan 1224940b61afSAnirudh Venkataramanan oicr = rd32(hw, PFINT_OICR); 1225940b61afSAnirudh Venkataramanan ena_mask = rd32(hw, PFINT_OICR_ENA); 1226940b61afSAnirudh Venkataramanan 1227b3969fd7SSudheer Mogilappagari if (oicr & PFINT_OICR_MAL_DETECT_M) { 1228b3969fd7SSudheer Mogilappagari ena_mask &= ~PFINT_OICR_MAL_DETECT_M; 1229b3969fd7SSudheer Mogilappagari set_bit(__ICE_MDD_EVENT_PENDING, pf->state); 1230b3969fd7SSudheer Mogilappagari } 1231b3969fd7SSudheer Mogilappagari 12320b28b702SAnirudh Venkataramanan if (oicr & PFINT_OICR_GRST_M) { 12330b28b702SAnirudh Venkataramanan u32 reset; 1234b3969fd7SSudheer Mogilappagari 12350b28b702SAnirudh Venkataramanan /* we have a reset warning */ 12360b28b702SAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_GRST_M; 12370b28b702SAnirudh Venkataramanan reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >> 12380b28b702SAnirudh Venkataramanan GLGEN_RSTAT_RESET_TYPE_S; 12390b28b702SAnirudh Venkataramanan 12400b28b702SAnirudh Venkataramanan if (reset == ICE_RESET_CORER) 12410b28b702SAnirudh Venkataramanan pf->corer_count++; 12420b28b702SAnirudh Venkataramanan else if (reset == ICE_RESET_GLOBR) 12430b28b702SAnirudh Venkataramanan pf->globr_count++; 12440b28b702SAnirudh Venkataramanan else 12450b28b702SAnirudh Venkataramanan pf->empr_count++; 12460b28b702SAnirudh Venkataramanan 12470b28b702SAnirudh Venkataramanan /* If a reset cycle isn't already in progress, we set a bit in 12480b28b702SAnirudh Venkataramanan * pf->state so that the service task can start a reset/rebuild. 12490b28b702SAnirudh Venkataramanan * We also make note of which reset happened so that peer 12500b28b702SAnirudh Venkataramanan * devices/drivers can be informed. 12510b28b702SAnirudh Venkataramanan */ 12525df7e45dSDave Ertman if (!test_and_set_bit(__ICE_RESET_OICR_RECV, pf->state)) { 12530b28b702SAnirudh Venkataramanan if (reset == ICE_RESET_CORER) 12540b28b702SAnirudh Venkataramanan set_bit(__ICE_CORER_RECV, pf->state); 12550b28b702SAnirudh Venkataramanan else if (reset == ICE_RESET_GLOBR) 12560b28b702SAnirudh Venkataramanan set_bit(__ICE_GLOBR_RECV, pf->state); 12570b28b702SAnirudh Venkataramanan else 12580b28b702SAnirudh Venkataramanan set_bit(__ICE_EMPR_RECV, pf->state); 12590b28b702SAnirudh Venkataramanan 1260fd2a9817SAnirudh Venkataramanan /* There are couple of different bits at play here. 1261fd2a9817SAnirudh Venkataramanan * hw->reset_ongoing indicates whether the hardware is 1262fd2a9817SAnirudh Venkataramanan * in reset. This is set to true when a reset interrupt 1263fd2a9817SAnirudh Venkataramanan * is received and set back to false after the driver 1264fd2a9817SAnirudh Venkataramanan * has determined that the hardware is out of reset. 1265fd2a9817SAnirudh Venkataramanan * 12665df7e45dSDave Ertman * __ICE_RESET_OICR_RECV in pf->state indicates 1267fd2a9817SAnirudh Venkataramanan * that a post reset rebuild is required before the 1268fd2a9817SAnirudh Venkataramanan * driver is operational again. This is set above. 1269fd2a9817SAnirudh Venkataramanan * 1270fd2a9817SAnirudh Venkataramanan * As this is the start of the reset/rebuild cycle, set 1271fd2a9817SAnirudh Venkataramanan * both to indicate that. 1272fd2a9817SAnirudh Venkataramanan */ 1273fd2a9817SAnirudh Venkataramanan hw->reset_ongoing = true; 12740b28b702SAnirudh Venkataramanan } 12750b28b702SAnirudh Venkataramanan } 12760b28b702SAnirudh Venkataramanan 1277940b61afSAnirudh Venkataramanan if (oicr & PFINT_OICR_HMC_ERR_M) { 1278940b61afSAnirudh Venkataramanan ena_mask &= ~PFINT_OICR_HMC_ERR_M; 1279940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 1280940b61afSAnirudh Venkataramanan "HMC Error interrupt - info 0x%x, data 0x%x\n", 1281940b61afSAnirudh Venkataramanan rd32(hw, PFHMC_ERRORINFO), 1282940b61afSAnirudh Venkataramanan rd32(hw, PFHMC_ERRORDATA)); 1283940b61afSAnirudh Venkataramanan } 1284940b61afSAnirudh Venkataramanan 1285940b61afSAnirudh Venkataramanan /* Report and mask off any remaining unexpected interrupts */ 1286940b61afSAnirudh Venkataramanan oicr &= ena_mask; 1287940b61afSAnirudh Venkataramanan if (oicr) { 1288940b61afSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "unhandled interrupt oicr=0x%08x\n", 1289940b61afSAnirudh Venkataramanan oicr); 1290940b61afSAnirudh Venkataramanan /* If a critical error is pending there is no choice but to 1291940b61afSAnirudh Venkataramanan * reset the device. 1292940b61afSAnirudh Venkataramanan */ 1293940b61afSAnirudh Venkataramanan if (oicr & (PFINT_OICR_PE_CRITERR_M | 1294940b61afSAnirudh Venkataramanan PFINT_OICR_PCI_EXCEPTION_M | 12950b28b702SAnirudh Venkataramanan PFINT_OICR_ECC_ERR_M)) { 1296940b61afSAnirudh Venkataramanan set_bit(__ICE_PFR_REQ, pf->state); 12970b28b702SAnirudh Venkataramanan ice_service_task_schedule(pf); 12980b28b702SAnirudh Venkataramanan } 1299940b61afSAnirudh Venkataramanan ena_mask &= ~oicr; 1300940b61afSAnirudh Venkataramanan } 1301940b61afSAnirudh Venkataramanan ret = IRQ_HANDLED; 1302940b61afSAnirudh Venkataramanan 1303940b61afSAnirudh Venkataramanan /* re-enable interrupt causes that are not handled during this pass */ 1304940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_ENA, ena_mask); 1305940b61afSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) { 1306940b61afSAnirudh Venkataramanan ice_service_task_schedule(pf); 1307cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, NULL, NULL); 1308940b61afSAnirudh Venkataramanan } 1309940b61afSAnirudh Venkataramanan 1310940b61afSAnirudh Venkataramanan return ret; 1311940b61afSAnirudh Venkataramanan } 1312940b61afSAnirudh Venkataramanan 1313940b61afSAnirudh Venkataramanan /** 1314940b61afSAnirudh Venkataramanan * ice_free_irq_msix_misc - Unroll misc vector setup 1315940b61afSAnirudh Venkataramanan * @pf: board private structure 1316940b61afSAnirudh Venkataramanan */ 1317940b61afSAnirudh Venkataramanan static void ice_free_irq_msix_misc(struct ice_pf *pf) 1318940b61afSAnirudh Venkataramanan { 1319940b61afSAnirudh Venkataramanan /* disable OICR interrupt */ 1320940b61afSAnirudh Venkataramanan wr32(&pf->hw, PFINT_OICR_ENA, 0); 1321940b61afSAnirudh Venkataramanan ice_flush(&pf->hw); 1322940b61afSAnirudh Venkataramanan 1323940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { 1324940b61afSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); 1325940b61afSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, 1326940b61afSAnirudh Venkataramanan pf->msix_entries[pf->oicr_idx].vector, pf); 1327940b61afSAnirudh Venkataramanan } 1328940b61afSAnirudh Venkataramanan 1329940b61afSAnirudh Venkataramanan ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID); 1330940b61afSAnirudh Venkataramanan } 1331940b61afSAnirudh Venkataramanan 1332940b61afSAnirudh Venkataramanan /** 1333940b61afSAnirudh Venkataramanan * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events 1334940b61afSAnirudh Venkataramanan * @pf: board private structure 1335940b61afSAnirudh Venkataramanan * 1336940b61afSAnirudh Venkataramanan * This sets up the handler for MSIX 0, which is used to manage the 1337940b61afSAnirudh Venkataramanan * non-queue interrupts, e.g. AdminQ and errors. This is not used 1338940b61afSAnirudh Venkataramanan * when in MSI or Legacy interrupt mode. 1339940b61afSAnirudh Venkataramanan */ 1340940b61afSAnirudh Venkataramanan static int ice_req_irq_msix_misc(struct ice_pf *pf) 1341940b61afSAnirudh Venkataramanan { 1342940b61afSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1343940b61afSAnirudh Venkataramanan int oicr_idx, err = 0; 1344940b61afSAnirudh Venkataramanan u8 itr_gran; 1345940b61afSAnirudh Venkataramanan u32 val; 1346940b61afSAnirudh Venkataramanan 1347940b61afSAnirudh Venkataramanan if (!pf->int_name[0]) 1348940b61afSAnirudh Venkataramanan snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", 1349940b61afSAnirudh Venkataramanan dev_driver_string(&pf->pdev->dev), 1350940b61afSAnirudh Venkataramanan dev_name(&pf->pdev->dev)); 1351940b61afSAnirudh Venkataramanan 13520b28b702SAnirudh Venkataramanan /* Do not request IRQ but do enable OICR interrupt since settings are 13530b28b702SAnirudh Venkataramanan * lost during reset. Note that this function is called only during 13540b28b702SAnirudh Venkataramanan * rebuild path and not while reset is in progress. 13550b28b702SAnirudh Venkataramanan */ 13565df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) 13570b28b702SAnirudh Venkataramanan goto skip_req_irq; 13580b28b702SAnirudh Venkataramanan 1359940b61afSAnirudh Venkataramanan /* reserve one vector in irq_tracker for misc interrupts */ 1360940b61afSAnirudh Venkataramanan oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1361940b61afSAnirudh Venkataramanan if (oicr_idx < 0) 1362940b61afSAnirudh Venkataramanan return oicr_idx; 1363940b61afSAnirudh Venkataramanan 1364940b61afSAnirudh Venkataramanan pf->oicr_idx = oicr_idx; 1365940b61afSAnirudh Venkataramanan 1366940b61afSAnirudh Venkataramanan err = devm_request_irq(&pf->pdev->dev, 1367940b61afSAnirudh Venkataramanan pf->msix_entries[pf->oicr_idx].vector, 1368940b61afSAnirudh Venkataramanan ice_misc_intr, 0, pf->int_name, pf); 1369940b61afSAnirudh Venkataramanan if (err) { 1370940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1371940b61afSAnirudh Venkataramanan "devm_request_irq for %s failed: %d\n", 1372940b61afSAnirudh Venkataramanan pf->int_name, err); 1373940b61afSAnirudh Venkataramanan ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); 1374940b61afSAnirudh Venkataramanan return err; 1375940b61afSAnirudh Venkataramanan } 1376940b61afSAnirudh Venkataramanan 13770b28b702SAnirudh Venkataramanan skip_req_irq: 1378940b61afSAnirudh Venkataramanan ice_ena_misc_vector(pf); 1379940b61afSAnirudh Venkataramanan 13804381147dSAnirudh Venkataramanan val = ((pf->oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | 13814381147dSAnirudh Venkataramanan PFINT_OICR_CTL_CAUSE_ENA_M); 1382940b61afSAnirudh Venkataramanan wr32(hw, PFINT_OICR_CTL, val); 1383940b61afSAnirudh Venkataramanan 1384940b61afSAnirudh Venkataramanan /* This enables Admin queue Interrupt causes */ 13854381147dSAnirudh Venkataramanan val = ((pf->oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | 13864381147dSAnirudh Venkataramanan PFINT_FW_CTL_CAUSE_ENA_M); 1387940b61afSAnirudh Venkataramanan wr32(hw, PFINT_FW_CTL, val); 1388940b61afSAnirudh Venkataramanan 1389940b61afSAnirudh Venkataramanan itr_gran = hw->itr_gran_200; 1390940b61afSAnirudh Venkataramanan 1391940b61afSAnirudh Venkataramanan wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx), 1392940b61afSAnirudh Venkataramanan ITR_TO_REG(ICE_ITR_8K, itr_gran)); 1393940b61afSAnirudh Venkataramanan 1394940b61afSAnirudh Venkataramanan ice_flush(hw); 1395cdedef59SAnirudh Venkataramanan ice_irq_dynamic_ena(hw, NULL, NULL); 1396940b61afSAnirudh Venkataramanan 1397940b61afSAnirudh Venkataramanan return 0; 1398940b61afSAnirudh Venkataramanan } 1399940b61afSAnirudh Venkataramanan 1400940b61afSAnirudh Venkataramanan /** 1401df0f8479SAnirudh Venkataramanan * ice_napi_del - Remove NAPI handler for the VSI 1402df0f8479SAnirudh Venkataramanan * @vsi: VSI for which NAPI handler is to be removed 14033a858ba3SAnirudh Venkataramanan */ 1404df0f8479SAnirudh Venkataramanan static void ice_napi_del(struct ice_vsi *vsi) 14053a858ba3SAnirudh Venkataramanan { 14063a858ba3SAnirudh Venkataramanan int v_idx; 14073a858ba3SAnirudh Venkataramanan 1408df0f8479SAnirudh Venkataramanan if (!vsi->netdev) 1409df0f8479SAnirudh Venkataramanan return; 1410df0f8479SAnirudh Venkataramanan 14113a858ba3SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1412df0f8479SAnirudh Venkataramanan netif_napi_del(&vsi->q_vectors[v_idx]->napi); 14133a858ba3SAnirudh Venkataramanan } 14143a858ba3SAnirudh Venkataramanan 14153a858ba3SAnirudh Venkataramanan /** 1416df0f8479SAnirudh Venkataramanan * ice_napi_add - register NAPI handler for the VSI 1417df0f8479SAnirudh Venkataramanan * @vsi: VSI for which NAPI handler is to be registered 1418df0f8479SAnirudh Venkataramanan * 1419df0f8479SAnirudh Venkataramanan * This function is only called in the driver's load path. Registering the NAPI 1420df0f8479SAnirudh Venkataramanan * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume, 1421df0f8479SAnirudh Venkataramanan * reset/rebuild, etc.) 1422df0f8479SAnirudh Venkataramanan */ 1423df0f8479SAnirudh Venkataramanan static void ice_napi_add(struct ice_vsi *vsi) 1424df0f8479SAnirudh Venkataramanan { 1425df0f8479SAnirudh Venkataramanan int v_idx; 1426df0f8479SAnirudh Venkataramanan 1427df0f8479SAnirudh Venkataramanan if (!vsi->netdev) 1428df0f8479SAnirudh Venkataramanan return; 1429df0f8479SAnirudh Venkataramanan 1430df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1431df0f8479SAnirudh Venkataramanan netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi, 1432df0f8479SAnirudh Venkataramanan ice_napi_poll, NAPI_POLL_WEIGHT); 1433df0f8479SAnirudh Venkataramanan } 1434df0f8479SAnirudh Venkataramanan 1435df0f8479SAnirudh Venkataramanan /** 1436df0f8479SAnirudh Venkataramanan * ice_cfg_netdev - Allocate, configure and register a netdev 1437df0f8479SAnirudh Venkataramanan * @vsi: the VSI associated with the new netdev 14383a858ba3SAnirudh Venkataramanan * 14393a858ba3SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 14403a858ba3SAnirudh Venkataramanan */ 14413a858ba3SAnirudh Venkataramanan static int ice_cfg_netdev(struct ice_vsi *vsi) 14423a858ba3SAnirudh Venkataramanan { 1443d76a60baSAnirudh Venkataramanan netdev_features_t csumo_features; 1444d76a60baSAnirudh Venkataramanan netdev_features_t vlano_features; 1445d76a60baSAnirudh Venkataramanan netdev_features_t dflt_features; 1446d76a60baSAnirudh Venkataramanan netdev_features_t tso_features; 14473a858ba3SAnirudh Venkataramanan struct ice_netdev_priv *np; 14483a858ba3SAnirudh Venkataramanan struct net_device *netdev; 14493a858ba3SAnirudh Venkataramanan u8 mac_addr[ETH_ALEN]; 1450df0f8479SAnirudh Venkataramanan int err; 14513a858ba3SAnirudh Venkataramanan 14523a858ba3SAnirudh Venkataramanan netdev = alloc_etherdev_mqs(sizeof(struct ice_netdev_priv), 14533a858ba3SAnirudh Venkataramanan vsi->alloc_txq, vsi->alloc_rxq); 14543a858ba3SAnirudh Venkataramanan if (!netdev) 14553a858ba3SAnirudh Venkataramanan return -ENOMEM; 14563a858ba3SAnirudh Venkataramanan 14573a858ba3SAnirudh Venkataramanan vsi->netdev = netdev; 14583a858ba3SAnirudh Venkataramanan np = netdev_priv(netdev); 14593a858ba3SAnirudh Venkataramanan np->vsi = vsi; 14603a858ba3SAnirudh Venkataramanan 1461d76a60baSAnirudh Venkataramanan dflt_features = NETIF_F_SG | 14623a858ba3SAnirudh Venkataramanan NETIF_F_HIGHDMA | 14633a858ba3SAnirudh Venkataramanan NETIF_F_RXHASH; 14643a858ba3SAnirudh Venkataramanan 1465d76a60baSAnirudh Venkataramanan csumo_features = NETIF_F_RXCSUM | 1466d76a60baSAnirudh Venkataramanan NETIF_F_IP_CSUM | 1467d76a60baSAnirudh Venkataramanan NETIF_F_IPV6_CSUM; 1468d76a60baSAnirudh Venkataramanan 1469d76a60baSAnirudh Venkataramanan vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER | 1470d76a60baSAnirudh Venkataramanan NETIF_F_HW_VLAN_CTAG_TX | 1471d76a60baSAnirudh Venkataramanan NETIF_F_HW_VLAN_CTAG_RX; 1472d76a60baSAnirudh Venkataramanan 1473d76a60baSAnirudh Venkataramanan tso_features = NETIF_F_TSO; 1474d76a60baSAnirudh Venkataramanan 1475d76a60baSAnirudh Venkataramanan /* set features that user can change */ 1476d76a60baSAnirudh Venkataramanan netdev->hw_features = dflt_features | csumo_features | 1477d76a60baSAnirudh Venkataramanan vlano_features | tso_features; 1478d76a60baSAnirudh Venkataramanan 14793a858ba3SAnirudh Venkataramanan /* enable features */ 14803a858ba3SAnirudh Venkataramanan netdev->features |= netdev->hw_features; 1481d76a60baSAnirudh Venkataramanan /* encap and VLAN devices inherit default, csumo and tso features */ 1482d76a60baSAnirudh Venkataramanan netdev->hw_enc_features |= dflt_features | csumo_features | 1483d76a60baSAnirudh Venkataramanan tso_features; 1484d76a60baSAnirudh Venkataramanan netdev->vlan_features |= dflt_features | csumo_features | 1485d76a60baSAnirudh Venkataramanan tso_features; 14863a858ba3SAnirudh Venkataramanan 14873a858ba3SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 14883a858ba3SAnirudh Venkataramanan SET_NETDEV_DEV(netdev, &vsi->back->pdev->dev); 14893a858ba3SAnirudh Venkataramanan ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr); 14903a858ba3SAnirudh Venkataramanan 14913a858ba3SAnirudh Venkataramanan ether_addr_copy(netdev->dev_addr, mac_addr); 14923a858ba3SAnirudh Venkataramanan ether_addr_copy(netdev->perm_addr, mac_addr); 14933a858ba3SAnirudh Venkataramanan } 14943a858ba3SAnirudh Venkataramanan 14953a858ba3SAnirudh Venkataramanan netdev->priv_flags |= IFF_UNICAST_FLT; 14963a858ba3SAnirudh Venkataramanan 1497cdedef59SAnirudh Venkataramanan /* assign netdev_ops */ 1498cdedef59SAnirudh Venkataramanan netdev->netdev_ops = &ice_netdev_ops; 1499cdedef59SAnirudh Venkataramanan 15003a858ba3SAnirudh Venkataramanan /* setup watchdog timeout value to be 5 second */ 15013a858ba3SAnirudh Venkataramanan netdev->watchdog_timeo = 5 * HZ; 15023a858ba3SAnirudh Venkataramanan 1503fcea6f3dSAnirudh Venkataramanan ice_set_ethtool_ops(netdev); 1504fcea6f3dSAnirudh Venkataramanan 15053a858ba3SAnirudh Venkataramanan netdev->min_mtu = ETH_MIN_MTU; 15063a858ba3SAnirudh Venkataramanan netdev->max_mtu = ICE_MAX_MTU; 15073a858ba3SAnirudh Venkataramanan 1508df0f8479SAnirudh Venkataramanan err = register_netdev(vsi->netdev); 15093a858ba3SAnirudh Venkataramanan if (err) 15103a858ba3SAnirudh Venkataramanan return err; 15113a858ba3SAnirudh Venkataramanan 1512df0f8479SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 15133a858ba3SAnirudh Venkataramanan 1514df0f8479SAnirudh Venkataramanan /* make sure transmit queues start off as stopped */ 1515df0f8479SAnirudh Venkataramanan netif_tx_stop_all_queues(vsi->netdev); 15163a858ba3SAnirudh Venkataramanan 15173a858ba3SAnirudh Venkataramanan return 0; 15183a858ba3SAnirudh Venkataramanan } 15193a858ba3SAnirudh Venkataramanan 15203a858ba3SAnirudh Venkataramanan /** 1521d76a60baSAnirudh Venkataramanan * ice_fill_rss_lut - Fill the RSS lookup table with default values 1522d76a60baSAnirudh Venkataramanan * @lut: Lookup table 1523d76a60baSAnirudh Venkataramanan * @rss_table_size: Lookup table size 1524d76a60baSAnirudh Venkataramanan * @rss_size: Range of queue number for hashing 1525d76a60baSAnirudh Venkataramanan */ 1526d76a60baSAnirudh Venkataramanan void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size) 1527d76a60baSAnirudh Venkataramanan { 1528d76a60baSAnirudh Venkataramanan u16 i; 1529d76a60baSAnirudh Venkataramanan 1530d76a60baSAnirudh Venkataramanan for (i = 0; i < rss_table_size; i++) 1531d76a60baSAnirudh Venkataramanan lut[i] = i % rss_size; 1532d76a60baSAnirudh Venkataramanan } 1533d76a60baSAnirudh Venkataramanan 1534d76a60baSAnirudh Venkataramanan /** 15350f9d5027SAnirudh Venkataramanan * ice_pf_vsi_setup - Set up a PF VSI 15360f9d5027SAnirudh Venkataramanan * @pf: board private structure 15370f9d5027SAnirudh Venkataramanan * @pi: pointer to the port_info instance 15380f9d5027SAnirudh Venkataramanan * 15390f9d5027SAnirudh Venkataramanan * Returns pointer to the successfully allocated VSI sw struct on success, 15400f9d5027SAnirudh Venkataramanan * otherwise returns NULL on failure. 15410f9d5027SAnirudh Venkataramanan */ 15420f9d5027SAnirudh Venkataramanan static struct ice_vsi * 15430f9d5027SAnirudh Venkataramanan ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi) 15440f9d5027SAnirudh Venkataramanan { 15450f9d5027SAnirudh Venkataramanan return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID); 15460f9d5027SAnirudh Venkataramanan } 15470f9d5027SAnirudh Venkataramanan 15480f9d5027SAnirudh Venkataramanan /** 1549d76a60baSAnirudh Venkataramanan * ice_vlan_rx_add_vid - Add a vlan id filter to HW offload 1550d76a60baSAnirudh Venkataramanan * @netdev: network interface to be adjusted 1551d76a60baSAnirudh Venkataramanan * @proto: unused protocol 1552d76a60baSAnirudh Venkataramanan * @vid: vlan id to be added 1553d76a60baSAnirudh Venkataramanan * 1554d76a60baSAnirudh Venkataramanan * net_device_ops implementation for adding vlan ids 1555d76a60baSAnirudh Venkataramanan */ 1556d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_add_vid(struct net_device *netdev, 1557d76a60baSAnirudh Venkataramanan __always_unused __be16 proto, u16 vid) 1558d76a60baSAnirudh Venkataramanan { 1559d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1560d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 15614f74dcc1SBrett Creeley int ret; 1562d76a60baSAnirudh Venkataramanan 1563d76a60baSAnirudh Venkataramanan if (vid >= VLAN_N_VID) { 1564d76a60baSAnirudh Venkataramanan netdev_err(netdev, "VLAN id requested %d is out of range %d\n", 1565d76a60baSAnirudh Venkataramanan vid, VLAN_N_VID); 1566d76a60baSAnirudh Venkataramanan return -EINVAL; 1567d76a60baSAnirudh Venkataramanan } 1568d76a60baSAnirudh Venkataramanan 1569d76a60baSAnirudh Venkataramanan if (vsi->info.pvid) 1570d76a60baSAnirudh Venkataramanan return -EINVAL; 1571d76a60baSAnirudh Venkataramanan 15724f74dcc1SBrett Creeley /* Enable VLAN pruning when VLAN 0 is added */ 15734f74dcc1SBrett Creeley if (unlikely(!vid)) { 15744f74dcc1SBrett Creeley ret = ice_cfg_vlan_pruning(vsi, true); 15754f74dcc1SBrett Creeley if (ret) 15764f74dcc1SBrett Creeley return ret; 15774f74dcc1SBrett Creeley } 15784f74dcc1SBrett Creeley 1579d76a60baSAnirudh Venkataramanan /* Add all VLAN ids including 0 to the switch filter. VLAN id 0 is 1580d76a60baSAnirudh Venkataramanan * needed to continue allowing all untagged packets since VLAN prune 1581d76a60baSAnirudh Venkataramanan * list is applied to all packets by the switch 1582d76a60baSAnirudh Venkataramanan */ 1583d76a60baSAnirudh Venkataramanan ret = ice_vsi_add_vlan(vsi, vid); 1584d76a60baSAnirudh Venkataramanan 1585d76a60baSAnirudh Venkataramanan if (!ret) 1586d76a60baSAnirudh Venkataramanan set_bit(vid, vsi->active_vlans); 1587d76a60baSAnirudh Venkataramanan 1588d76a60baSAnirudh Venkataramanan return ret; 1589d76a60baSAnirudh Venkataramanan } 1590d76a60baSAnirudh Venkataramanan 1591d76a60baSAnirudh Venkataramanan /** 1592d76a60baSAnirudh Venkataramanan * ice_vlan_rx_kill_vid - Remove a vlan id filter from HW offload 1593d76a60baSAnirudh Venkataramanan * @netdev: network interface to be adjusted 1594d76a60baSAnirudh Venkataramanan * @proto: unused protocol 1595d76a60baSAnirudh Venkataramanan * @vid: vlan id to be removed 1596d76a60baSAnirudh Venkataramanan * 1597d76a60baSAnirudh Venkataramanan * net_device_ops implementation for removing vlan ids 1598d76a60baSAnirudh Venkataramanan */ 1599d76a60baSAnirudh Venkataramanan static int ice_vlan_rx_kill_vid(struct net_device *netdev, 1600d76a60baSAnirudh Venkataramanan __always_unused __be16 proto, u16 vid) 1601d76a60baSAnirudh Venkataramanan { 1602d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1603d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 16044f74dcc1SBrett Creeley int status; 1605d76a60baSAnirudh Venkataramanan 1606d76a60baSAnirudh Venkataramanan if (vsi->info.pvid) 1607d76a60baSAnirudh Venkataramanan return -EINVAL; 1608d76a60baSAnirudh Venkataramanan 16094f74dcc1SBrett Creeley /* Make sure ice_vsi_kill_vlan is successful before updating VLAN 16104f74dcc1SBrett Creeley * information 1611d76a60baSAnirudh Venkataramanan */ 16124f74dcc1SBrett Creeley status = ice_vsi_kill_vlan(vsi, vid); 16134f74dcc1SBrett Creeley if (status) 16144f74dcc1SBrett Creeley return status; 1615d76a60baSAnirudh Venkataramanan 1616d76a60baSAnirudh Venkataramanan clear_bit(vid, vsi->active_vlans); 1617d76a60baSAnirudh Venkataramanan 16184f74dcc1SBrett Creeley /* Disable VLAN pruning when VLAN 0 is removed */ 16194f74dcc1SBrett Creeley if (unlikely(!vid)) 16204f74dcc1SBrett Creeley status = ice_cfg_vlan_pruning(vsi, false); 16214f74dcc1SBrett Creeley 16224f74dcc1SBrett Creeley return status; 1623d76a60baSAnirudh Venkataramanan } 1624d76a60baSAnirudh Venkataramanan 1625d76a60baSAnirudh Venkataramanan /** 16263a858ba3SAnirudh Venkataramanan * ice_setup_pf_sw - Setup the HW switch on startup or after reset 16273a858ba3SAnirudh Venkataramanan * @pf: board private structure 16283a858ba3SAnirudh Venkataramanan * 16293a858ba3SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 16303a858ba3SAnirudh Venkataramanan */ 16313a858ba3SAnirudh Venkataramanan static int ice_setup_pf_sw(struct ice_pf *pf) 16323a858ba3SAnirudh Venkataramanan { 16339daf8208SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 16349daf8208SAnirudh Venkataramanan u8 broadcast[ETH_ALEN]; 16353a858ba3SAnirudh Venkataramanan struct ice_vsi *vsi; 16363a858ba3SAnirudh Venkataramanan int status = 0; 16373a858ba3SAnirudh Venkataramanan 16385df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) 16390f9d5027SAnirudh Venkataramanan return -EBUSY; 16400f9d5027SAnirudh Venkataramanan 16410f9d5027SAnirudh Venkataramanan vsi = ice_pf_vsi_setup(pf, pf->hw.port_info); 16423a858ba3SAnirudh Venkataramanan if (!vsi) { 16433a858ba3SAnirudh Venkataramanan status = -ENOMEM; 16440f9d5027SAnirudh Venkataramanan goto unroll_vsi_setup; 16450b28b702SAnirudh Venkataramanan } 16463a858ba3SAnirudh Venkataramanan 1647df0f8479SAnirudh Venkataramanan status = ice_cfg_netdev(vsi); 1648df0f8479SAnirudh Venkataramanan if (status) { 1649df0f8479SAnirudh Venkataramanan status = -ENODEV; 1650df0f8479SAnirudh Venkataramanan goto unroll_vsi_setup; 1651df0f8479SAnirudh Venkataramanan } 1652df0f8479SAnirudh Venkataramanan 1653df0f8479SAnirudh Venkataramanan /* registering the NAPI handler requires both the queues and 1654df0f8479SAnirudh Venkataramanan * netdev to be created, which are done in ice_pf_vsi_setup() 1655df0f8479SAnirudh Venkataramanan * and ice_cfg_netdev() respectively 1656df0f8479SAnirudh Venkataramanan */ 1657df0f8479SAnirudh Venkataramanan ice_napi_add(vsi); 1658df0f8479SAnirudh Venkataramanan 16590f9d5027SAnirudh Venkataramanan /* To add a MAC filter, first add the MAC to a list and then 16600f9d5027SAnirudh Venkataramanan * pass the list to ice_add_mac. 16619daf8208SAnirudh Venkataramanan */ 16620f9d5027SAnirudh Venkataramanan 16630f9d5027SAnirudh Venkataramanan /* Add a unicast MAC filter so the VSI can get its packets */ 16649daf8208SAnirudh Venkataramanan status = ice_add_mac_to_list(vsi, &tmp_add_list, 16659daf8208SAnirudh Venkataramanan vsi->port_info->mac.perm_addr); 16669daf8208SAnirudh Venkataramanan if (status) 1667df0f8479SAnirudh Venkataramanan goto unroll_napi_add; 16689daf8208SAnirudh Venkataramanan 16699daf8208SAnirudh Venkataramanan /* VSI needs to receive broadcast traffic, so add the broadcast 16700f9d5027SAnirudh Venkataramanan * MAC address to the list as well. 16719daf8208SAnirudh Venkataramanan */ 16729daf8208SAnirudh Venkataramanan eth_broadcast_addr(broadcast); 16739daf8208SAnirudh Venkataramanan status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast); 16749daf8208SAnirudh Venkataramanan if (status) 16750f9d5027SAnirudh Venkataramanan goto free_mac_list; 16769daf8208SAnirudh Venkataramanan 16779daf8208SAnirudh Venkataramanan /* program MAC filters for entries in tmp_add_list */ 16789daf8208SAnirudh Venkataramanan status = ice_add_mac(&pf->hw, &tmp_add_list); 16799daf8208SAnirudh Venkataramanan if (status) { 16809daf8208SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Could not add MAC filters\n"); 16819daf8208SAnirudh Venkataramanan status = -ENOMEM; 16820f9d5027SAnirudh Venkataramanan goto free_mac_list; 16839daf8208SAnirudh Venkataramanan } 16849daf8208SAnirudh Venkataramanan 16859daf8208SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 16869daf8208SAnirudh Venkataramanan return status; 16879daf8208SAnirudh Venkataramanan 16880f9d5027SAnirudh Venkataramanan free_mac_list: 16899daf8208SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 16909daf8208SAnirudh Venkataramanan 1691df0f8479SAnirudh Venkataramanan unroll_napi_add: 16923a858ba3SAnirudh Venkataramanan if (vsi) { 1693df0f8479SAnirudh Venkataramanan ice_napi_del(vsi); 16943a858ba3SAnirudh Venkataramanan if (vsi->netdev) { 1695df0f8479SAnirudh Venkataramanan if (vsi->netdev->reg_state == NETREG_REGISTERED) 1696df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 16973a858ba3SAnirudh Venkataramanan free_netdev(vsi->netdev); 16983a858ba3SAnirudh Venkataramanan vsi->netdev = NULL; 16993a858ba3SAnirudh Venkataramanan } 1700df0f8479SAnirudh Venkataramanan } 17019daf8208SAnirudh Venkataramanan 1702df0f8479SAnirudh Venkataramanan unroll_vsi_setup: 1703df0f8479SAnirudh Venkataramanan if (vsi) { 1704df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 17053a858ba3SAnirudh Venkataramanan ice_vsi_delete(vsi); 17063a858ba3SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 17073a858ba3SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 17083a858ba3SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 17093a858ba3SAnirudh Venkataramanan ice_vsi_clear(vsi); 17103a858ba3SAnirudh Venkataramanan } 17113a858ba3SAnirudh Venkataramanan return status; 17123a858ba3SAnirudh Venkataramanan } 17133a858ba3SAnirudh Venkataramanan 17143a858ba3SAnirudh Venkataramanan /** 1715940b61afSAnirudh Venkataramanan * ice_determine_q_usage - Calculate queue distribution 1716940b61afSAnirudh Venkataramanan * @pf: board private structure 1717940b61afSAnirudh Venkataramanan * 1718940b61afSAnirudh Venkataramanan * Return -ENOMEM if we don't get enough queues for all ports 1719940b61afSAnirudh Venkataramanan */ 1720940b61afSAnirudh Venkataramanan static void ice_determine_q_usage(struct ice_pf *pf) 1721940b61afSAnirudh Venkataramanan { 1722940b61afSAnirudh Venkataramanan u16 q_left_tx, q_left_rx; 1723940b61afSAnirudh Venkataramanan 1724940b61afSAnirudh Venkataramanan q_left_tx = pf->hw.func_caps.common_cap.num_txq; 1725940b61afSAnirudh Venkataramanan q_left_rx = pf->hw.func_caps.common_cap.num_rxq; 1726940b61afSAnirudh Venkataramanan 17275513b920SAnirudh Venkataramanan pf->num_lan_tx = min_t(int, q_left_tx, num_online_cpus()); 1728d76a60baSAnirudh Venkataramanan 1729d76a60baSAnirudh Venkataramanan /* only 1 rx queue unless RSS is enabled */ 1730d76a60baSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 1731940b61afSAnirudh Venkataramanan pf->num_lan_rx = 1; 1732d76a60baSAnirudh Venkataramanan else 1733d76a60baSAnirudh Venkataramanan pf->num_lan_rx = min_t(int, q_left_rx, num_online_cpus()); 1734940b61afSAnirudh Venkataramanan 1735940b61afSAnirudh Venkataramanan pf->q_left_tx = q_left_tx - pf->num_lan_tx; 1736940b61afSAnirudh Venkataramanan pf->q_left_rx = q_left_rx - pf->num_lan_rx; 1737940b61afSAnirudh Venkataramanan } 1738940b61afSAnirudh Venkataramanan 1739940b61afSAnirudh Venkataramanan /** 1740940b61afSAnirudh Venkataramanan * ice_deinit_pf - Unrolls initialziations done by ice_init_pf 1741940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 1742940b61afSAnirudh Venkataramanan */ 1743940b61afSAnirudh Venkataramanan static void ice_deinit_pf(struct ice_pf *pf) 1744940b61afSAnirudh Venkataramanan { 17458d81fa55SAkeem G Abodunrin ice_service_task_stop(pf); 1746940b61afSAnirudh Venkataramanan mutex_destroy(&pf->sw_mutex); 1747940b61afSAnirudh Venkataramanan mutex_destroy(&pf->avail_q_mutex); 1748940b61afSAnirudh Venkataramanan } 1749940b61afSAnirudh Venkataramanan 1750940b61afSAnirudh Venkataramanan /** 1751940b61afSAnirudh Venkataramanan * ice_init_pf - Initialize general software structures (struct ice_pf) 1752940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 1753940b61afSAnirudh Venkataramanan */ 1754940b61afSAnirudh Venkataramanan static void ice_init_pf(struct ice_pf *pf) 1755940b61afSAnirudh Venkataramanan { 1756940b61afSAnirudh Venkataramanan bitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS); 1757940b61afSAnirudh Venkataramanan set_bit(ICE_FLAG_MSIX_ENA, pf->flags); 1758940b61afSAnirudh Venkataramanan 1759940b61afSAnirudh Venkataramanan mutex_init(&pf->sw_mutex); 1760940b61afSAnirudh Venkataramanan mutex_init(&pf->avail_q_mutex); 1761940b61afSAnirudh Venkataramanan 1762940b61afSAnirudh Venkataramanan /* Clear avail_[t|r]x_qs bitmaps (set all to avail) */ 1763940b61afSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 1764940b61afSAnirudh Venkataramanan bitmap_zero(pf->avail_txqs, ICE_MAX_TXQS); 1765940b61afSAnirudh Venkataramanan bitmap_zero(pf->avail_rxqs, ICE_MAX_RXQS); 1766940b61afSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 1767940b61afSAnirudh Venkataramanan 1768d76a60baSAnirudh Venkataramanan if (pf->hw.func_caps.common_cap.rss_table_size) 1769d76a60baSAnirudh Venkataramanan set_bit(ICE_FLAG_RSS_ENA, pf->flags); 1770d76a60baSAnirudh Venkataramanan 1771940b61afSAnirudh Venkataramanan /* setup service timer and periodic service task */ 1772940b61afSAnirudh Venkataramanan timer_setup(&pf->serv_tmr, ice_service_timer, 0); 1773940b61afSAnirudh Venkataramanan pf->serv_tmr_period = HZ; 1774940b61afSAnirudh Venkataramanan INIT_WORK(&pf->serv_task, ice_service_task); 1775940b61afSAnirudh Venkataramanan clear_bit(__ICE_SERVICE_SCHED, pf->state); 1776940b61afSAnirudh Venkataramanan } 1777940b61afSAnirudh Venkataramanan 1778940b61afSAnirudh Venkataramanan /** 1779940b61afSAnirudh Venkataramanan * ice_ena_msix_range - Request a range of MSIX vectors from the OS 1780940b61afSAnirudh Venkataramanan * @pf: board private structure 1781940b61afSAnirudh Venkataramanan * 1782940b61afSAnirudh Venkataramanan * compute the number of MSIX vectors required (v_budget) and request from 1783940b61afSAnirudh Venkataramanan * the OS. Return the number of vectors reserved or negative on failure 1784940b61afSAnirudh Venkataramanan */ 1785940b61afSAnirudh Venkataramanan static int ice_ena_msix_range(struct ice_pf *pf) 1786940b61afSAnirudh Venkataramanan { 1787940b61afSAnirudh Venkataramanan int v_left, v_actual, v_budget = 0; 1788940b61afSAnirudh Venkataramanan int needed, err, i; 1789940b61afSAnirudh Venkataramanan 1790940b61afSAnirudh Venkataramanan v_left = pf->hw.func_caps.common_cap.num_msix_vectors; 1791940b61afSAnirudh Venkataramanan 1792940b61afSAnirudh Venkataramanan /* reserve one vector for miscellaneous handler */ 1793940b61afSAnirudh Venkataramanan needed = 1; 1794940b61afSAnirudh Venkataramanan v_budget += needed; 1795940b61afSAnirudh Venkataramanan v_left -= needed; 1796940b61afSAnirudh Venkataramanan 1797940b61afSAnirudh Venkataramanan /* reserve vectors for LAN traffic */ 1798940b61afSAnirudh Venkataramanan pf->num_lan_msix = min_t(int, num_online_cpus(), v_left); 1799940b61afSAnirudh Venkataramanan v_budget += pf->num_lan_msix; 1800940b61afSAnirudh Venkataramanan 1801940b61afSAnirudh Venkataramanan pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget, 1802940b61afSAnirudh Venkataramanan sizeof(struct msix_entry), GFP_KERNEL); 1803940b61afSAnirudh Venkataramanan 1804940b61afSAnirudh Venkataramanan if (!pf->msix_entries) { 1805940b61afSAnirudh Venkataramanan err = -ENOMEM; 1806940b61afSAnirudh Venkataramanan goto exit_err; 1807940b61afSAnirudh Venkataramanan } 1808940b61afSAnirudh Venkataramanan 1809940b61afSAnirudh Venkataramanan for (i = 0; i < v_budget; i++) 1810940b61afSAnirudh Venkataramanan pf->msix_entries[i].entry = i; 1811940b61afSAnirudh Venkataramanan 1812940b61afSAnirudh Venkataramanan /* actually reserve the vectors */ 1813940b61afSAnirudh Venkataramanan v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries, 1814940b61afSAnirudh Venkataramanan ICE_MIN_MSIX, v_budget); 1815940b61afSAnirudh Venkataramanan 1816940b61afSAnirudh Venkataramanan if (v_actual < 0) { 1817940b61afSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "unable to reserve MSI-X vectors\n"); 1818940b61afSAnirudh Venkataramanan err = v_actual; 1819940b61afSAnirudh Venkataramanan goto msix_err; 1820940b61afSAnirudh Venkataramanan } 1821940b61afSAnirudh Venkataramanan 1822940b61afSAnirudh Venkataramanan if (v_actual < v_budget) { 1823940b61afSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 1824940b61afSAnirudh Venkataramanan "not enough vectors. requested = %d, obtained = %d\n", 1825940b61afSAnirudh Venkataramanan v_budget, v_actual); 1826940b61afSAnirudh Venkataramanan if (v_actual >= (pf->num_lan_msix + 1)) { 1827940b61afSAnirudh Venkataramanan pf->num_avail_msix = v_actual - (pf->num_lan_msix + 1); 1828940b61afSAnirudh Venkataramanan } else if (v_actual >= 2) { 1829940b61afSAnirudh Venkataramanan pf->num_lan_msix = 1; 1830940b61afSAnirudh Venkataramanan pf->num_avail_msix = v_actual - 2; 1831940b61afSAnirudh Venkataramanan } else { 1832940b61afSAnirudh Venkataramanan pci_disable_msix(pf->pdev); 1833940b61afSAnirudh Venkataramanan err = -ERANGE; 1834940b61afSAnirudh Venkataramanan goto msix_err; 1835940b61afSAnirudh Venkataramanan } 1836940b61afSAnirudh Venkataramanan } 1837940b61afSAnirudh Venkataramanan 1838940b61afSAnirudh Venkataramanan return v_actual; 1839940b61afSAnirudh Venkataramanan 1840940b61afSAnirudh Venkataramanan msix_err: 1841940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->msix_entries); 1842940b61afSAnirudh Venkataramanan goto exit_err; 1843940b61afSAnirudh Venkataramanan 1844940b61afSAnirudh Venkataramanan exit_err: 1845940b61afSAnirudh Venkataramanan pf->num_lan_msix = 0; 1846940b61afSAnirudh Venkataramanan clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); 1847940b61afSAnirudh Venkataramanan return err; 1848940b61afSAnirudh Venkataramanan } 1849940b61afSAnirudh Venkataramanan 1850940b61afSAnirudh Venkataramanan /** 1851940b61afSAnirudh Venkataramanan * ice_dis_msix - Disable MSI-X interrupt setup in OS 1852940b61afSAnirudh Venkataramanan * @pf: board private structure 1853940b61afSAnirudh Venkataramanan */ 1854940b61afSAnirudh Venkataramanan static void ice_dis_msix(struct ice_pf *pf) 1855940b61afSAnirudh Venkataramanan { 1856940b61afSAnirudh Venkataramanan pci_disable_msix(pf->pdev); 1857940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->msix_entries); 1858940b61afSAnirudh Venkataramanan pf->msix_entries = NULL; 1859940b61afSAnirudh Venkataramanan clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); 1860940b61afSAnirudh Venkataramanan } 1861940b61afSAnirudh Venkataramanan 1862940b61afSAnirudh Venkataramanan /** 1863940b61afSAnirudh Venkataramanan * ice_init_interrupt_scheme - Determine proper interrupt scheme 1864940b61afSAnirudh Venkataramanan * @pf: board private structure to initialize 1865940b61afSAnirudh Venkataramanan */ 1866940b61afSAnirudh Venkataramanan static int ice_init_interrupt_scheme(struct ice_pf *pf) 1867940b61afSAnirudh Venkataramanan { 1868940b61afSAnirudh Venkataramanan int vectors = 0; 1869940b61afSAnirudh Venkataramanan ssize_t size; 1870940b61afSAnirudh Venkataramanan 1871940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 1872940b61afSAnirudh Venkataramanan vectors = ice_ena_msix_range(pf); 1873940b61afSAnirudh Venkataramanan else 1874940b61afSAnirudh Venkataramanan return -ENODEV; 1875940b61afSAnirudh Venkataramanan 1876940b61afSAnirudh Venkataramanan if (vectors < 0) 1877940b61afSAnirudh Venkataramanan return vectors; 1878940b61afSAnirudh Venkataramanan 1879940b61afSAnirudh Venkataramanan /* set up vector assignment tracking */ 1880940b61afSAnirudh Venkataramanan size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors); 1881940b61afSAnirudh Venkataramanan 1882940b61afSAnirudh Venkataramanan pf->irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); 1883940b61afSAnirudh Venkataramanan if (!pf->irq_tracker) { 1884940b61afSAnirudh Venkataramanan ice_dis_msix(pf); 1885940b61afSAnirudh Venkataramanan return -ENOMEM; 1886940b61afSAnirudh Venkataramanan } 1887940b61afSAnirudh Venkataramanan 1888940b61afSAnirudh Venkataramanan pf->irq_tracker->num_entries = vectors; 1889940b61afSAnirudh Venkataramanan 1890940b61afSAnirudh Venkataramanan return 0; 1891940b61afSAnirudh Venkataramanan } 1892940b61afSAnirudh Venkataramanan 1893940b61afSAnirudh Venkataramanan /** 1894940b61afSAnirudh Venkataramanan * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme 1895940b61afSAnirudh Venkataramanan * @pf: board private structure 1896940b61afSAnirudh Venkataramanan */ 1897940b61afSAnirudh Venkataramanan static void ice_clear_interrupt_scheme(struct ice_pf *pf) 1898940b61afSAnirudh Venkataramanan { 1899940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 1900940b61afSAnirudh Venkataramanan ice_dis_msix(pf); 1901940b61afSAnirudh Venkataramanan 1902c7f2c42bSAnirudh Venkataramanan if (pf->irq_tracker) { 1903940b61afSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->irq_tracker); 1904940b61afSAnirudh Venkataramanan pf->irq_tracker = NULL; 1905940b61afSAnirudh Venkataramanan } 1906c7f2c42bSAnirudh Venkataramanan } 1907940b61afSAnirudh Venkataramanan 1908940b61afSAnirudh Venkataramanan /** 1909837f08fdSAnirudh Venkataramanan * ice_probe - Device initialization routine 1910837f08fdSAnirudh Venkataramanan * @pdev: PCI device information struct 1911837f08fdSAnirudh Venkataramanan * @ent: entry in ice_pci_tbl 1912837f08fdSAnirudh Venkataramanan * 1913837f08fdSAnirudh Venkataramanan * Returns 0 on success, negative on failure 1914837f08fdSAnirudh Venkataramanan */ 1915837f08fdSAnirudh Venkataramanan static int ice_probe(struct pci_dev *pdev, 1916837f08fdSAnirudh Venkataramanan const struct pci_device_id __always_unused *ent) 1917837f08fdSAnirudh Venkataramanan { 1918837f08fdSAnirudh Venkataramanan struct ice_pf *pf; 1919837f08fdSAnirudh Venkataramanan struct ice_hw *hw; 1920837f08fdSAnirudh Venkataramanan int err; 1921837f08fdSAnirudh Venkataramanan 1922837f08fdSAnirudh Venkataramanan /* this driver uses devres, see Documentation/driver-model/devres.txt */ 1923837f08fdSAnirudh Venkataramanan err = pcim_enable_device(pdev); 1924837f08fdSAnirudh Venkataramanan if (err) 1925837f08fdSAnirudh Venkataramanan return err; 1926837f08fdSAnirudh Venkataramanan 1927837f08fdSAnirudh Venkataramanan err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev)); 1928837f08fdSAnirudh Venkataramanan if (err) { 19293968540bSAnirudh Venkataramanan dev_err(&pdev->dev, "BAR0 I/O map error %d\n", err); 1930837f08fdSAnirudh Venkataramanan return err; 1931837f08fdSAnirudh Venkataramanan } 1932837f08fdSAnirudh Venkataramanan 1933837f08fdSAnirudh Venkataramanan pf = devm_kzalloc(&pdev->dev, sizeof(*pf), GFP_KERNEL); 1934837f08fdSAnirudh Venkataramanan if (!pf) 1935837f08fdSAnirudh Venkataramanan return -ENOMEM; 1936837f08fdSAnirudh Venkataramanan 1937837f08fdSAnirudh Venkataramanan /* set up for high or low dma */ 1938837f08fdSAnirudh Venkataramanan err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 1939837f08fdSAnirudh Venkataramanan if (err) 1940837f08fdSAnirudh Venkataramanan err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 1941837f08fdSAnirudh Venkataramanan if (err) { 1942837f08fdSAnirudh Venkataramanan dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err); 1943837f08fdSAnirudh Venkataramanan return err; 1944837f08fdSAnirudh Venkataramanan } 1945837f08fdSAnirudh Venkataramanan 1946837f08fdSAnirudh Venkataramanan pci_enable_pcie_error_reporting(pdev); 1947837f08fdSAnirudh Venkataramanan pci_set_master(pdev); 1948837f08fdSAnirudh Venkataramanan 1949837f08fdSAnirudh Venkataramanan pf->pdev = pdev; 1950837f08fdSAnirudh Venkataramanan pci_set_drvdata(pdev, pf); 1951837f08fdSAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 19528d81fa55SAkeem G Abodunrin /* Disable service task until DOWN bit is cleared */ 19538d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 1954837f08fdSAnirudh Venkataramanan 1955837f08fdSAnirudh Venkataramanan hw = &pf->hw; 1956837f08fdSAnirudh Venkataramanan hw->hw_addr = pcim_iomap_table(pdev)[ICE_BAR0]; 1957837f08fdSAnirudh Venkataramanan hw->back = pf; 1958837f08fdSAnirudh Venkataramanan hw->vendor_id = pdev->vendor; 1959837f08fdSAnirudh Venkataramanan hw->device_id = pdev->device; 1960837f08fdSAnirudh Venkataramanan pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); 1961837f08fdSAnirudh Venkataramanan hw->subsystem_vendor_id = pdev->subsystem_vendor; 1962837f08fdSAnirudh Venkataramanan hw->subsystem_device_id = pdev->subsystem_device; 1963837f08fdSAnirudh Venkataramanan hw->bus.device = PCI_SLOT(pdev->devfn); 1964837f08fdSAnirudh Venkataramanan hw->bus.func = PCI_FUNC(pdev->devfn); 1965f31e4b6fSAnirudh Venkataramanan ice_set_ctrlq_len(hw); 1966f31e4b6fSAnirudh Venkataramanan 1967837f08fdSAnirudh Venkataramanan pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M); 1968837f08fdSAnirudh Venkataramanan 19697ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 19707ec59eeaSAnirudh Venkataramanan if (debug < -1) 19717ec59eeaSAnirudh Venkataramanan hw->debug_mask = debug; 19727ec59eeaSAnirudh Venkataramanan #endif 19737ec59eeaSAnirudh Venkataramanan 1974f31e4b6fSAnirudh Venkataramanan err = ice_init_hw(hw); 1975f31e4b6fSAnirudh Venkataramanan if (err) { 1976f31e4b6fSAnirudh Venkataramanan dev_err(&pdev->dev, "ice_init_hw failed: %d\n", err); 1977f31e4b6fSAnirudh Venkataramanan err = -EIO; 1978f31e4b6fSAnirudh Venkataramanan goto err_exit_unroll; 1979f31e4b6fSAnirudh Venkataramanan } 1980f31e4b6fSAnirudh Venkataramanan 1981f31e4b6fSAnirudh Venkataramanan dev_info(&pdev->dev, "firmware %d.%d.%05d api %d.%d\n", 1982f31e4b6fSAnirudh Venkataramanan hw->fw_maj_ver, hw->fw_min_ver, hw->fw_build, 1983f31e4b6fSAnirudh Venkataramanan hw->api_maj_ver, hw->api_min_ver); 1984f31e4b6fSAnirudh Venkataramanan 1985940b61afSAnirudh Venkataramanan ice_init_pf(pf); 1986940b61afSAnirudh Venkataramanan 1987940b61afSAnirudh Venkataramanan ice_determine_q_usage(pf); 1988940b61afSAnirudh Venkataramanan 1989940b61afSAnirudh Venkataramanan pf->num_alloc_vsi = min_t(u16, ICE_MAX_VSI_ALLOC, 1990940b61afSAnirudh Venkataramanan hw->func_caps.guaranteed_num_vsi); 1991940b61afSAnirudh Venkataramanan if (!pf->num_alloc_vsi) { 1992940b61afSAnirudh Venkataramanan err = -EIO; 1993940b61afSAnirudh Venkataramanan goto err_init_pf_unroll; 1994940b61afSAnirudh Venkataramanan } 1995940b61afSAnirudh Venkataramanan 1996940b61afSAnirudh Venkataramanan pf->vsi = devm_kcalloc(&pdev->dev, pf->num_alloc_vsi, 1997940b61afSAnirudh Venkataramanan sizeof(struct ice_vsi *), GFP_KERNEL); 1998940b61afSAnirudh Venkataramanan if (!pf->vsi) { 1999940b61afSAnirudh Venkataramanan err = -ENOMEM; 2000940b61afSAnirudh Venkataramanan goto err_init_pf_unroll; 2001940b61afSAnirudh Venkataramanan } 2002940b61afSAnirudh Venkataramanan 2003940b61afSAnirudh Venkataramanan err = ice_init_interrupt_scheme(pf); 2004940b61afSAnirudh Venkataramanan if (err) { 2005940b61afSAnirudh Venkataramanan dev_err(&pdev->dev, 2006940b61afSAnirudh Venkataramanan "ice_init_interrupt_scheme failed: %d\n", err); 2007940b61afSAnirudh Venkataramanan err = -EIO; 2008940b61afSAnirudh Venkataramanan goto err_init_interrupt_unroll; 2009940b61afSAnirudh Venkataramanan } 2010940b61afSAnirudh Venkataramanan 20118d81fa55SAkeem G Abodunrin /* Driver is mostly up */ 20128d81fa55SAkeem G Abodunrin clear_bit(__ICE_DOWN, pf->state); 20138d81fa55SAkeem G Abodunrin 2014940b61afSAnirudh Venkataramanan /* In case of MSIX we are going to setup the misc vector right here 2015940b61afSAnirudh Venkataramanan * to handle admin queue events etc. In case of legacy and MSI 2016940b61afSAnirudh Venkataramanan * the misc functionality and queue processing is combined in 2017940b61afSAnirudh Venkataramanan * the same vector and that gets setup at open. 2018940b61afSAnirudh Venkataramanan */ 2019940b61afSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 2020940b61afSAnirudh Venkataramanan err = ice_req_irq_msix_misc(pf); 2021940b61afSAnirudh Venkataramanan if (err) { 2022940b61afSAnirudh Venkataramanan dev_err(&pdev->dev, 2023940b61afSAnirudh Venkataramanan "setup of misc vector failed: %d\n", err); 2024940b61afSAnirudh Venkataramanan goto err_init_interrupt_unroll; 2025940b61afSAnirudh Venkataramanan } 2026940b61afSAnirudh Venkataramanan } 2027940b61afSAnirudh Venkataramanan 2028940b61afSAnirudh Venkataramanan /* create switch struct for the switch element created by FW on boot */ 2029940b61afSAnirudh Venkataramanan pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(struct ice_sw), 2030940b61afSAnirudh Venkataramanan GFP_KERNEL); 2031940b61afSAnirudh Venkataramanan if (!pf->first_sw) { 2032940b61afSAnirudh Venkataramanan err = -ENOMEM; 2033940b61afSAnirudh Venkataramanan goto err_msix_misc_unroll; 2034940b61afSAnirudh Venkataramanan } 2035940b61afSAnirudh Venkataramanan 2036b1edc14aSMd Fahad Iqbal Polash if (hw->evb_veb) 2037940b61afSAnirudh Venkataramanan pf->first_sw->bridge_mode = BRIDGE_MODE_VEB; 2038b1edc14aSMd Fahad Iqbal Polash else 2039b1edc14aSMd Fahad Iqbal Polash pf->first_sw->bridge_mode = BRIDGE_MODE_VEPA; 2040b1edc14aSMd Fahad Iqbal Polash 2041940b61afSAnirudh Venkataramanan pf->first_sw->pf = pf; 2042940b61afSAnirudh Venkataramanan 2043940b61afSAnirudh Venkataramanan /* record the sw_id available for later use */ 2044940b61afSAnirudh Venkataramanan pf->first_sw->sw_id = hw->port_info->sw_id; 2045940b61afSAnirudh Venkataramanan 20463a858ba3SAnirudh Venkataramanan err = ice_setup_pf_sw(pf); 20473a858ba3SAnirudh Venkataramanan if (err) { 20483a858ba3SAnirudh Venkataramanan dev_err(&pdev->dev, 20493a858ba3SAnirudh Venkataramanan "probe failed due to setup pf switch:%d\n", err); 20503a858ba3SAnirudh Venkataramanan goto err_alloc_sw_unroll; 20513a858ba3SAnirudh Venkataramanan } 20529daf8208SAnirudh Venkataramanan 20538d81fa55SAkeem G Abodunrin clear_bit(__ICE_SERVICE_DIS, pf->state); 20549daf8208SAnirudh Venkataramanan 20559daf8208SAnirudh Venkataramanan /* since everything is good, start the service timer */ 20569daf8208SAnirudh Venkataramanan mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); 20579daf8208SAnirudh Venkataramanan 20580b28b702SAnirudh Venkataramanan err = ice_init_link_events(pf->hw.port_info); 20590b28b702SAnirudh Venkataramanan if (err) { 20600b28b702SAnirudh Venkataramanan dev_err(&pdev->dev, "ice_init_link_events failed: %d\n", err); 20610b28b702SAnirudh Venkataramanan goto err_alloc_sw_unroll; 20620b28b702SAnirudh Venkataramanan } 20630b28b702SAnirudh Venkataramanan 2064837f08fdSAnirudh Venkataramanan return 0; 2065f31e4b6fSAnirudh Venkataramanan 20663a858ba3SAnirudh Venkataramanan err_alloc_sw_unroll: 20678d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 20683a858ba3SAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 20693a858ba3SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, pf->first_sw); 2070940b61afSAnirudh Venkataramanan err_msix_misc_unroll: 2071940b61afSAnirudh Venkataramanan ice_free_irq_msix_misc(pf); 2072940b61afSAnirudh Venkataramanan err_init_interrupt_unroll: 2073940b61afSAnirudh Venkataramanan ice_clear_interrupt_scheme(pf); 2074940b61afSAnirudh Venkataramanan devm_kfree(&pdev->dev, pf->vsi); 2075940b61afSAnirudh Venkataramanan err_init_pf_unroll: 2076940b61afSAnirudh Venkataramanan ice_deinit_pf(pf); 2077940b61afSAnirudh Venkataramanan ice_deinit_hw(hw); 2078f31e4b6fSAnirudh Venkataramanan err_exit_unroll: 2079f31e4b6fSAnirudh Venkataramanan pci_disable_pcie_error_reporting(pdev); 2080f31e4b6fSAnirudh Venkataramanan return err; 2081837f08fdSAnirudh Venkataramanan } 2082837f08fdSAnirudh Venkataramanan 2083837f08fdSAnirudh Venkataramanan /** 2084837f08fdSAnirudh Venkataramanan * ice_remove - Device removal routine 2085837f08fdSAnirudh Venkataramanan * @pdev: PCI device information struct 2086837f08fdSAnirudh Venkataramanan */ 2087837f08fdSAnirudh Venkataramanan static void ice_remove(struct pci_dev *pdev) 2088837f08fdSAnirudh Venkataramanan { 2089837f08fdSAnirudh Venkataramanan struct ice_pf *pf = pci_get_drvdata(pdev); 2090837f08fdSAnirudh Venkataramanan 2091837f08fdSAnirudh Venkataramanan if (!pf) 2092837f08fdSAnirudh Venkataramanan return; 2093837f08fdSAnirudh Venkataramanan 2094837f08fdSAnirudh Venkataramanan set_bit(__ICE_DOWN, pf->state); 20958d81fa55SAkeem G Abodunrin ice_service_task_stop(pf); 2096f31e4b6fSAnirudh Venkataramanan 20970f9d5027SAnirudh Venkataramanan ice_vsi_release_all(pf); 2098940b61afSAnirudh Venkataramanan ice_free_irq_msix_misc(pf); 2099940b61afSAnirudh Venkataramanan ice_clear_interrupt_scheme(pf); 2100940b61afSAnirudh Venkataramanan ice_deinit_pf(pf); 2101f31e4b6fSAnirudh Venkataramanan ice_deinit_hw(&pf->hw); 2102837f08fdSAnirudh Venkataramanan pci_disable_pcie_error_reporting(pdev); 2103837f08fdSAnirudh Venkataramanan } 2104837f08fdSAnirudh Venkataramanan 2105837f08fdSAnirudh Venkataramanan /* ice_pci_tbl - PCI Device ID Table 2106837f08fdSAnirudh Venkataramanan * 2107837f08fdSAnirudh Venkataramanan * Wildcard entries (PCI_ANY_ID) should come last 2108837f08fdSAnirudh Venkataramanan * Last entry must be all 0s 2109837f08fdSAnirudh Venkataramanan * 2110837f08fdSAnirudh Venkataramanan * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, 2111837f08fdSAnirudh Venkataramanan * Class, Class Mask, private data (not used) } 2112837f08fdSAnirudh Venkataramanan */ 2113837f08fdSAnirudh Venkataramanan static const struct pci_device_id ice_pci_tbl[] = { 2114837f08fdSAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_BACKPLANE), 0 }, 2115837f08fdSAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_QSFP), 0 }, 2116837f08fdSAnirudh Venkataramanan { PCI_VDEVICE(INTEL, ICE_DEV_ID_C810_SFP), 0 }, 2117837f08fdSAnirudh Venkataramanan /* required last entry */ 2118837f08fdSAnirudh Venkataramanan { 0, } 2119837f08fdSAnirudh Venkataramanan }; 2120837f08fdSAnirudh Venkataramanan MODULE_DEVICE_TABLE(pci, ice_pci_tbl); 2121837f08fdSAnirudh Venkataramanan 2122837f08fdSAnirudh Venkataramanan static struct pci_driver ice_driver = { 2123837f08fdSAnirudh Venkataramanan .name = KBUILD_MODNAME, 2124837f08fdSAnirudh Venkataramanan .id_table = ice_pci_tbl, 2125837f08fdSAnirudh Venkataramanan .probe = ice_probe, 2126837f08fdSAnirudh Venkataramanan .remove = ice_remove, 2127837f08fdSAnirudh Venkataramanan }; 2128837f08fdSAnirudh Venkataramanan 2129837f08fdSAnirudh Venkataramanan /** 2130837f08fdSAnirudh Venkataramanan * ice_module_init - Driver registration routine 2131837f08fdSAnirudh Venkataramanan * 2132837f08fdSAnirudh Venkataramanan * ice_module_init is the first routine called when the driver is 2133837f08fdSAnirudh Venkataramanan * loaded. All it does is register with the PCI subsystem. 2134837f08fdSAnirudh Venkataramanan */ 2135837f08fdSAnirudh Venkataramanan static int __init ice_module_init(void) 2136837f08fdSAnirudh Venkataramanan { 2137837f08fdSAnirudh Venkataramanan int status; 2138837f08fdSAnirudh Venkataramanan 2139837f08fdSAnirudh Venkataramanan pr_info("%s - version %s\n", ice_driver_string, ice_drv_ver); 2140837f08fdSAnirudh Venkataramanan pr_info("%s\n", ice_copyright); 2141837f08fdSAnirudh Venkataramanan 21420f9d5027SAnirudh Venkataramanan ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME); 2143940b61afSAnirudh Venkataramanan if (!ice_wq) { 2144940b61afSAnirudh Venkataramanan pr_err("Failed to create workqueue\n"); 2145940b61afSAnirudh Venkataramanan return -ENOMEM; 2146940b61afSAnirudh Venkataramanan } 2147940b61afSAnirudh Venkataramanan 2148837f08fdSAnirudh Venkataramanan status = pci_register_driver(&ice_driver); 2149940b61afSAnirudh Venkataramanan if (status) { 2150837f08fdSAnirudh Venkataramanan pr_err("failed to register pci driver, err %d\n", status); 2151940b61afSAnirudh Venkataramanan destroy_workqueue(ice_wq); 2152940b61afSAnirudh Venkataramanan } 2153837f08fdSAnirudh Venkataramanan 2154837f08fdSAnirudh Venkataramanan return status; 2155837f08fdSAnirudh Venkataramanan } 2156837f08fdSAnirudh Venkataramanan module_init(ice_module_init); 2157837f08fdSAnirudh Venkataramanan 2158837f08fdSAnirudh Venkataramanan /** 2159837f08fdSAnirudh Venkataramanan * ice_module_exit - Driver exit cleanup routine 2160837f08fdSAnirudh Venkataramanan * 2161837f08fdSAnirudh Venkataramanan * ice_module_exit is called just before the driver is removed 2162837f08fdSAnirudh Venkataramanan * from memory. 2163837f08fdSAnirudh Venkataramanan */ 2164837f08fdSAnirudh Venkataramanan static void __exit ice_module_exit(void) 2165837f08fdSAnirudh Venkataramanan { 2166837f08fdSAnirudh Venkataramanan pci_unregister_driver(&ice_driver); 2167940b61afSAnirudh Venkataramanan destroy_workqueue(ice_wq); 2168837f08fdSAnirudh Venkataramanan pr_info("module unloaded\n"); 2169837f08fdSAnirudh Venkataramanan } 2170837f08fdSAnirudh Venkataramanan module_exit(ice_module_exit); 21713a858ba3SAnirudh Venkataramanan 21723a858ba3SAnirudh Venkataramanan /** 2173e94d4478SAnirudh Venkataramanan * ice_set_mac_address - NDO callback to set mac address 2174e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 2175e94d4478SAnirudh Venkataramanan * @pi: pointer to an address structure 2176e94d4478SAnirudh Venkataramanan * 2177e94d4478SAnirudh Venkataramanan * Returns 0 on success, negative on failure 2178e94d4478SAnirudh Venkataramanan */ 2179e94d4478SAnirudh Venkataramanan static int ice_set_mac_address(struct net_device *netdev, void *pi) 2180e94d4478SAnirudh Venkataramanan { 2181e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2182e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2183e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2184e94d4478SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2185e94d4478SAnirudh Venkataramanan struct sockaddr *addr = pi; 2186e94d4478SAnirudh Venkataramanan enum ice_status status; 2187e94d4478SAnirudh Venkataramanan LIST_HEAD(a_mac_list); 2188e94d4478SAnirudh Venkataramanan LIST_HEAD(r_mac_list); 2189e94d4478SAnirudh Venkataramanan u8 flags = 0; 2190e94d4478SAnirudh Venkataramanan int err; 2191e94d4478SAnirudh Venkataramanan u8 *mac; 2192e94d4478SAnirudh Venkataramanan 2193e94d4478SAnirudh Venkataramanan mac = (u8 *)addr->sa_data; 2194e94d4478SAnirudh Venkataramanan 2195e94d4478SAnirudh Venkataramanan if (!is_valid_ether_addr(mac)) 2196e94d4478SAnirudh Venkataramanan return -EADDRNOTAVAIL; 2197e94d4478SAnirudh Venkataramanan 2198e94d4478SAnirudh Venkataramanan if (ether_addr_equal(netdev->dev_addr, mac)) { 2199e94d4478SAnirudh Venkataramanan netdev_warn(netdev, "already using mac %pM\n", mac); 2200e94d4478SAnirudh Venkataramanan return 0; 2201e94d4478SAnirudh Venkataramanan } 2202e94d4478SAnirudh Venkataramanan 2203e94d4478SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state) || 22045df7e45dSDave Ertman ice_is_reset_in_progress(pf->state)) { 2205e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. device not ready\n", 2206e94d4478SAnirudh Venkataramanan mac); 2207e94d4478SAnirudh Venkataramanan return -EBUSY; 2208e94d4478SAnirudh Venkataramanan } 2209e94d4478SAnirudh Venkataramanan 2210e94d4478SAnirudh Venkataramanan /* When we change the mac address we also have to change the mac address 2211e94d4478SAnirudh Venkataramanan * based filter rules that were created previously for the old mac 2212e94d4478SAnirudh Venkataramanan * address. So first, we remove the old filter rule using ice_remove_mac 2213e94d4478SAnirudh Venkataramanan * and then create a new filter rule using ice_add_mac. Note that for 2214e94d4478SAnirudh Venkataramanan * both these operations, we first need to form a "list" of mac 2215e94d4478SAnirudh Venkataramanan * addresses (even though in this case, we have only 1 mac address to be 2216e94d4478SAnirudh Venkataramanan * added/removed) and this done using ice_add_mac_to_list. Depending on 2217e94d4478SAnirudh Venkataramanan * the ensuing operation this "list" of mac addresses is either to be 2218e94d4478SAnirudh Venkataramanan * added or removed from the filter. 2219e94d4478SAnirudh Venkataramanan */ 2220e94d4478SAnirudh Venkataramanan err = ice_add_mac_to_list(vsi, &r_mac_list, netdev->dev_addr); 2221e94d4478SAnirudh Venkataramanan if (err) { 2222e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2223e94d4478SAnirudh Venkataramanan goto free_lists; 2224e94d4478SAnirudh Venkataramanan } 2225e94d4478SAnirudh Venkataramanan 2226e94d4478SAnirudh Venkataramanan status = ice_remove_mac(hw, &r_mac_list); 2227e94d4478SAnirudh Venkataramanan if (status) { 2228e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2229e94d4478SAnirudh Venkataramanan goto free_lists; 2230e94d4478SAnirudh Venkataramanan } 2231e94d4478SAnirudh Venkataramanan 2232e94d4478SAnirudh Venkataramanan err = ice_add_mac_to_list(vsi, &a_mac_list, mac); 2233e94d4478SAnirudh Venkataramanan if (err) { 2234e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2235e94d4478SAnirudh Venkataramanan goto free_lists; 2236e94d4478SAnirudh Venkataramanan } 2237e94d4478SAnirudh Venkataramanan 2238e94d4478SAnirudh Venkataramanan status = ice_add_mac(hw, &a_mac_list); 2239e94d4478SAnirudh Venkataramanan if (status) { 2240e94d4478SAnirudh Venkataramanan err = -EADDRNOTAVAIL; 2241e94d4478SAnirudh Venkataramanan goto free_lists; 2242e94d4478SAnirudh Venkataramanan } 2243e94d4478SAnirudh Venkataramanan 2244e94d4478SAnirudh Venkataramanan free_lists: 2245e94d4478SAnirudh Venkataramanan /* free list entries */ 2246e94d4478SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &r_mac_list); 2247e94d4478SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &a_mac_list); 2248e94d4478SAnirudh Venkataramanan 2249e94d4478SAnirudh Venkataramanan if (err) { 2250e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. filter update failed\n", 2251e94d4478SAnirudh Venkataramanan mac); 2252e94d4478SAnirudh Venkataramanan return err; 2253e94d4478SAnirudh Venkataramanan } 2254e94d4478SAnirudh Venkataramanan 2255e94d4478SAnirudh Venkataramanan /* change the netdev's mac address */ 2256e94d4478SAnirudh Venkataramanan memcpy(netdev->dev_addr, mac, netdev->addr_len); 2257e94d4478SAnirudh Venkataramanan netdev_dbg(vsi->netdev, "updated mac address to %pM\n", 2258e94d4478SAnirudh Venkataramanan netdev->dev_addr); 2259e94d4478SAnirudh Venkataramanan 2260e94d4478SAnirudh Venkataramanan /* write new mac address to the firmware */ 2261e94d4478SAnirudh Venkataramanan flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL; 2262e94d4478SAnirudh Venkataramanan status = ice_aq_manage_mac_write(hw, mac, flags, NULL); 2263e94d4478SAnirudh Venkataramanan if (status) { 2264e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't set mac %pM. write to firmware failed.\n", 2265e94d4478SAnirudh Venkataramanan mac); 2266e94d4478SAnirudh Venkataramanan } 2267e94d4478SAnirudh Venkataramanan return 0; 2268e94d4478SAnirudh Venkataramanan } 2269e94d4478SAnirudh Venkataramanan 2270e94d4478SAnirudh Venkataramanan /** 2271e94d4478SAnirudh Venkataramanan * ice_set_rx_mode - NDO callback to set the netdev filters 2272e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 2273e94d4478SAnirudh Venkataramanan */ 2274e94d4478SAnirudh Venkataramanan static void ice_set_rx_mode(struct net_device *netdev) 2275e94d4478SAnirudh Venkataramanan { 2276e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2277e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2278e94d4478SAnirudh Venkataramanan 2279e94d4478SAnirudh Venkataramanan if (!vsi) 2280e94d4478SAnirudh Venkataramanan return; 2281e94d4478SAnirudh Venkataramanan 2282e94d4478SAnirudh Venkataramanan /* Set the flags to synchronize filters 2283e94d4478SAnirudh Venkataramanan * ndo_set_rx_mode may be triggered even without a change in netdev 2284e94d4478SAnirudh Venkataramanan * flags 2285e94d4478SAnirudh Venkataramanan */ 2286e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags); 2287e94d4478SAnirudh Venkataramanan set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags); 2288e94d4478SAnirudh Venkataramanan set_bit(ICE_FLAG_FLTR_SYNC, vsi->back->flags); 2289e94d4478SAnirudh Venkataramanan 2290e94d4478SAnirudh Venkataramanan /* schedule our worker thread which will take care of 2291e94d4478SAnirudh Venkataramanan * applying the new filter changes 2292e94d4478SAnirudh Venkataramanan */ 2293e94d4478SAnirudh Venkataramanan ice_service_task_schedule(vsi->back); 2294e94d4478SAnirudh Venkataramanan } 2295e94d4478SAnirudh Venkataramanan 2296e94d4478SAnirudh Venkataramanan /** 2297e94d4478SAnirudh Venkataramanan * ice_fdb_add - add an entry to the hardware database 2298e94d4478SAnirudh Venkataramanan * @ndm: the input from the stack 2299e94d4478SAnirudh Venkataramanan * @tb: pointer to array of nladdr (unused) 2300e94d4478SAnirudh Venkataramanan * @dev: the net device pointer 2301e94d4478SAnirudh Venkataramanan * @addr: the MAC address entry being added 2302e94d4478SAnirudh Venkataramanan * @vid: VLAN id 2303e94d4478SAnirudh Venkataramanan * @flags: instructions from stack about fdb operation 2304e94d4478SAnirudh Venkataramanan */ 2305e94d4478SAnirudh Venkataramanan static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[], 2306e94d4478SAnirudh Venkataramanan struct net_device *dev, const unsigned char *addr, 2307e94d4478SAnirudh Venkataramanan u16 vid, u16 flags) 2308e94d4478SAnirudh Venkataramanan { 2309e94d4478SAnirudh Venkataramanan int err; 2310e94d4478SAnirudh Venkataramanan 2311e94d4478SAnirudh Venkataramanan if (vid) { 2312e94d4478SAnirudh Venkataramanan netdev_err(dev, "VLANs aren't supported yet for dev_uc|mc_add()\n"); 2313e94d4478SAnirudh Venkataramanan return -EINVAL; 2314e94d4478SAnirudh Venkataramanan } 2315e94d4478SAnirudh Venkataramanan if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { 2316e94d4478SAnirudh Venkataramanan netdev_err(dev, "FDB only supports static addresses\n"); 2317e94d4478SAnirudh Venkataramanan return -EINVAL; 2318e94d4478SAnirudh Venkataramanan } 2319e94d4478SAnirudh Venkataramanan 2320e94d4478SAnirudh Venkataramanan if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) 2321e94d4478SAnirudh Venkataramanan err = dev_uc_add_excl(dev, addr); 2322e94d4478SAnirudh Venkataramanan else if (is_multicast_ether_addr(addr)) 2323e94d4478SAnirudh Venkataramanan err = dev_mc_add_excl(dev, addr); 2324e94d4478SAnirudh Venkataramanan else 2325e94d4478SAnirudh Venkataramanan err = -EINVAL; 2326e94d4478SAnirudh Venkataramanan 2327e94d4478SAnirudh Venkataramanan /* Only return duplicate errors if NLM_F_EXCL is set */ 2328e94d4478SAnirudh Venkataramanan if (err == -EEXIST && !(flags & NLM_F_EXCL)) 2329e94d4478SAnirudh Venkataramanan err = 0; 2330e94d4478SAnirudh Venkataramanan 2331e94d4478SAnirudh Venkataramanan return err; 2332e94d4478SAnirudh Venkataramanan } 2333e94d4478SAnirudh Venkataramanan 2334e94d4478SAnirudh Venkataramanan /** 2335e94d4478SAnirudh Venkataramanan * ice_fdb_del - delete an entry from the hardware database 2336e94d4478SAnirudh Venkataramanan * @ndm: the input from the stack 2337e94d4478SAnirudh Venkataramanan * @tb: pointer to array of nladdr (unused) 2338e94d4478SAnirudh Venkataramanan * @dev: the net device pointer 2339e94d4478SAnirudh Venkataramanan * @addr: the MAC address entry being added 2340e94d4478SAnirudh Venkataramanan * @vid: VLAN id 2341e94d4478SAnirudh Venkataramanan */ 2342e94d4478SAnirudh Venkataramanan static int ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[], 2343e94d4478SAnirudh Venkataramanan struct net_device *dev, const unsigned char *addr, 2344e94d4478SAnirudh Venkataramanan __always_unused u16 vid) 2345e94d4478SAnirudh Venkataramanan { 2346e94d4478SAnirudh Venkataramanan int err; 2347e94d4478SAnirudh Venkataramanan 2348e94d4478SAnirudh Venkataramanan if (ndm->ndm_state & NUD_PERMANENT) { 2349e94d4478SAnirudh Venkataramanan netdev_err(dev, "FDB only supports static addresses\n"); 2350e94d4478SAnirudh Venkataramanan return -EINVAL; 2351e94d4478SAnirudh Venkataramanan } 2352e94d4478SAnirudh Venkataramanan 2353e94d4478SAnirudh Venkataramanan if (is_unicast_ether_addr(addr)) 2354e94d4478SAnirudh Venkataramanan err = dev_uc_del(dev, addr); 2355e94d4478SAnirudh Venkataramanan else if (is_multicast_ether_addr(addr)) 2356e94d4478SAnirudh Venkataramanan err = dev_mc_del(dev, addr); 2357e94d4478SAnirudh Venkataramanan else 2358e94d4478SAnirudh Venkataramanan err = -EINVAL; 2359e94d4478SAnirudh Venkataramanan 2360e94d4478SAnirudh Venkataramanan return err; 2361e94d4478SAnirudh Venkataramanan } 2362e94d4478SAnirudh Venkataramanan 2363e94d4478SAnirudh Venkataramanan /** 2364d76a60baSAnirudh Venkataramanan * ice_set_features - set the netdev feature flags 2365d76a60baSAnirudh Venkataramanan * @netdev: ptr to the netdev being adjusted 2366d76a60baSAnirudh Venkataramanan * @features: the feature set that the stack is suggesting 2367d76a60baSAnirudh Venkataramanan */ 2368d76a60baSAnirudh Venkataramanan static int ice_set_features(struct net_device *netdev, 2369d76a60baSAnirudh Venkataramanan netdev_features_t features) 2370d76a60baSAnirudh Venkataramanan { 2371d76a60baSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2372d76a60baSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2373d76a60baSAnirudh Venkataramanan int ret = 0; 2374d76a60baSAnirudh Venkataramanan 2375d76a60baSAnirudh Venkataramanan if ((features & NETIF_F_HW_VLAN_CTAG_RX) && 2376d76a60baSAnirudh Venkataramanan !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) 2377d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, true); 2378d76a60baSAnirudh Venkataramanan else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && 2379d76a60baSAnirudh Venkataramanan (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) 2380d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, false); 2381d76a60baSAnirudh Venkataramanan else if ((features & NETIF_F_HW_VLAN_CTAG_TX) && 2382d76a60baSAnirudh Venkataramanan !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) 2383d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2384d76a60baSAnirudh Venkataramanan else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) && 2385d76a60baSAnirudh Venkataramanan (netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) 2386d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2387d76a60baSAnirudh Venkataramanan 2388d76a60baSAnirudh Venkataramanan return ret; 2389d76a60baSAnirudh Venkataramanan } 2390d76a60baSAnirudh Venkataramanan 2391d76a60baSAnirudh Venkataramanan /** 2392d76a60baSAnirudh Venkataramanan * ice_vsi_vlan_setup - Setup vlan offload properties on a VSI 2393d76a60baSAnirudh Venkataramanan * @vsi: VSI to setup vlan properties for 2394d76a60baSAnirudh Venkataramanan */ 2395d76a60baSAnirudh Venkataramanan static int ice_vsi_vlan_setup(struct ice_vsi *vsi) 2396d76a60baSAnirudh Venkataramanan { 2397d76a60baSAnirudh Venkataramanan int ret = 0; 2398d76a60baSAnirudh Venkataramanan 2399d76a60baSAnirudh Venkataramanan if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) 2400d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_stripping(vsi, true); 2401d76a60baSAnirudh Venkataramanan if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX) 2402d76a60baSAnirudh Venkataramanan ret = ice_vsi_manage_vlan_insertion(vsi); 2403d76a60baSAnirudh Venkataramanan 2404d76a60baSAnirudh Venkataramanan return ret; 2405d76a60baSAnirudh Venkataramanan } 2406d76a60baSAnirudh Venkataramanan 2407d76a60baSAnirudh Venkataramanan /** 2408d76a60baSAnirudh Venkataramanan * ice_restore_vlan - Reinstate VLANs when vsi/netdev comes back up 2409d76a60baSAnirudh Venkataramanan * @vsi: the VSI being brought back up 2410d76a60baSAnirudh Venkataramanan */ 2411d76a60baSAnirudh Venkataramanan static int ice_restore_vlan(struct ice_vsi *vsi) 2412d76a60baSAnirudh Venkataramanan { 2413d76a60baSAnirudh Venkataramanan int err; 2414d76a60baSAnirudh Venkataramanan u16 vid; 2415d76a60baSAnirudh Venkataramanan 2416d76a60baSAnirudh Venkataramanan if (!vsi->netdev) 2417d76a60baSAnirudh Venkataramanan return -EINVAL; 2418d76a60baSAnirudh Venkataramanan 2419d76a60baSAnirudh Venkataramanan err = ice_vsi_vlan_setup(vsi); 2420d76a60baSAnirudh Venkataramanan if (err) 2421d76a60baSAnirudh Venkataramanan return err; 2422d76a60baSAnirudh Venkataramanan 2423d76a60baSAnirudh Venkataramanan for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID) { 2424d76a60baSAnirudh Venkataramanan err = ice_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q), vid); 2425d76a60baSAnirudh Venkataramanan if (err) 2426d76a60baSAnirudh Venkataramanan break; 2427d76a60baSAnirudh Venkataramanan } 2428d76a60baSAnirudh Venkataramanan 2429d76a60baSAnirudh Venkataramanan return err; 2430d76a60baSAnirudh Venkataramanan } 2431d76a60baSAnirudh Venkataramanan 2432d76a60baSAnirudh Venkataramanan /** 2433cdedef59SAnirudh Venkataramanan * ice_vsi_cfg - Setup the VSI 2434cdedef59SAnirudh Venkataramanan * @vsi: the VSI being configured 2435cdedef59SAnirudh Venkataramanan * 2436cdedef59SAnirudh Venkataramanan * Return 0 on success and negative value on error 2437cdedef59SAnirudh Venkataramanan */ 2438cdedef59SAnirudh Venkataramanan static int ice_vsi_cfg(struct ice_vsi *vsi) 2439cdedef59SAnirudh Venkataramanan { 2440cdedef59SAnirudh Venkataramanan int err; 2441cdedef59SAnirudh Venkataramanan 2442c7f2c42bSAnirudh Venkataramanan if (vsi->netdev) { 2443e94d4478SAnirudh Venkataramanan ice_set_rx_mode(vsi->netdev); 2444d76a60baSAnirudh Venkataramanan err = ice_restore_vlan(vsi); 2445d76a60baSAnirudh Venkataramanan if (err) 2446d76a60baSAnirudh Venkataramanan return err; 2447c7f2c42bSAnirudh Venkataramanan } 2448d76a60baSAnirudh Venkataramanan 2449cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg_txqs(vsi); 2450cdedef59SAnirudh Venkataramanan if (!err) 2451cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg_rxqs(vsi); 2452cdedef59SAnirudh Venkataramanan 2453cdedef59SAnirudh Venkataramanan return err; 2454cdedef59SAnirudh Venkataramanan } 2455cdedef59SAnirudh Venkataramanan 2456cdedef59SAnirudh Venkataramanan /** 24572b245cb2SAnirudh Venkataramanan * ice_napi_enable_all - Enable NAPI for all q_vectors in the VSI 24582b245cb2SAnirudh Venkataramanan * @vsi: the VSI being configured 24592b245cb2SAnirudh Venkataramanan */ 24602b245cb2SAnirudh Venkataramanan static void ice_napi_enable_all(struct ice_vsi *vsi) 24612b245cb2SAnirudh Venkataramanan { 24622b245cb2SAnirudh Venkataramanan int q_idx; 24632b245cb2SAnirudh Venkataramanan 24642b245cb2SAnirudh Venkataramanan if (!vsi->netdev) 24652b245cb2SAnirudh Venkataramanan return; 24662b245cb2SAnirudh Venkataramanan 24672b245cb2SAnirudh Venkataramanan for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) 24682b245cb2SAnirudh Venkataramanan napi_enable(&vsi->q_vectors[q_idx]->napi); 24692b245cb2SAnirudh Venkataramanan } 24702b245cb2SAnirudh Venkataramanan 24712b245cb2SAnirudh Venkataramanan /** 2472cdedef59SAnirudh Venkataramanan * ice_up_complete - Finish the last steps of bringing up a connection 2473cdedef59SAnirudh Venkataramanan * @vsi: The VSI being configured 2474cdedef59SAnirudh Venkataramanan * 2475cdedef59SAnirudh Venkataramanan * Return 0 on success and negative value on error 2476cdedef59SAnirudh Venkataramanan */ 2477cdedef59SAnirudh Venkataramanan static int ice_up_complete(struct ice_vsi *vsi) 2478cdedef59SAnirudh Venkataramanan { 2479cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2480cdedef59SAnirudh Venkataramanan int err; 2481cdedef59SAnirudh Venkataramanan 2482cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 2483cdedef59SAnirudh Venkataramanan ice_vsi_cfg_msix(vsi); 2484cdedef59SAnirudh Venkataramanan else 2485cdedef59SAnirudh Venkataramanan return -ENOTSUPP; 2486cdedef59SAnirudh Venkataramanan 2487cdedef59SAnirudh Venkataramanan /* Enable only Rx rings, Tx rings were enabled by the FW when the 2488cdedef59SAnirudh Venkataramanan * Tx queue group list was configured and the context bits were 2489cdedef59SAnirudh Venkataramanan * programmed using ice_vsi_cfg_txqs 2490cdedef59SAnirudh Venkataramanan */ 2491cdedef59SAnirudh Venkataramanan err = ice_vsi_start_rx_rings(vsi); 2492cdedef59SAnirudh Venkataramanan if (err) 2493cdedef59SAnirudh Venkataramanan return err; 2494cdedef59SAnirudh Venkataramanan 2495cdedef59SAnirudh Venkataramanan clear_bit(__ICE_DOWN, vsi->state); 24962b245cb2SAnirudh Venkataramanan ice_napi_enable_all(vsi); 2497cdedef59SAnirudh Venkataramanan ice_vsi_ena_irq(vsi); 2498cdedef59SAnirudh Venkataramanan 2499cdedef59SAnirudh Venkataramanan if (vsi->port_info && 2500cdedef59SAnirudh Venkataramanan (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) && 2501cdedef59SAnirudh Venkataramanan vsi->netdev) { 2502cdedef59SAnirudh Venkataramanan ice_print_link_msg(vsi, true); 2503cdedef59SAnirudh Venkataramanan netif_tx_start_all_queues(vsi->netdev); 2504cdedef59SAnirudh Venkataramanan netif_carrier_on(vsi->netdev); 2505cdedef59SAnirudh Venkataramanan } 2506cdedef59SAnirudh Venkataramanan 2507cdedef59SAnirudh Venkataramanan ice_service_task_schedule(pf); 2508cdedef59SAnirudh Venkataramanan 2509cdedef59SAnirudh Venkataramanan return err; 2510cdedef59SAnirudh Venkataramanan } 2511cdedef59SAnirudh Venkataramanan 2512cdedef59SAnirudh Venkataramanan /** 2513fcea6f3dSAnirudh Venkataramanan * ice_up - Bring the connection back up after being down 2514fcea6f3dSAnirudh Venkataramanan * @vsi: VSI being configured 2515fcea6f3dSAnirudh Venkataramanan */ 2516fcea6f3dSAnirudh Venkataramanan int ice_up(struct ice_vsi *vsi) 2517fcea6f3dSAnirudh Venkataramanan { 2518fcea6f3dSAnirudh Venkataramanan int err; 2519fcea6f3dSAnirudh Venkataramanan 2520fcea6f3dSAnirudh Venkataramanan err = ice_vsi_cfg(vsi); 2521fcea6f3dSAnirudh Venkataramanan if (!err) 2522fcea6f3dSAnirudh Venkataramanan err = ice_up_complete(vsi); 2523fcea6f3dSAnirudh Venkataramanan 2524fcea6f3dSAnirudh Venkataramanan return err; 2525fcea6f3dSAnirudh Venkataramanan } 2526fcea6f3dSAnirudh Venkataramanan 2527fcea6f3dSAnirudh Venkataramanan /** 2528fcea6f3dSAnirudh Venkataramanan * ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring 2529fcea6f3dSAnirudh Venkataramanan * @ring: Tx or Rx ring to read stats from 2530fcea6f3dSAnirudh Venkataramanan * @pkts: packets stats counter 2531fcea6f3dSAnirudh Venkataramanan * @bytes: bytes stats counter 2532fcea6f3dSAnirudh Venkataramanan * 2533fcea6f3dSAnirudh Venkataramanan * This function fetches stats from the ring considering the atomic operations 2534fcea6f3dSAnirudh Venkataramanan * that needs to be performed to read u64 values in 32 bit machine. 2535fcea6f3dSAnirudh Venkataramanan */ 2536fcea6f3dSAnirudh Venkataramanan static void ice_fetch_u64_stats_per_ring(struct ice_ring *ring, u64 *pkts, 2537fcea6f3dSAnirudh Venkataramanan u64 *bytes) 2538fcea6f3dSAnirudh Venkataramanan { 2539fcea6f3dSAnirudh Venkataramanan unsigned int start; 2540fcea6f3dSAnirudh Venkataramanan *pkts = 0; 2541fcea6f3dSAnirudh Venkataramanan *bytes = 0; 2542fcea6f3dSAnirudh Venkataramanan 2543fcea6f3dSAnirudh Venkataramanan if (!ring) 2544fcea6f3dSAnirudh Venkataramanan return; 2545fcea6f3dSAnirudh Venkataramanan do { 2546fcea6f3dSAnirudh Venkataramanan start = u64_stats_fetch_begin_irq(&ring->syncp); 2547fcea6f3dSAnirudh Venkataramanan *pkts = ring->stats.pkts; 2548fcea6f3dSAnirudh Venkataramanan *bytes = ring->stats.bytes; 2549fcea6f3dSAnirudh Venkataramanan } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 2550fcea6f3dSAnirudh Venkataramanan } 2551fcea6f3dSAnirudh Venkataramanan 2552fcea6f3dSAnirudh Venkataramanan /** 2553fcea6f3dSAnirudh Venkataramanan * ice_update_vsi_ring_stats - Update VSI stats counters 2554fcea6f3dSAnirudh Venkataramanan * @vsi: the VSI to be updated 2555fcea6f3dSAnirudh Venkataramanan */ 2556fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) 2557fcea6f3dSAnirudh Venkataramanan { 2558fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats; 2559fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 2560fcea6f3dSAnirudh Venkataramanan u64 pkts, bytes; 2561fcea6f3dSAnirudh Venkataramanan int i; 2562fcea6f3dSAnirudh Venkataramanan 2563fcea6f3dSAnirudh Venkataramanan /* reset netdev stats */ 2564fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_packets = 0; 2565fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_bytes = 0; 2566fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_packets = 0; 2567fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_bytes = 0; 2568fcea6f3dSAnirudh Venkataramanan 2569fcea6f3dSAnirudh Venkataramanan /* reset non-netdev (extended) stats */ 2570fcea6f3dSAnirudh Venkataramanan vsi->tx_restart = 0; 2571fcea6f3dSAnirudh Venkataramanan vsi->tx_busy = 0; 2572fcea6f3dSAnirudh Venkataramanan vsi->tx_linearize = 0; 2573fcea6f3dSAnirudh Venkataramanan vsi->rx_buf_failed = 0; 2574fcea6f3dSAnirudh Venkataramanan vsi->rx_page_failed = 0; 2575fcea6f3dSAnirudh Venkataramanan 2576fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 2577fcea6f3dSAnirudh Venkataramanan 2578fcea6f3dSAnirudh Venkataramanan /* update Tx rings counters */ 2579fcea6f3dSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 2580fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[i]); 2581fcea6f3dSAnirudh Venkataramanan ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes); 2582fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_packets += pkts; 2583fcea6f3dSAnirudh Venkataramanan vsi_stats->tx_bytes += bytes; 2584fcea6f3dSAnirudh Venkataramanan vsi->tx_restart += ring->tx_stats.restart_q; 2585fcea6f3dSAnirudh Venkataramanan vsi->tx_busy += ring->tx_stats.tx_busy; 2586fcea6f3dSAnirudh Venkataramanan vsi->tx_linearize += ring->tx_stats.tx_linearize; 2587fcea6f3dSAnirudh Venkataramanan } 2588fcea6f3dSAnirudh Venkataramanan 2589fcea6f3dSAnirudh Venkataramanan /* update Rx rings counters */ 2590fcea6f3dSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 2591fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[i]); 2592fcea6f3dSAnirudh Venkataramanan ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes); 2593fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_packets += pkts; 2594fcea6f3dSAnirudh Venkataramanan vsi_stats->rx_bytes += bytes; 2595fcea6f3dSAnirudh Venkataramanan vsi->rx_buf_failed += ring->rx_stats.alloc_buf_failed; 2596fcea6f3dSAnirudh Venkataramanan vsi->rx_page_failed += ring->rx_stats.alloc_page_failed; 2597fcea6f3dSAnirudh Venkataramanan } 2598fcea6f3dSAnirudh Venkataramanan 2599fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 2600fcea6f3dSAnirudh Venkataramanan } 2601fcea6f3dSAnirudh Venkataramanan 2602fcea6f3dSAnirudh Venkataramanan /** 2603fcea6f3dSAnirudh Venkataramanan * ice_update_vsi_stats - Update VSI stats counters 2604fcea6f3dSAnirudh Venkataramanan * @vsi: the VSI to be updated 2605fcea6f3dSAnirudh Venkataramanan */ 2606fcea6f3dSAnirudh Venkataramanan static void ice_update_vsi_stats(struct ice_vsi *vsi) 2607fcea6f3dSAnirudh Venkataramanan { 2608fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *cur_ns = &vsi->net_stats; 2609fcea6f3dSAnirudh Venkataramanan struct ice_eth_stats *cur_es = &vsi->eth_stats; 2610fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2611fcea6f3dSAnirudh Venkataramanan 2612fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state) || 2613fcea6f3dSAnirudh Venkataramanan test_bit(__ICE_CFG_BUSY, pf->state)) 2614fcea6f3dSAnirudh Venkataramanan return; 2615fcea6f3dSAnirudh Venkataramanan 2616fcea6f3dSAnirudh Venkataramanan /* get stats as recorded by Tx/Rx rings */ 2617fcea6f3dSAnirudh Venkataramanan ice_update_vsi_ring_stats(vsi); 2618fcea6f3dSAnirudh Venkataramanan 2619fcea6f3dSAnirudh Venkataramanan /* get VSI stats as recorded by the hardware */ 2620fcea6f3dSAnirudh Venkataramanan ice_update_eth_stats(vsi); 2621fcea6f3dSAnirudh Venkataramanan 2622fcea6f3dSAnirudh Venkataramanan cur_ns->tx_errors = cur_es->tx_errors; 2623fcea6f3dSAnirudh Venkataramanan cur_ns->rx_dropped = cur_es->rx_discards; 2624fcea6f3dSAnirudh Venkataramanan cur_ns->tx_dropped = cur_es->tx_discards; 2625fcea6f3dSAnirudh Venkataramanan cur_ns->multicast = cur_es->rx_multicast; 2626fcea6f3dSAnirudh Venkataramanan 2627fcea6f3dSAnirudh Venkataramanan /* update some more netdev stats if this is main VSI */ 2628fcea6f3dSAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) { 2629fcea6f3dSAnirudh Venkataramanan cur_ns->rx_crc_errors = pf->stats.crc_errors; 2630fcea6f3dSAnirudh Venkataramanan cur_ns->rx_errors = pf->stats.crc_errors + 2631fcea6f3dSAnirudh Venkataramanan pf->stats.illegal_bytes; 2632fcea6f3dSAnirudh Venkataramanan cur_ns->rx_length_errors = pf->stats.rx_len_errors; 2633fcea6f3dSAnirudh Venkataramanan } 2634fcea6f3dSAnirudh Venkataramanan } 2635fcea6f3dSAnirudh Venkataramanan 2636fcea6f3dSAnirudh Venkataramanan /** 2637fcea6f3dSAnirudh Venkataramanan * ice_update_pf_stats - Update PF port stats counters 2638fcea6f3dSAnirudh Venkataramanan * @pf: PF whose stats needs to be updated 2639fcea6f3dSAnirudh Venkataramanan */ 2640fcea6f3dSAnirudh Venkataramanan static void ice_update_pf_stats(struct ice_pf *pf) 2641fcea6f3dSAnirudh Venkataramanan { 2642fcea6f3dSAnirudh Venkataramanan struct ice_hw_port_stats *prev_ps, *cur_ps; 2643fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2644fcea6f3dSAnirudh Venkataramanan u8 pf_id; 2645fcea6f3dSAnirudh Venkataramanan 2646fcea6f3dSAnirudh Venkataramanan prev_ps = &pf->stats_prev; 2647fcea6f3dSAnirudh Venkataramanan cur_ps = &pf->stats; 2648fcea6f3dSAnirudh Venkataramanan pf_id = hw->pf_id; 2649fcea6f3dSAnirudh Venkataramanan 2650fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_GORCH(pf_id), GLPRT_GORCL(pf_id), 2651fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_bytes, 2652fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_bytes); 2653fcea6f3dSAnirudh Venkataramanan 2654fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_UPRCH(pf_id), GLPRT_UPRCL(pf_id), 2655fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_unicast, 2656fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_unicast); 2657fcea6f3dSAnirudh Venkataramanan 2658fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_MPRCH(pf_id), GLPRT_MPRCL(pf_id), 2659fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_multicast, 2660fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_multicast); 2661fcea6f3dSAnirudh Venkataramanan 2662fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_BPRCH(pf_id), GLPRT_BPRCL(pf_id), 2663fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.rx_broadcast, 2664fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.rx_broadcast); 2665fcea6f3dSAnirudh Venkataramanan 2666fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_GOTCH(pf_id), GLPRT_GOTCL(pf_id), 2667fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_bytes, 2668fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_bytes); 2669fcea6f3dSAnirudh Venkataramanan 2670fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_UPTCH(pf_id), GLPRT_UPTCL(pf_id), 2671fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_unicast, 2672fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_unicast); 2673fcea6f3dSAnirudh Venkataramanan 2674fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_MPTCH(pf_id), GLPRT_MPTCL(pf_id), 2675fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_multicast, 2676fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_multicast); 2677fcea6f3dSAnirudh Venkataramanan 2678fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_BPTCH(pf_id), GLPRT_BPTCL(pf_id), 2679fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->eth.tx_broadcast, 2680fcea6f3dSAnirudh Venkataramanan &cur_ps->eth.tx_broadcast); 2681fcea6f3dSAnirudh Venkataramanan 2682fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_TDOLD(pf_id), pf->stat_prev_loaded, 2683fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_dropped_link_down, 2684fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_dropped_link_down); 2685fcea6f3dSAnirudh Venkataramanan 2686fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC64H(pf_id), GLPRT_PRC64L(pf_id), 2687fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_64, 2688fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_64); 2689fcea6f3dSAnirudh Venkataramanan 2690fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC127H(pf_id), GLPRT_PRC127L(pf_id), 2691fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_127, 2692fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_127); 2693fcea6f3dSAnirudh Venkataramanan 2694fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC255H(pf_id), GLPRT_PRC255L(pf_id), 2695fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_255, 2696fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_255); 2697fcea6f3dSAnirudh Venkataramanan 2698fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC511H(pf_id), GLPRT_PRC511L(pf_id), 2699fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->rx_size_511, 2700fcea6f3dSAnirudh Venkataramanan &cur_ps->rx_size_511); 2701fcea6f3dSAnirudh Venkataramanan 2702fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC1023H(pf_id), 2703fcea6f3dSAnirudh Venkataramanan GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded, 2704fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_1023, &cur_ps->rx_size_1023); 2705fcea6f3dSAnirudh Venkataramanan 2706fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC1522H(pf_id), 2707fcea6f3dSAnirudh Venkataramanan GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded, 2708fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_1522, &cur_ps->rx_size_1522); 2709fcea6f3dSAnirudh Venkataramanan 2710fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PRC9522H(pf_id), 2711fcea6f3dSAnirudh Venkataramanan GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded, 2712fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_size_big, &cur_ps->rx_size_big); 2713fcea6f3dSAnirudh Venkataramanan 2714fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC64H(pf_id), GLPRT_PTC64L(pf_id), 2715fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_64, 2716fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_64); 2717fcea6f3dSAnirudh Venkataramanan 2718fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC127H(pf_id), GLPRT_PTC127L(pf_id), 2719fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_127, 2720fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_127); 2721fcea6f3dSAnirudh Venkataramanan 2722fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC255H(pf_id), GLPRT_PTC255L(pf_id), 2723fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_255, 2724fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_255); 2725fcea6f3dSAnirudh Venkataramanan 2726fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC511H(pf_id), GLPRT_PTC511L(pf_id), 2727fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded, &prev_ps->tx_size_511, 2728fcea6f3dSAnirudh Venkataramanan &cur_ps->tx_size_511); 2729fcea6f3dSAnirudh Venkataramanan 2730fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC1023H(pf_id), 2731fcea6f3dSAnirudh Venkataramanan GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded, 2732fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_1023, &cur_ps->tx_size_1023); 2733fcea6f3dSAnirudh Venkataramanan 2734fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC1522H(pf_id), 2735fcea6f3dSAnirudh Venkataramanan GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded, 2736fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_1522, &cur_ps->tx_size_1522); 2737fcea6f3dSAnirudh Venkataramanan 2738fcea6f3dSAnirudh Venkataramanan ice_stat_update40(hw, GLPRT_PTC9522H(pf_id), 2739fcea6f3dSAnirudh Venkataramanan GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded, 2740fcea6f3dSAnirudh Venkataramanan &prev_ps->tx_size_big, &cur_ps->tx_size_big); 2741fcea6f3dSAnirudh Venkataramanan 2742fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXONRXC(pf_id), pf->stat_prev_loaded, 2743fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xon_rx, &cur_ps->link_xon_rx); 2744fcea6f3dSAnirudh Venkataramanan 2745fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXOFFRXC(pf_id), pf->stat_prev_loaded, 2746fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xoff_rx, &cur_ps->link_xoff_rx); 2747fcea6f3dSAnirudh Venkataramanan 2748fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXONTXC(pf_id), pf->stat_prev_loaded, 2749fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xon_tx, &cur_ps->link_xon_tx); 2750fcea6f3dSAnirudh Venkataramanan 2751fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_LXOFFTXC(pf_id), pf->stat_prev_loaded, 2752fcea6f3dSAnirudh Venkataramanan &prev_ps->link_xoff_tx, &cur_ps->link_xoff_tx); 2753fcea6f3dSAnirudh Venkataramanan 2754fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_CRCERRS(pf_id), pf->stat_prev_loaded, 2755fcea6f3dSAnirudh Venkataramanan &prev_ps->crc_errors, &cur_ps->crc_errors); 2756fcea6f3dSAnirudh Venkataramanan 2757fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_ILLERRC(pf_id), pf->stat_prev_loaded, 2758fcea6f3dSAnirudh Venkataramanan &prev_ps->illegal_bytes, &cur_ps->illegal_bytes); 2759fcea6f3dSAnirudh Venkataramanan 2760fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_MLFC(pf_id), pf->stat_prev_loaded, 2761fcea6f3dSAnirudh Venkataramanan &prev_ps->mac_local_faults, 2762fcea6f3dSAnirudh Venkataramanan &cur_ps->mac_local_faults); 2763fcea6f3dSAnirudh Venkataramanan 2764fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_MRFC(pf_id), pf->stat_prev_loaded, 2765fcea6f3dSAnirudh Venkataramanan &prev_ps->mac_remote_faults, 2766fcea6f3dSAnirudh Venkataramanan &cur_ps->mac_remote_faults); 2767fcea6f3dSAnirudh Venkataramanan 2768fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RLEC(pf_id), pf->stat_prev_loaded, 2769fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_len_errors, &cur_ps->rx_len_errors); 2770fcea6f3dSAnirudh Venkataramanan 2771fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RUC(pf_id), pf->stat_prev_loaded, 2772fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_undersize, &cur_ps->rx_undersize); 2773fcea6f3dSAnirudh Venkataramanan 2774fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RFC(pf_id), pf->stat_prev_loaded, 2775fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_fragments, &cur_ps->rx_fragments); 2776fcea6f3dSAnirudh Venkataramanan 2777fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_ROC(pf_id), pf->stat_prev_loaded, 2778fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_oversize, &cur_ps->rx_oversize); 2779fcea6f3dSAnirudh Venkataramanan 2780fcea6f3dSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RJC(pf_id), pf->stat_prev_loaded, 2781fcea6f3dSAnirudh Venkataramanan &prev_ps->rx_jabber, &cur_ps->rx_jabber); 2782fcea6f3dSAnirudh Venkataramanan 2783fcea6f3dSAnirudh Venkataramanan pf->stat_prev_loaded = true; 2784fcea6f3dSAnirudh Venkataramanan } 2785fcea6f3dSAnirudh Venkataramanan 2786fcea6f3dSAnirudh Venkataramanan /** 2787fcea6f3dSAnirudh Venkataramanan * ice_get_stats64 - get statistics for network device structure 2788fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2789fcea6f3dSAnirudh Venkataramanan * @stats: main device statistics structure 2790fcea6f3dSAnirudh Venkataramanan */ 2791fcea6f3dSAnirudh Venkataramanan static 2792fcea6f3dSAnirudh Venkataramanan void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) 2793fcea6f3dSAnirudh Venkataramanan { 2794fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2795fcea6f3dSAnirudh Venkataramanan struct rtnl_link_stats64 *vsi_stats; 2796fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2797fcea6f3dSAnirudh Venkataramanan 2798fcea6f3dSAnirudh Venkataramanan vsi_stats = &vsi->net_stats; 2799fcea6f3dSAnirudh Venkataramanan 2800fcea6f3dSAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state) || !vsi->num_txq || !vsi->num_rxq) 2801fcea6f3dSAnirudh Venkataramanan return; 2802fcea6f3dSAnirudh Venkataramanan /* netdev packet/byte stats come from ring counter. These are obtained 2803fcea6f3dSAnirudh Venkataramanan * by summing up ring counters (done by ice_update_vsi_ring_stats). 2804fcea6f3dSAnirudh Venkataramanan */ 2805fcea6f3dSAnirudh Venkataramanan ice_update_vsi_ring_stats(vsi); 2806fcea6f3dSAnirudh Venkataramanan stats->tx_packets = vsi_stats->tx_packets; 2807fcea6f3dSAnirudh Venkataramanan stats->tx_bytes = vsi_stats->tx_bytes; 2808fcea6f3dSAnirudh Venkataramanan stats->rx_packets = vsi_stats->rx_packets; 2809fcea6f3dSAnirudh Venkataramanan stats->rx_bytes = vsi_stats->rx_bytes; 2810fcea6f3dSAnirudh Venkataramanan 2811fcea6f3dSAnirudh Venkataramanan /* The rest of the stats can be read from the hardware but instead we 2812fcea6f3dSAnirudh Venkataramanan * just return values that the watchdog task has already obtained from 2813fcea6f3dSAnirudh Venkataramanan * the hardware. 2814fcea6f3dSAnirudh Venkataramanan */ 2815fcea6f3dSAnirudh Venkataramanan stats->multicast = vsi_stats->multicast; 2816fcea6f3dSAnirudh Venkataramanan stats->tx_errors = vsi_stats->tx_errors; 2817fcea6f3dSAnirudh Venkataramanan stats->tx_dropped = vsi_stats->tx_dropped; 2818fcea6f3dSAnirudh Venkataramanan stats->rx_errors = vsi_stats->rx_errors; 2819fcea6f3dSAnirudh Venkataramanan stats->rx_dropped = vsi_stats->rx_dropped; 2820fcea6f3dSAnirudh Venkataramanan stats->rx_crc_errors = vsi_stats->rx_crc_errors; 2821fcea6f3dSAnirudh Venkataramanan stats->rx_length_errors = vsi_stats->rx_length_errors; 2822fcea6f3dSAnirudh Venkataramanan } 2823fcea6f3dSAnirudh Venkataramanan 2824fcea6f3dSAnirudh Venkataramanan /** 28252b245cb2SAnirudh Venkataramanan * ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI 28262b245cb2SAnirudh Venkataramanan * @vsi: VSI having NAPI disabled 28272b245cb2SAnirudh Venkataramanan */ 28282b245cb2SAnirudh Venkataramanan static void ice_napi_disable_all(struct ice_vsi *vsi) 28292b245cb2SAnirudh Venkataramanan { 28302b245cb2SAnirudh Venkataramanan int q_idx; 28312b245cb2SAnirudh Venkataramanan 28322b245cb2SAnirudh Venkataramanan if (!vsi->netdev) 28332b245cb2SAnirudh Venkataramanan return; 28342b245cb2SAnirudh Venkataramanan 28352b245cb2SAnirudh Venkataramanan for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) 28362b245cb2SAnirudh Venkataramanan napi_disable(&vsi->q_vectors[q_idx]->napi); 28372b245cb2SAnirudh Venkataramanan } 28382b245cb2SAnirudh Venkataramanan 28392b245cb2SAnirudh Venkataramanan /** 2840cdedef59SAnirudh Venkataramanan * ice_down - Shutdown the connection 2841cdedef59SAnirudh Venkataramanan * @vsi: The VSI being stopped 2842cdedef59SAnirudh Venkataramanan */ 2843fcea6f3dSAnirudh Venkataramanan int ice_down(struct ice_vsi *vsi) 2844cdedef59SAnirudh Venkataramanan { 284572adf242SAnirudh Venkataramanan int i, tx_err, rx_err; 2846cdedef59SAnirudh Venkataramanan 2847cdedef59SAnirudh Venkataramanan /* Caller of this function is expected to set the 2848cdedef59SAnirudh Venkataramanan * vsi->state __ICE_DOWN bit 2849cdedef59SAnirudh Venkataramanan */ 2850cdedef59SAnirudh Venkataramanan if (vsi->netdev) { 2851cdedef59SAnirudh Venkataramanan netif_carrier_off(vsi->netdev); 2852cdedef59SAnirudh Venkataramanan netif_tx_disable(vsi->netdev); 2853cdedef59SAnirudh Venkataramanan } 2854cdedef59SAnirudh Venkataramanan 2855cdedef59SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 285672adf242SAnirudh Venkataramanan tx_err = ice_vsi_stop_tx_rings(vsi); 285772adf242SAnirudh Venkataramanan if (tx_err) 285872adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 285972adf242SAnirudh Venkataramanan "Failed stop Tx rings, VSI %d error %d\n", 286072adf242SAnirudh Venkataramanan vsi->vsi_num, tx_err); 286172adf242SAnirudh Venkataramanan 286272adf242SAnirudh Venkataramanan rx_err = ice_vsi_stop_rx_rings(vsi); 286372adf242SAnirudh Venkataramanan if (rx_err) 286472adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 286572adf242SAnirudh Venkataramanan "Failed stop Rx rings, VSI %d error %d\n", 286672adf242SAnirudh Venkataramanan vsi->vsi_num, rx_err); 286772adf242SAnirudh Venkataramanan 28682b245cb2SAnirudh Venkataramanan ice_napi_disable_all(vsi); 2869cdedef59SAnirudh Venkataramanan 2870cdedef59SAnirudh Venkataramanan ice_for_each_txq(vsi, i) 2871cdedef59SAnirudh Venkataramanan ice_clean_tx_ring(vsi->tx_rings[i]); 2872cdedef59SAnirudh Venkataramanan 2873cdedef59SAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 2874cdedef59SAnirudh Venkataramanan ice_clean_rx_ring(vsi->rx_rings[i]); 2875cdedef59SAnirudh Venkataramanan 287672adf242SAnirudh Venkataramanan if (tx_err || rx_err) { 287772adf242SAnirudh Venkataramanan netdev_err(vsi->netdev, 287872adf242SAnirudh Venkataramanan "Failed to close VSI 0x%04X on switch 0x%04X\n", 2879cdedef59SAnirudh Venkataramanan vsi->vsi_num, vsi->vsw->sw_id); 288072adf242SAnirudh Venkataramanan return -EIO; 288172adf242SAnirudh Venkataramanan } 288272adf242SAnirudh Venkataramanan 288372adf242SAnirudh Venkataramanan return 0; 2884cdedef59SAnirudh Venkataramanan } 2885cdedef59SAnirudh Venkataramanan 2886cdedef59SAnirudh Venkataramanan /** 2887cdedef59SAnirudh Venkataramanan * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources 2888cdedef59SAnirudh Venkataramanan * @vsi: VSI having resources allocated 2889cdedef59SAnirudh Venkataramanan * 2890cdedef59SAnirudh Venkataramanan * Return 0 on success, negative on failure 2891cdedef59SAnirudh Venkataramanan */ 2892cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi) 2893cdedef59SAnirudh Venkataramanan { 2894dab0588fSJesse Brandeburg int i, err = 0; 2895cdedef59SAnirudh Venkataramanan 2896cdedef59SAnirudh Venkataramanan if (!vsi->num_txq) { 2897cdedef59SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Tx queues\n", 2898cdedef59SAnirudh Venkataramanan vsi->vsi_num); 2899cdedef59SAnirudh Venkataramanan return -EINVAL; 2900cdedef59SAnirudh Venkataramanan } 2901cdedef59SAnirudh Venkataramanan 2902cdedef59SAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 290372adf242SAnirudh Venkataramanan vsi->tx_rings[i]->netdev = vsi->netdev; 2904cdedef59SAnirudh Venkataramanan err = ice_setup_tx_ring(vsi->tx_rings[i]); 2905cdedef59SAnirudh Venkataramanan if (err) 2906cdedef59SAnirudh Venkataramanan break; 2907cdedef59SAnirudh Venkataramanan } 2908cdedef59SAnirudh Venkataramanan 2909cdedef59SAnirudh Venkataramanan return err; 2910cdedef59SAnirudh Venkataramanan } 2911cdedef59SAnirudh Venkataramanan 2912cdedef59SAnirudh Venkataramanan /** 2913cdedef59SAnirudh Venkataramanan * ice_vsi_setup_rx_rings - Allocate VSI Rx queue resources 2914cdedef59SAnirudh Venkataramanan * @vsi: VSI having resources allocated 2915cdedef59SAnirudh Venkataramanan * 2916cdedef59SAnirudh Venkataramanan * Return 0 on success, negative on failure 2917cdedef59SAnirudh Venkataramanan */ 2918cdedef59SAnirudh Venkataramanan static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi) 2919cdedef59SAnirudh Venkataramanan { 2920dab0588fSJesse Brandeburg int i, err = 0; 2921cdedef59SAnirudh Venkataramanan 2922cdedef59SAnirudh Venkataramanan if (!vsi->num_rxq) { 2923cdedef59SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Rx queues\n", 2924cdedef59SAnirudh Venkataramanan vsi->vsi_num); 2925cdedef59SAnirudh Venkataramanan return -EINVAL; 2926cdedef59SAnirudh Venkataramanan } 2927cdedef59SAnirudh Venkataramanan 2928cdedef59SAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 292972adf242SAnirudh Venkataramanan vsi->rx_rings[i]->netdev = vsi->netdev; 2930cdedef59SAnirudh Venkataramanan err = ice_setup_rx_ring(vsi->rx_rings[i]); 2931cdedef59SAnirudh Venkataramanan if (err) 2932cdedef59SAnirudh Venkataramanan break; 2933cdedef59SAnirudh Venkataramanan } 2934cdedef59SAnirudh Venkataramanan 2935cdedef59SAnirudh Venkataramanan return err; 2936cdedef59SAnirudh Venkataramanan } 2937cdedef59SAnirudh Venkataramanan 2938cdedef59SAnirudh Venkataramanan /** 2939cdedef59SAnirudh Venkataramanan * ice_vsi_req_irq - Request IRQ from the OS 2940cdedef59SAnirudh Venkataramanan * @vsi: The VSI IRQ is being requested for 2941cdedef59SAnirudh Venkataramanan * @basename: name for the vector 2942cdedef59SAnirudh Venkataramanan * 2943cdedef59SAnirudh Venkataramanan * Return 0 on success and a negative value on error 2944cdedef59SAnirudh Venkataramanan */ 2945cdedef59SAnirudh Venkataramanan static int ice_vsi_req_irq(struct ice_vsi *vsi, char *basename) 2946cdedef59SAnirudh Venkataramanan { 2947cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2948cdedef59SAnirudh Venkataramanan int err = -EINVAL; 2949cdedef59SAnirudh Venkataramanan 2950cdedef59SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 2951cdedef59SAnirudh Venkataramanan err = ice_vsi_req_irq_msix(vsi, basename); 2952cdedef59SAnirudh Venkataramanan 2953cdedef59SAnirudh Venkataramanan return err; 2954cdedef59SAnirudh Venkataramanan } 2955cdedef59SAnirudh Venkataramanan 2956cdedef59SAnirudh Venkataramanan /** 2957cdedef59SAnirudh Venkataramanan * ice_vsi_open - Called when a network interface is made active 2958cdedef59SAnirudh Venkataramanan * @vsi: the VSI to open 2959cdedef59SAnirudh Venkataramanan * 2960cdedef59SAnirudh Venkataramanan * Initialization of the VSI 2961cdedef59SAnirudh Venkataramanan * 2962cdedef59SAnirudh Venkataramanan * Returns 0 on success, negative value on error 2963cdedef59SAnirudh Venkataramanan */ 2964cdedef59SAnirudh Venkataramanan static int ice_vsi_open(struct ice_vsi *vsi) 2965cdedef59SAnirudh Venkataramanan { 2966cdedef59SAnirudh Venkataramanan char int_name[ICE_INT_NAME_STR_LEN]; 2967cdedef59SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2968cdedef59SAnirudh Venkataramanan int err; 2969cdedef59SAnirudh Venkataramanan 2970cdedef59SAnirudh Venkataramanan /* allocate descriptors */ 2971cdedef59SAnirudh Venkataramanan err = ice_vsi_setup_tx_rings(vsi); 2972cdedef59SAnirudh Venkataramanan if (err) 2973cdedef59SAnirudh Venkataramanan goto err_setup_tx; 2974cdedef59SAnirudh Venkataramanan 2975cdedef59SAnirudh Venkataramanan err = ice_vsi_setup_rx_rings(vsi); 2976cdedef59SAnirudh Venkataramanan if (err) 2977cdedef59SAnirudh Venkataramanan goto err_setup_rx; 2978cdedef59SAnirudh Venkataramanan 2979cdedef59SAnirudh Venkataramanan err = ice_vsi_cfg(vsi); 2980cdedef59SAnirudh Venkataramanan if (err) 2981cdedef59SAnirudh Venkataramanan goto err_setup_rx; 2982cdedef59SAnirudh Venkataramanan 2983cdedef59SAnirudh Venkataramanan snprintf(int_name, sizeof(int_name) - 1, "%s-%s", 2984cdedef59SAnirudh Venkataramanan dev_driver_string(&pf->pdev->dev), vsi->netdev->name); 2985cdedef59SAnirudh Venkataramanan err = ice_vsi_req_irq(vsi, int_name); 2986cdedef59SAnirudh Venkataramanan if (err) 2987cdedef59SAnirudh Venkataramanan goto err_setup_rx; 2988cdedef59SAnirudh Venkataramanan 2989cdedef59SAnirudh Venkataramanan /* Notify the stack of the actual queue counts. */ 2990cdedef59SAnirudh Venkataramanan err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq); 2991cdedef59SAnirudh Venkataramanan if (err) 2992cdedef59SAnirudh Venkataramanan goto err_set_qs; 2993cdedef59SAnirudh Venkataramanan 2994cdedef59SAnirudh Venkataramanan err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq); 2995cdedef59SAnirudh Venkataramanan if (err) 2996cdedef59SAnirudh Venkataramanan goto err_set_qs; 2997cdedef59SAnirudh Venkataramanan 2998cdedef59SAnirudh Venkataramanan err = ice_up_complete(vsi); 2999cdedef59SAnirudh Venkataramanan if (err) 3000cdedef59SAnirudh Venkataramanan goto err_up_complete; 3001cdedef59SAnirudh Venkataramanan 3002cdedef59SAnirudh Venkataramanan return 0; 3003cdedef59SAnirudh Venkataramanan 3004cdedef59SAnirudh Venkataramanan err_up_complete: 3005cdedef59SAnirudh Venkataramanan ice_down(vsi); 3006cdedef59SAnirudh Venkataramanan err_set_qs: 3007cdedef59SAnirudh Venkataramanan ice_vsi_free_irq(vsi); 3008cdedef59SAnirudh Venkataramanan err_setup_rx: 3009cdedef59SAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 3010cdedef59SAnirudh Venkataramanan err_setup_tx: 3011cdedef59SAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 3012cdedef59SAnirudh Venkataramanan 3013cdedef59SAnirudh Venkataramanan return err; 3014cdedef59SAnirudh Venkataramanan } 3015cdedef59SAnirudh Venkataramanan 3016cdedef59SAnirudh Venkataramanan /** 30170f9d5027SAnirudh Venkataramanan * ice_vsi_release_all - Delete all VSIs 30180f9d5027SAnirudh Venkataramanan * @pf: PF from which all VSIs are being removed 30190f9d5027SAnirudh Venkataramanan */ 30200f9d5027SAnirudh Venkataramanan static void ice_vsi_release_all(struct ice_pf *pf) 30210f9d5027SAnirudh Venkataramanan { 30220f9d5027SAnirudh Venkataramanan int err, i; 30230f9d5027SAnirudh Venkataramanan 30240f9d5027SAnirudh Venkataramanan if (!pf->vsi) 30250f9d5027SAnirudh Venkataramanan return; 30260f9d5027SAnirudh Venkataramanan 30270f9d5027SAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) { 30280f9d5027SAnirudh Venkataramanan if (!pf->vsi[i]) 30290f9d5027SAnirudh Venkataramanan continue; 30300f9d5027SAnirudh Venkataramanan 30310f9d5027SAnirudh Venkataramanan err = ice_vsi_release(pf->vsi[i]); 30320f9d5027SAnirudh Venkataramanan if (err) 30330f9d5027SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 30340f9d5027SAnirudh Venkataramanan "Failed to release pf->vsi[%d], err %d, vsi_num = %d\n", 30350f9d5027SAnirudh Venkataramanan i, err, pf->vsi[i]->vsi_num); 30360f9d5027SAnirudh Venkataramanan } 30370f9d5027SAnirudh Venkataramanan } 30380f9d5027SAnirudh Venkataramanan 30390f9d5027SAnirudh Venkataramanan /** 30400b28b702SAnirudh Venkataramanan * ice_dis_vsi - pause a VSI 30410b28b702SAnirudh Venkataramanan * @vsi: the VSI being paused 30420b28b702SAnirudh Venkataramanan */ 30430b28b702SAnirudh Venkataramanan static void ice_dis_vsi(struct ice_vsi *vsi) 30440b28b702SAnirudh Venkataramanan { 30450b28b702SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state)) 30460b28b702SAnirudh Venkataramanan return; 30470b28b702SAnirudh Venkataramanan 30480b28b702SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, vsi->state); 30490b28b702SAnirudh Venkataramanan 30500b28b702SAnirudh Venkataramanan if (vsi->netdev && netif_running(vsi->netdev) && 30510f9d5027SAnirudh Venkataramanan vsi->type == ICE_VSI_PF) { 30520f9d5027SAnirudh Venkataramanan rtnl_lock(); 30530b28b702SAnirudh Venkataramanan vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); 30540f9d5027SAnirudh Venkataramanan rtnl_unlock(); 30550f9d5027SAnirudh Venkataramanan } else { 30560b28b702SAnirudh Venkataramanan ice_vsi_close(vsi); 30570b28b702SAnirudh Venkataramanan } 30580f9d5027SAnirudh Venkataramanan } 30590b28b702SAnirudh Venkataramanan 30600b28b702SAnirudh Venkataramanan /** 30610b28b702SAnirudh Venkataramanan * ice_ena_vsi - resume a VSI 30620b28b702SAnirudh Venkataramanan * @vsi: the VSI being resume 30630b28b702SAnirudh Venkataramanan */ 30640f9d5027SAnirudh Venkataramanan static int ice_ena_vsi(struct ice_vsi *vsi) 30650b28b702SAnirudh Venkataramanan { 30660f9d5027SAnirudh Venkataramanan int err = 0; 30670b28b702SAnirudh Venkataramanan 30680f9d5027SAnirudh Venkataramanan if (test_and_clear_bit(__ICE_NEEDS_RESTART, vsi->state)) 30690f9d5027SAnirudh Venkataramanan if (vsi->netdev && netif_running(vsi->netdev)) { 30700f9d5027SAnirudh Venkataramanan rtnl_lock(); 30710f9d5027SAnirudh Venkataramanan err = vsi->netdev->netdev_ops->ndo_open(vsi->netdev); 30720f9d5027SAnirudh Venkataramanan rtnl_unlock(); 30730f9d5027SAnirudh Venkataramanan } 30740f9d5027SAnirudh Venkataramanan 30750f9d5027SAnirudh Venkataramanan return err; 30760b28b702SAnirudh Venkataramanan } 30770b28b702SAnirudh Venkataramanan 30780b28b702SAnirudh Venkataramanan /** 30790b28b702SAnirudh Venkataramanan * ice_pf_dis_all_vsi - Pause all VSIs on a PF 30800b28b702SAnirudh Venkataramanan * @pf: the PF 30810b28b702SAnirudh Venkataramanan */ 30820b28b702SAnirudh Venkataramanan static void ice_pf_dis_all_vsi(struct ice_pf *pf) 30830b28b702SAnirudh Venkataramanan { 30840b28b702SAnirudh Venkataramanan int v; 30850b28b702SAnirudh Venkataramanan 30860b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) 30870b28b702SAnirudh Venkataramanan if (pf->vsi[v]) 30880b28b702SAnirudh Venkataramanan ice_dis_vsi(pf->vsi[v]); 30890b28b702SAnirudh Venkataramanan } 30900b28b702SAnirudh Venkataramanan 30910b28b702SAnirudh Venkataramanan /** 30920b28b702SAnirudh Venkataramanan * ice_pf_ena_all_vsi - Resume all VSIs on a PF 30930b28b702SAnirudh Venkataramanan * @pf: the PF 30940b28b702SAnirudh Venkataramanan */ 30950f9d5027SAnirudh Venkataramanan static int ice_pf_ena_all_vsi(struct ice_pf *pf) 30960b28b702SAnirudh Venkataramanan { 30970b28b702SAnirudh Venkataramanan int v; 30980b28b702SAnirudh Venkataramanan 30990b28b702SAnirudh Venkataramanan ice_for_each_vsi(pf, v) 31000b28b702SAnirudh Venkataramanan if (pf->vsi[v]) 31010f9d5027SAnirudh Venkataramanan if (ice_ena_vsi(pf->vsi[v])) 31020f9d5027SAnirudh Venkataramanan return -EIO; 31030f9d5027SAnirudh Venkataramanan 31040f9d5027SAnirudh Venkataramanan return 0; 31050f9d5027SAnirudh Venkataramanan } 31060f9d5027SAnirudh Venkataramanan 31070f9d5027SAnirudh Venkataramanan /** 31080f9d5027SAnirudh Venkataramanan * ice_vsi_rebuild_all - rebuild all VSIs in pf 31090f9d5027SAnirudh Venkataramanan * @pf: the PF 31100f9d5027SAnirudh Venkataramanan */ 31110f9d5027SAnirudh Venkataramanan static int ice_vsi_rebuild_all(struct ice_pf *pf) 31120f9d5027SAnirudh Venkataramanan { 31130f9d5027SAnirudh Venkataramanan int i; 31140f9d5027SAnirudh Venkataramanan 31150f9d5027SAnirudh Venkataramanan /* loop through pf->vsi array and reinit the VSI if found */ 31160f9d5027SAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vsi; i++) { 31170f9d5027SAnirudh Venkataramanan int err; 31180f9d5027SAnirudh Venkataramanan 31190f9d5027SAnirudh Venkataramanan if (!pf->vsi[i]) 31200f9d5027SAnirudh Venkataramanan continue; 31210f9d5027SAnirudh Venkataramanan 31220f9d5027SAnirudh Venkataramanan err = ice_vsi_rebuild(pf->vsi[i]); 31230f9d5027SAnirudh Venkataramanan if (err) { 31240f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 31250f9d5027SAnirudh Venkataramanan "VSI at index %d rebuild failed\n", 31260f9d5027SAnirudh Venkataramanan pf->vsi[i]->idx); 31270f9d5027SAnirudh Venkataramanan return err; 31280f9d5027SAnirudh Venkataramanan } 31290f9d5027SAnirudh Venkataramanan 31300f9d5027SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 31310f9d5027SAnirudh Venkataramanan "VSI at index %d rebuilt. vsi_num = 0x%x\n", 31320f9d5027SAnirudh Venkataramanan pf->vsi[i]->idx, pf->vsi[i]->vsi_num); 31330f9d5027SAnirudh Venkataramanan } 31340f9d5027SAnirudh Venkataramanan 31350f9d5027SAnirudh Venkataramanan return 0; 31360b28b702SAnirudh Venkataramanan } 31370b28b702SAnirudh Venkataramanan 31380b28b702SAnirudh Venkataramanan /** 31390b28b702SAnirudh Venkataramanan * ice_rebuild - rebuild after reset 31400b28b702SAnirudh Venkataramanan * @pf: pf to rebuild 31410b28b702SAnirudh Venkataramanan */ 31420b28b702SAnirudh Venkataramanan static void ice_rebuild(struct ice_pf *pf) 31430b28b702SAnirudh Venkataramanan { 31440b28b702SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 31450b28b702SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 31460b28b702SAnirudh Venkataramanan enum ice_status ret; 31470b28b702SAnirudh Venkataramanan int err; 31480b28b702SAnirudh Venkataramanan 31490b28b702SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, pf->state)) 31500b28b702SAnirudh Venkataramanan goto clear_recovery; 31510b28b702SAnirudh Venkataramanan 31520b28b702SAnirudh Venkataramanan dev_dbg(dev, "rebuilding pf\n"); 31530b28b702SAnirudh Venkataramanan 31540b28b702SAnirudh Venkataramanan ret = ice_init_all_ctrlq(hw); 31550b28b702SAnirudh Venkataramanan if (ret) { 31560b28b702SAnirudh Venkataramanan dev_err(dev, "control queues init failed %d\n", ret); 31570f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 31580b28b702SAnirudh Venkataramanan } 31590b28b702SAnirudh Venkataramanan 31600b28b702SAnirudh Venkataramanan ret = ice_clear_pf_cfg(hw); 31610b28b702SAnirudh Venkataramanan if (ret) { 31620b28b702SAnirudh Venkataramanan dev_err(dev, "clear PF configuration failed %d\n", ret); 31630f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 31640b28b702SAnirudh Venkataramanan } 31650b28b702SAnirudh Venkataramanan 31660b28b702SAnirudh Venkataramanan ice_clear_pxe_mode(hw); 31670b28b702SAnirudh Venkataramanan 31680b28b702SAnirudh Venkataramanan ret = ice_get_caps(hw); 31690b28b702SAnirudh Venkataramanan if (ret) { 31700b28b702SAnirudh Venkataramanan dev_err(dev, "ice_get_caps failed %d\n", ret); 31710f9d5027SAnirudh Venkataramanan goto err_init_ctrlq; 31720b28b702SAnirudh Venkataramanan } 31730b28b702SAnirudh Venkataramanan 31740f9d5027SAnirudh Venkataramanan err = ice_sched_init_port(hw->port_info); 31750f9d5027SAnirudh Venkataramanan if (err) 31760f9d5027SAnirudh Venkataramanan goto err_sched_init_port; 31770f9d5027SAnirudh Venkataramanan 31780f9d5027SAnirudh Venkataramanan err = ice_vsi_rebuild_all(pf); 31790b28b702SAnirudh Venkataramanan if (err) { 31800f9d5027SAnirudh Venkataramanan dev_err(dev, "ice_vsi_rebuild_all failed\n"); 31810f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 31820f9d5027SAnirudh Venkataramanan } 31830f9d5027SAnirudh Venkataramanan 31840f9d5027SAnirudh Venkataramanan ret = ice_replay_all_fltr(&pf->hw); 31850f9d5027SAnirudh Venkataramanan if (ret) { 31860f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 31870f9d5027SAnirudh Venkataramanan "error replaying switch filter rules\n"); 31880f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 31890b28b702SAnirudh Venkataramanan } 31900b28b702SAnirudh Venkataramanan 31910b28b702SAnirudh Venkataramanan /* start misc vector */ 31920b28b702SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 31930b28b702SAnirudh Venkataramanan err = ice_req_irq_msix_misc(pf); 31940b28b702SAnirudh Venkataramanan if (err) { 31950b28b702SAnirudh Venkataramanan dev_err(dev, "misc vector setup failed: %d\n", err); 31960f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 31970b28b702SAnirudh Venkataramanan } 31980b28b702SAnirudh Venkataramanan } 31990b28b702SAnirudh Venkataramanan 32000b28b702SAnirudh Venkataramanan /* restart the VSIs that were rebuilt and running before the reset */ 32010f9d5027SAnirudh Venkataramanan err = ice_pf_ena_all_vsi(pf); 32020f9d5027SAnirudh Venkataramanan if (err) { 32030f9d5027SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "error enabling VSIs\n"); 32040f9d5027SAnirudh Venkataramanan /* no need to disable VSIs in tear down path in ice_rebuild() 32050f9d5027SAnirudh Venkataramanan * since its already taken care in ice_vsi_open() 32060f9d5027SAnirudh Venkataramanan */ 32070f9d5027SAnirudh Venkataramanan goto err_vsi_rebuild; 32080f9d5027SAnirudh Venkataramanan } 32090b28b702SAnirudh Venkataramanan 32100f9d5027SAnirudh Venkataramanan /* if we get here, reset flow is successful */ 32110f9d5027SAnirudh Venkataramanan clear_bit(__ICE_RESET_FAILED, pf->state); 32120b28b702SAnirudh Venkataramanan return; 32130b28b702SAnirudh Venkataramanan 32140f9d5027SAnirudh Venkataramanan err_vsi_rebuild: 32150f9d5027SAnirudh Venkataramanan ice_vsi_release_all(pf); 32160f9d5027SAnirudh Venkataramanan err_sched_init_port: 32170f9d5027SAnirudh Venkataramanan ice_sched_cleanup_all(hw); 32180f9d5027SAnirudh Venkataramanan err_init_ctrlq: 32190b28b702SAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 32200b28b702SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, pf->state); 32210b28b702SAnirudh Venkataramanan clear_recovery: 32220f9d5027SAnirudh Venkataramanan /* set this bit in PF state to control service task scheduling */ 32230f9d5027SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, pf->state); 32240f9d5027SAnirudh Venkataramanan dev_err(dev, "Rebuild failed, unload and reload driver\n"); 32250b28b702SAnirudh Venkataramanan } 32260b28b702SAnirudh Venkataramanan 32270b28b702SAnirudh Venkataramanan /** 3228e94d4478SAnirudh Venkataramanan * ice_change_mtu - NDO callback to change the MTU 3229e94d4478SAnirudh Venkataramanan * @netdev: network interface device structure 3230e94d4478SAnirudh Venkataramanan * @new_mtu: new value for maximum frame size 3231e94d4478SAnirudh Venkataramanan * 3232e94d4478SAnirudh Venkataramanan * Returns 0 on success, negative on failure 3233e94d4478SAnirudh Venkataramanan */ 3234e94d4478SAnirudh Venkataramanan static int ice_change_mtu(struct net_device *netdev, int new_mtu) 3235e94d4478SAnirudh Venkataramanan { 3236e94d4478SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3237e94d4478SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3238e94d4478SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3239e94d4478SAnirudh Venkataramanan u8 count = 0; 3240e94d4478SAnirudh Venkataramanan 3241e94d4478SAnirudh Venkataramanan if (new_mtu == netdev->mtu) { 32423968540bSAnirudh Venkataramanan netdev_warn(netdev, "mtu is already %u\n", netdev->mtu); 3243e94d4478SAnirudh Venkataramanan return 0; 3244e94d4478SAnirudh Venkataramanan } 3245e94d4478SAnirudh Venkataramanan 3246e94d4478SAnirudh Venkataramanan if (new_mtu < netdev->min_mtu) { 3247e94d4478SAnirudh Venkataramanan netdev_err(netdev, "new mtu invalid. min_mtu is %d\n", 3248e94d4478SAnirudh Venkataramanan netdev->min_mtu); 3249e94d4478SAnirudh Venkataramanan return -EINVAL; 3250e94d4478SAnirudh Venkataramanan } else if (new_mtu > netdev->max_mtu) { 3251e94d4478SAnirudh Venkataramanan netdev_err(netdev, "new mtu invalid. max_mtu is %d\n", 3252e94d4478SAnirudh Venkataramanan netdev->min_mtu); 3253e94d4478SAnirudh Venkataramanan return -EINVAL; 3254e94d4478SAnirudh Venkataramanan } 3255e94d4478SAnirudh Venkataramanan /* if a reset is in progress, wait for some time for it to complete */ 3256e94d4478SAnirudh Venkataramanan do { 32575df7e45dSDave Ertman if (ice_is_reset_in_progress(pf->state)) { 3258e94d4478SAnirudh Venkataramanan count++; 3259e94d4478SAnirudh Venkataramanan usleep_range(1000, 2000); 3260e94d4478SAnirudh Venkataramanan } else { 3261e94d4478SAnirudh Venkataramanan break; 3262e94d4478SAnirudh Venkataramanan } 3263e94d4478SAnirudh Venkataramanan 3264e94d4478SAnirudh Venkataramanan } while (count < 100); 3265e94d4478SAnirudh Venkataramanan 3266e94d4478SAnirudh Venkataramanan if (count == 100) { 3267e94d4478SAnirudh Venkataramanan netdev_err(netdev, "can't change mtu. Device is busy\n"); 3268e94d4478SAnirudh Venkataramanan return -EBUSY; 3269e94d4478SAnirudh Venkataramanan } 3270e94d4478SAnirudh Venkataramanan 3271e94d4478SAnirudh Venkataramanan netdev->mtu = new_mtu; 3272e94d4478SAnirudh Venkataramanan 3273e94d4478SAnirudh Venkataramanan /* if VSI is up, bring it down and then back up */ 3274e94d4478SAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 3275e94d4478SAnirudh Venkataramanan int err; 3276e94d4478SAnirudh Venkataramanan 3277e94d4478SAnirudh Venkataramanan err = ice_down(vsi); 3278e94d4478SAnirudh Venkataramanan if (err) { 3279e94d4478SAnirudh Venkataramanan netdev_err(netdev, "change mtu if_up err %d\n", err); 3280e94d4478SAnirudh Venkataramanan return err; 3281e94d4478SAnirudh Venkataramanan } 3282e94d4478SAnirudh Venkataramanan 3283e94d4478SAnirudh Venkataramanan err = ice_up(vsi); 3284e94d4478SAnirudh Venkataramanan if (err) { 3285e94d4478SAnirudh Venkataramanan netdev_err(netdev, "change mtu if_up err %d\n", err); 3286e94d4478SAnirudh Venkataramanan return err; 3287e94d4478SAnirudh Venkataramanan } 3288e94d4478SAnirudh Venkataramanan } 3289e94d4478SAnirudh Venkataramanan 3290e94d4478SAnirudh Venkataramanan netdev_dbg(netdev, "changed mtu to %d\n", new_mtu); 3291e94d4478SAnirudh Venkataramanan return 0; 3292e94d4478SAnirudh Venkataramanan } 3293e94d4478SAnirudh Venkataramanan 3294e94d4478SAnirudh Venkataramanan /** 3295d76a60baSAnirudh Venkataramanan * ice_set_rss - Set RSS keys and lut 3296d76a60baSAnirudh Venkataramanan * @vsi: Pointer to VSI structure 3297d76a60baSAnirudh Venkataramanan * @seed: RSS hash seed 3298d76a60baSAnirudh Venkataramanan * @lut: Lookup table 3299d76a60baSAnirudh Venkataramanan * @lut_size: Lookup table size 3300d76a60baSAnirudh Venkataramanan * 3301d76a60baSAnirudh Venkataramanan * Returns 0 on success, negative on failure 3302d76a60baSAnirudh Venkataramanan */ 3303d76a60baSAnirudh Venkataramanan int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) 3304d76a60baSAnirudh Venkataramanan { 3305d76a60baSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3306d76a60baSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3307d76a60baSAnirudh Venkataramanan enum ice_status status; 3308d76a60baSAnirudh Venkataramanan 3309d76a60baSAnirudh Venkataramanan if (seed) { 3310d76a60baSAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *buf = 3311d76a60baSAnirudh Venkataramanan (struct ice_aqc_get_set_rss_keys *)seed; 3312d76a60baSAnirudh Venkataramanan 33134fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(hw, vsi->idx, buf); 3314d76a60baSAnirudh Venkataramanan 3315d76a60baSAnirudh Venkataramanan if (status) { 3316d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3317d76a60baSAnirudh Venkataramanan "Cannot set RSS key, err %d aq_err %d\n", 3318d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3319d76a60baSAnirudh Venkataramanan return -EIO; 3320d76a60baSAnirudh Venkataramanan } 3321d76a60baSAnirudh Venkataramanan } 3322d76a60baSAnirudh Venkataramanan 3323d76a60baSAnirudh Venkataramanan if (lut) { 33244fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type, 33254fb33f31SAnirudh Venkataramanan lut, lut_size); 3326d76a60baSAnirudh Venkataramanan if (status) { 3327d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3328d76a60baSAnirudh Venkataramanan "Cannot set RSS lut, err %d aq_err %d\n", 3329d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3330d76a60baSAnirudh Venkataramanan return -EIO; 3331d76a60baSAnirudh Venkataramanan } 3332d76a60baSAnirudh Venkataramanan } 3333d76a60baSAnirudh Venkataramanan 3334d76a60baSAnirudh Venkataramanan return 0; 3335d76a60baSAnirudh Venkataramanan } 3336d76a60baSAnirudh Venkataramanan 3337d76a60baSAnirudh Venkataramanan /** 3338d76a60baSAnirudh Venkataramanan * ice_get_rss - Get RSS keys and lut 3339d76a60baSAnirudh Venkataramanan * @vsi: Pointer to VSI structure 3340d76a60baSAnirudh Venkataramanan * @seed: Buffer to store the keys 3341d76a60baSAnirudh Venkataramanan * @lut: Buffer to store the lookup table entries 3342d76a60baSAnirudh Venkataramanan * @lut_size: Size of buffer to store the lookup table entries 3343d76a60baSAnirudh Venkataramanan * 3344d76a60baSAnirudh Venkataramanan * Returns 0 on success, negative on failure 3345d76a60baSAnirudh Venkataramanan */ 3346d76a60baSAnirudh Venkataramanan int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) 3347d76a60baSAnirudh Venkataramanan { 3348d76a60baSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3349d76a60baSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3350d76a60baSAnirudh Venkataramanan enum ice_status status; 3351d76a60baSAnirudh Venkataramanan 3352d76a60baSAnirudh Venkataramanan if (seed) { 3353d76a60baSAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *buf = 3354d76a60baSAnirudh Venkataramanan (struct ice_aqc_get_set_rss_keys *)seed; 3355d76a60baSAnirudh Venkataramanan 33564fb33f31SAnirudh Venkataramanan status = ice_aq_get_rss_key(hw, vsi->idx, buf); 3357d76a60baSAnirudh Venkataramanan if (status) { 3358d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3359d76a60baSAnirudh Venkataramanan "Cannot get RSS key, err %d aq_err %d\n", 3360d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3361d76a60baSAnirudh Venkataramanan return -EIO; 3362d76a60baSAnirudh Venkataramanan } 3363d76a60baSAnirudh Venkataramanan } 3364d76a60baSAnirudh Venkataramanan 3365d76a60baSAnirudh Venkataramanan if (lut) { 33664fb33f31SAnirudh Venkataramanan status = ice_aq_get_rss_lut(hw, vsi->idx, vsi->rss_lut_type, 33674fb33f31SAnirudh Venkataramanan lut, lut_size); 3368d76a60baSAnirudh Venkataramanan if (status) { 3369d76a60baSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3370d76a60baSAnirudh Venkataramanan "Cannot get RSS lut, err %d aq_err %d\n", 3371d76a60baSAnirudh Venkataramanan status, hw->adminq.rq_last_status); 3372d76a60baSAnirudh Venkataramanan return -EIO; 3373d76a60baSAnirudh Venkataramanan } 3374d76a60baSAnirudh Venkataramanan } 3375d76a60baSAnirudh Venkataramanan 3376d76a60baSAnirudh Venkataramanan return 0; 3377d76a60baSAnirudh Venkataramanan } 3378d76a60baSAnirudh Venkataramanan 3379d76a60baSAnirudh Venkataramanan /** 3380b1edc14aSMd Fahad Iqbal Polash * ice_bridge_getlink - Get the hardware bridge mode 3381b1edc14aSMd Fahad Iqbal Polash * @skb: skb buff 3382b1edc14aSMd Fahad Iqbal Polash * @pid: process id 3383b1edc14aSMd Fahad Iqbal Polash * @seq: RTNL message seq 3384b1edc14aSMd Fahad Iqbal Polash * @dev: the netdev being configured 3385b1edc14aSMd Fahad Iqbal Polash * @filter_mask: filter mask passed in 3386b1edc14aSMd Fahad Iqbal Polash * @nlflags: netlink flags passed in 3387b1edc14aSMd Fahad Iqbal Polash * 3388b1edc14aSMd Fahad Iqbal Polash * Return the bridge mode (VEB/VEPA) 3389b1edc14aSMd Fahad Iqbal Polash */ 3390b1edc14aSMd Fahad Iqbal Polash static int 3391b1edc14aSMd Fahad Iqbal Polash ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 3392b1edc14aSMd Fahad Iqbal Polash struct net_device *dev, u32 filter_mask, int nlflags) 3393b1edc14aSMd Fahad Iqbal Polash { 3394b1edc14aSMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(dev); 3395b1edc14aSMd Fahad Iqbal Polash struct ice_vsi *vsi = np->vsi; 3396b1edc14aSMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 3397b1edc14aSMd Fahad Iqbal Polash u16 bmode; 3398b1edc14aSMd Fahad Iqbal Polash 3399b1edc14aSMd Fahad Iqbal Polash bmode = pf->first_sw->bridge_mode; 3400b1edc14aSMd Fahad Iqbal Polash 3401b1edc14aSMd Fahad Iqbal Polash return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags, 3402b1edc14aSMd Fahad Iqbal Polash filter_mask, NULL); 3403b1edc14aSMd Fahad Iqbal Polash } 3404b1edc14aSMd Fahad Iqbal Polash 3405b1edc14aSMd Fahad Iqbal Polash /** 3406b1edc14aSMd Fahad Iqbal Polash * ice_vsi_update_bridge_mode - Update VSI for switching bridge mode (VEB/VEPA) 3407b1edc14aSMd Fahad Iqbal Polash * @vsi: Pointer to VSI structure 3408b1edc14aSMd Fahad Iqbal Polash * @bmode: Hardware bridge mode (VEB/VEPA) 3409b1edc14aSMd Fahad Iqbal Polash * 3410b1edc14aSMd Fahad Iqbal Polash * Returns 0 on success, negative on failure 3411b1edc14aSMd Fahad Iqbal Polash */ 3412b1edc14aSMd Fahad Iqbal Polash static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode) 3413b1edc14aSMd Fahad Iqbal Polash { 3414b1edc14aSMd Fahad Iqbal Polash struct device *dev = &vsi->back->pdev->dev; 3415b1edc14aSMd Fahad Iqbal Polash struct ice_aqc_vsi_props *vsi_props; 3416b1edc14aSMd Fahad Iqbal Polash struct ice_hw *hw = &vsi->back->hw; 3417b1edc14aSMd Fahad Iqbal Polash struct ice_vsi_ctx ctxt = { 0 }; 3418b1edc14aSMd Fahad Iqbal Polash enum ice_status status; 3419b1edc14aSMd Fahad Iqbal Polash 3420b1edc14aSMd Fahad Iqbal Polash vsi_props = &vsi->info; 3421b1edc14aSMd Fahad Iqbal Polash ctxt.info = vsi->info; 3422b1edc14aSMd Fahad Iqbal Polash 3423b1edc14aSMd Fahad Iqbal Polash if (bmode == BRIDGE_MODE_VEB) 3424b1edc14aSMd Fahad Iqbal Polash /* change from VEPA to VEB mode */ 3425b1edc14aSMd Fahad Iqbal Polash ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 3426b1edc14aSMd Fahad Iqbal Polash else 3427b1edc14aSMd Fahad Iqbal Polash /* change from VEB to VEPA mode */ 3428b1edc14aSMd Fahad Iqbal Polash ctxt.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 3429b1edc14aSMd Fahad Iqbal Polash ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); 34305726ca0eSAnirudh Venkataramanan 34315726ca0eSAnirudh Venkataramanan status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL); 3432b1edc14aSMd Fahad Iqbal Polash if (status) { 3433b1edc14aSMd Fahad Iqbal Polash dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n", 3434b1edc14aSMd Fahad Iqbal Polash bmode, status, hw->adminq.sq_last_status); 3435b1edc14aSMd Fahad Iqbal Polash return -EIO; 3436b1edc14aSMd Fahad Iqbal Polash } 3437b1edc14aSMd Fahad Iqbal Polash /* Update sw flags for book keeping */ 3438b1edc14aSMd Fahad Iqbal Polash vsi_props->sw_flags = ctxt.info.sw_flags; 3439b1edc14aSMd Fahad Iqbal Polash 3440b1edc14aSMd Fahad Iqbal Polash return 0; 3441b1edc14aSMd Fahad Iqbal Polash } 3442b1edc14aSMd Fahad Iqbal Polash 3443b1edc14aSMd Fahad Iqbal Polash /** 3444b1edc14aSMd Fahad Iqbal Polash * ice_bridge_setlink - Set the hardware bridge mode 3445b1edc14aSMd Fahad Iqbal Polash * @dev: the netdev being configured 3446b1edc14aSMd Fahad Iqbal Polash * @nlh: RTNL message 3447b1edc14aSMd Fahad Iqbal Polash * @flags: bridge setlink flags 3448b1edc14aSMd Fahad Iqbal Polash * 3449b1edc14aSMd Fahad Iqbal Polash * Sets the bridge mode (VEB/VEPA) of the switch to which the netdev (VSI) is 3450b1edc14aSMd Fahad Iqbal Polash * hooked up to. Iterates through the PF VSI list and sets the loopback mode (if 3451b1edc14aSMd Fahad Iqbal Polash * not already set for all VSIs connected to this switch. And also update the 3452b1edc14aSMd Fahad Iqbal Polash * unicast switch filter rules for the corresponding switch of the netdev. 3453b1edc14aSMd Fahad Iqbal Polash */ 3454b1edc14aSMd Fahad Iqbal Polash static int 3455b1edc14aSMd Fahad Iqbal Polash ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, 3456b1edc14aSMd Fahad Iqbal Polash u16 __always_unused flags) 3457b1edc14aSMd Fahad Iqbal Polash { 3458b1edc14aSMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(dev); 3459b1edc14aSMd Fahad Iqbal Polash struct ice_pf *pf = np->vsi->back; 3460b1edc14aSMd Fahad Iqbal Polash struct nlattr *attr, *br_spec; 3461b1edc14aSMd Fahad Iqbal Polash struct ice_hw *hw = &pf->hw; 3462b1edc14aSMd Fahad Iqbal Polash enum ice_status status; 3463b1edc14aSMd Fahad Iqbal Polash struct ice_sw *pf_sw; 3464b1edc14aSMd Fahad Iqbal Polash int rem, v, err = 0; 3465b1edc14aSMd Fahad Iqbal Polash 3466b1edc14aSMd Fahad Iqbal Polash pf_sw = pf->first_sw; 3467b1edc14aSMd Fahad Iqbal Polash /* find the attribute in the netlink message */ 3468b1edc14aSMd Fahad Iqbal Polash br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); 3469b1edc14aSMd Fahad Iqbal Polash 3470b1edc14aSMd Fahad Iqbal Polash nla_for_each_nested(attr, br_spec, rem) { 3471b1edc14aSMd Fahad Iqbal Polash __u16 mode; 3472b1edc14aSMd Fahad Iqbal Polash 3473b1edc14aSMd Fahad Iqbal Polash if (nla_type(attr) != IFLA_BRIDGE_MODE) 3474b1edc14aSMd Fahad Iqbal Polash continue; 3475b1edc14aSMd Fahad Iqbal Polash mode = nla_get_u16(attr); 3476b1edc14aSMd Fahad Iqbal Polash if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) 3477b1edc14aSMd Fahad Iqbal Polash return -EINVAL; 3478b1edc14aSMd Fahad Iqbal Polash /* Continue if bridge mode is not being flipped */ 3479b1edc14aSMd Fahad Iqbal Polash if (mode == pf_sw->bridge_mode) 3480b1edc14aSMd Fahad Iqbal Polash continue; 3481b1edc14aSMd Fahad Iqbal Polash /* Iterates through the PF VSI list and update the loopback 3482b1edc14aSMd Fahad Iqbal Polash * mode of the VSI 3483b1edc14aSMd Fahad Iqbal Polash */ 3484b1edc14aSMd Fahad Iqbal Polash ice_for_each_vsi(pf, v) { 3485b1edc14aSMd Fahad Iqbal Polash if (!pf->vsi[v]) 3486b1edc14aSMd Fahad Iqbal Polash continue; 3487b1edc14aSMd Fahad Iqbal Polash err = ice_vsi_update_bridge_mode(pf->vsi[v], mode); 3488b1edc14aSMd Fahad Iqbal Polash if (err) 3489b1edc14aSMd Fahad Iqbal Polash return err; 3490b1edc14aSMd Fahad Iqbal Polash } 3491b1edc14aSMd Fahad Iqbal Polash 3492b1edc14aSMd Fahad Iqbal Polash hw->evb_veb = (mode == BRIDGE_MODE_VEB); 3493b1edc14aSMd Fahad Iqbal Polash /* Update the unicast switch filter rules for the corresponding 3494b1edc14aSMd Fahad Iqbal Polash * switch of the netdev 3495b1edc14aSMd Fahad Iqbal Polash */ 3496b1edc14aSMd Fahad Iqbal Polash status = ice_update_sw_rule_bridge_mode(hw); 3497b1edc14aSMd Fahad Iqbal Polash if (status) { 3498b1edc14aSMd Fahad Iqbal Polash netdev_err(dev, "update SW_RULE for bridge mode failed, = %d err %d aq_err %d\n", 3499b1edc14aSMd Fahad Iqbal Polash mode, status, hw->adminq.sq_last_status); 3500b1edc14aSMd Fahad Iqbal Polash /* revert hw->evb_veb */ 3501b1edc14aSMd Fahad Iqbal Polash hw->evb_veb = (pf_sw->bridge_mode == BRIDGE_MODE_VEB); 3502b1edc14aSMd Fahad Iqbal Polash return -EIO; 3503b1edc14aSMd Fahad Iqbal Polash } 3504b1edc14aSMd Fahad Iqbal Polash 3505b1edc14aSMd Fahad Iqbal Polash pf_sw->bridge_mode = mode; 3506b1edc14aSMd Fahad Iqbal Polash } 3507b1edc14aSMd Fahad Iqbal Polash 3508b1edc14aSMd Fahad Iqbal Polash return 0; 3509b1edc14aSMd Fahad Iqbal Polash } 3510b1edc14aSMd Fahad Iqbal Polash 3511b1edc14aSMd Fahad Iqbal Polash /** 3512b3969fd7SSudheer Mogilappagari * ice_tx_timeout - Respond to a Tx Hang 3513b3969fd7SSudheer Mogilappagari * @netdev: network interface device structure 3514b3969fd7SSudheer Mogilappagari */ 3515b3969fd7SSudheer Mogilappagari static void ice_tx_timeout(struct net_device *netdev) 3516b3969fd7SSudheer Mogilappagari { 3517b3969fd7SSudheer Mogilappagari struct ice_netdev_priv *np = netdev_priv(netdev); 3518b3969fd7SSudheer Mogilappagari struct ice_ring *tx_ring = NULL; 3519b3969fd7SSudheer Mogilappagari struct ice_vsi *vsi = np->vsi; 3520b3969fd7SSudheer Mogilappagari struct ice_pf *pf = vsi->back; 3521b3969fd7SSudheer Mogilappagari u32 head, val = 0, i; 3522b3969fd7SSudheer Mogilappagari int hung_queue = -1; 3523b3969fd7SSudheer Mogilappagari 3524b3969fd7SSudheer Mogilappagari pf->tx_timeout_count++; 3525b3969fd7SSudheer Mogilappagari 3526b3969fd7SSudheer Mogilappagari /* find the stopped queue the same way the stack does */ 3527b3969fd7SSudheer Mogilappagari for (i = 0; i < netdev->num_tx_queues; i++) { 3528b3969fd7SSudheer Mogilappagari struct netdev_queue *q; 3529b3969fd7SSudheer Mogilappagari unsigned long trans_start; 3530b3969fd7SSudheer Mogilappagari 3531b3969fd7SSudheer Mogilappagari q = netdev_get_tx_queue(netdev, i); 3532b3969fd7SSudheer Mogilappagari trans_start = q->trans_start; 3533b3969fd7SSudheer Mogilappagari if (netif_xmit_stopped(q) && 3534b3969fd7SSudheer Mogilappagari time_after(jiffies, 3535b3969fd7SSudheer Mogilappagari (trans_start + netdev->watchdog_timeo))) { 3536b3969fd7SSudheer Mogilappagari hung_queue = i; 3537b3969fd7SSudheer Mogilappagari break; 3538b3969fd7SSudheer Mogilappagari } 3539b3969fd7SSudheer Mogilappagari } 3540b3969fd7SSudheer Mogilappagari 3541b3969fd7SSudheer Mogilappagari if (i == netdev->num_tx_queues) { 3542b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout: no netdev hung queue found\n"); 3543b3969fd7SSudheer Mogilappagari } else { 3544b3969fd7SSudheer Mogilappagari /* now that we have an index, find the tx_ring struct */ 3545b3969fd7SSudheer Mogilappagari for (i = 0; i < vsi->num_txq; i++) { 3546b3969fd7SSudheer Mogilappagari if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) { 3547b3969fd7SSudheer Mogilappagari if (hung_queue == 3548b3969fd7SSudheer Mogilappagari vsi->tx_rings[i]->q_index) { 3549b3969fd7SSudheer Mogilappagari tx_ring = vsi->tx_rings[i]; 3550b3969fd7SSudheer Mogilappagari break; 3551b3969fd7SSudheer Mogilappagari } 3552b3969fd7SSudheer Mogilappagari } 3553b3969fd7SSudheer Mogilappagari } 3554b3969fd7SSudheer Mogilappagari } 3555b3969fd7SSudheer Mogilappagari 3556b3969fd7SSudheer Mogilappagari /* Reset recovery level if enough time has elapsed after last timeout. 3557b3969fd7SSudheer Mogilappagari * Also ensure no new reset action happens before next timeout period. 3558b3969fd7SSudheer Mogilappagari */ 3559b3969fd7SSudheer Mogilappagari if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ * 20))) 3560b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level = 1; 3561b3969fd7SSudheer Mogilappagari else if (time_before(jiffies, (pf->tx_timeout_last_recovery + 3562b3969fd7SSudheer Mogilappagari netdev->watchdog_timeo))) 3563b3969fd7SSudheer Mogilappagari return; 3564b3969fd7SSudheer Mogilappagari 3565b3969fd7SSudheer Mogilappagari if (tx_ring) { 3566b3969fd7SSudheer Mogilappagari head = tx_ring->next_to_clean; 3567b3969fd7SSudheer Mogilappagari /* Read interrupt register */ 3568b3969fd7SSudheer Mogilappagari if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 3569b3969fd7SSudheer Mogilappagari val = rd32(&pf->hw, 3570b3969fd7SSudheer Mogilappagari GLINT_DYN_CTL(tx_ring->q_vector->v_idx + 3571b3969fd7SSudheer Mogilappagari tx_ring->vsi->base_vector - 1)); 3572b3969fd7SSudheer Mogilappagari 3573b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n", 3574b3969fd7SSudheer Mogilappagari vsi->vsi_num, hung_queue, tx_ring->next_to_clean, 3575b3969fd7SSudheer Mogilappagari head, tx_ring->next_to_use, 3576b3969fd7SSudheer Mogilappagari readl(tx_ring->tail), val); 3577b3969fd7SSudheer Mogilappagari } 3578b3969fd7SSudheer Mogilappagari 3579b3969fd7SSudheer Mogilappagari pf->tx_timeout_last_recovery = jiffies; 3580b3969fd7SSudheer Mogilappagari netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n", 3581b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level, hung_queue); 3582b3969fd7SSudheer Mogilappagari 3583b3969fd7SSudheer Mogilappagari switch (pf->tx_timeout_recovery_level) { 3584b3969fd7SSudheer Mogilappagari case 1: 3585b3969fd7SSudheer Mogilappagari set_bit(__ICE_PFR_REQ, pf->state); 3586b3969fd7SSudheer Mogilappagari break; 3587b3969fd7SSudheer Mogilappagari case 2: 3588b3969fd7SSudheer Mogilappagari set_bit(__ICE_CORER_REQ, pf->state); 3589b3969fd7SSudheer Mogilappagari break; 3590b3969fd7SSudheer Mogilappagari case 3: 3591b3969fd7SSudheer Mogilappagari set_bit(__ICE_GLOBR_REQ, pf->state); 3592b3969fd7SSudheer Mogilappagari break; 3593b3969fd7SSudheer Mogilappagari default: 3594b3969fd7SSudheer Mogilappagari netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in unrecoverable state.\n"); 3595b3969fd7SSudheer Mogilappagari set_bit(__ICE_DOWN, pf->state); 3596b3969fd7SSudheer Mogilappagari set_bit(__ICE_NEEDS_RESTART, vsi->state); 35978d81fa55SAkeem G Abodunrin set_bit(__ICE_SERVICE_DIS, pf->state); 3598b3969fd7SSudheer Mogilappagari break; 3599b3969fd7SSudheer Mogilappagari } 3600b3969fd7SSudheer Mogilappagari 3601b3969fd7SSudheer Mogilappagari ice_service_task_schedule(pf); 3602b3969fd7SSudheer Mogilappagari pf->tx_timeout_recovery_level++; 3603b3969fd7SSudheer Mogilappagari } 3604b3969fd7SSudheer Mogilappagari 3605b3969fd7SSudheer Mogilappagari /** 3606cdedef59SAnirudh Venkataramanan * ice_open - Called when a network interface becomes active 3607cdedef59SAnirudh Venkataramanan * @netdev: network interface device structure 3608cdedef59SAnirudh Venkataramanan * 3609cdedef59SAnirudh Venkataramanan * The open entry point is called when a network interface is made 3610cdedef59SAnirudh Venkataramanan * active by the system (IFF_UP). At this point all resources needed 3611cdedef59SAnirudh Venkataramanan * for transmit and receive operations are allocated, the interrupt 3612cdedef59SAnirudh Venkataramanan * handler is registered with the OS, the netdev watchdog is enabled, 3613cdedef59SAnirudh Venkataramanan * and the stack is notified that the interface is ready. 3614cdedef59SAnirudh Venkataramanan * 3615cdedef59SAnirudh Venkataramanan * Returns 0 on success, negative value on failure 3616cdedef59SAnirudh Venkataramanan */ 3617cdedef59SAnirudh Venkataramanan static int ice_open(struct net_device *netdev) 3618cdedef59SAnirudh Venkataramanan { 3619cdedef59SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3620cdedef59SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3621cdedef59SAnirudh Venkataramanan int err; 3622cdedef59SAnirudh Venkataramanan 36230f9d5027SAnirudh Venkataramanan if (test_bit(__ICE_NEEDS_RESTART, vsi->back->state)) { 36240f9d5027SAnirudh Venkataramanan netdev_err(netdev, "driver needs to be unloaded and reloaded\n"); 36250f9d5027SAnirudh Venkataramanan return -EIO; 36260f9d5027SAnirudh Venkataramanan } 36270f9d5027SAnirudh Venkataramanan 3628cdedef59SAnirudh Venkataramanan netif_carrier_off(netdev); 3629cdedef59SAnirudh Venkataramanan 3630cdedef59SAnirudh Venkataramanan err = ice_vsi_open(vsi); 3631cdedef59SAnirudh Venkataramanan 3632cdedef59SAnirudh Venkataramanan if (err) 3633cdedef59SAnirudh Venkataramanan netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n", 3634cdedef59SAnirudh Venkataramanan vsi->vsi_num, vsi->vsw->sw_id); 3635cdedef59SAnirudh Venkataramanan return err; 3636cdedef59SAnirudh Venkataramanan } 3637cdedef59SAnirudh Venkataramanan 3638cdedef59SAnirudh Venkataramanan /** 3639cdedef59SAnirudh Venkataramanan * ice_stop - Disables a network interface 3640cdedef59SAnirudh Venkataramanan * @netdev: network interface device structure 3641cdedef59SAnirudh Venkataramanan * 3642cdedef59SAnirudh Venkataramanan * The stop entry point is called when an interface is de-activated by the OS, 3643cdedef59SAnirudh Venkataramanan * and the netdevice enters the DOWN state. The hardware is still under the 3644cdedef59SAnirudh Venkataramanan * driver's control, but the netdev interface is disabled. 3645cdedef59SAnirudh Venkataramanan * 3646cdedef59SAnirudh Venkataramanan * Returns success only - not allowed to fail 3647cdedef59SAnirudh Venkataramanan */ 3648cdedef59SAnirudh Venkataramanan static int ice_stop(struct net_device *netdev) 3649cdedef59SAnirudh Venkataramanan { 3650cdedef59SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3651cdedef59SAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3652cdedef59SAnirudh Venkataramanan 3653cdedef59SAnirudh Venkataramanan ice_vsi_close(vsi); 3654cdedef59SAnirudh Venkataramanan 3655cdedef59SAnirudh Venkataramanan return 0; 3656cdedef59SAnirudh Venkataramanan } 3657cdedef59SAnirudh Venkataramanan 3658e94d4478SAnirudh Venkataramanan /** 3659e94d4478SAnirudh Venkataramanan * ice_features_check - Validate encapsulated packet conforms to limits 3660e94d4478SAnirudh Venkataramanan * @skb: skb buffer 3661e94d4478SAnirudh Venkataramanan * @netdev: This port's netdev 3662e94d4478SAnirudh Venkataramanan * @features: Offload features that the stack believes apply 3663e94d4478SAnirudh Venkataramanan */ 3664e94d4478SAnirudh Venkataramanan static netdev_features_t 3665e94d4478SAnirudh Venkataramanan ice_features_check(struct sk_buff *skb, 3666e94d4478SAnirudh Venkataramanan struct net_device __always_unused *netdev, 3667e94d4478SAnirudh Venkataramanan netdev_features_t features) 3668e94d4478SAnirudh Venkataramanan { 3669e94d4478SAnirudh Venkataramanan size_t len; 3670e94d4478SAnirudh Venkataramanan 3671e94d4478SAnirudh Venkataramanan /* No point in doing any of this if neither checksum nor GSO are 3672e94d4478SAnirudh Venkataramanan * being requested for this frame. We can rule out both by just 3673e94d4478SAnirudh Venkataramanan * checking for CHECKSUM_PARTIAL 3674e94d4478SAnirudh Venkataramanan */ 3675e94d4478SAnirudh Venkataramanan if (skb->ip_summed != CHECKSUM_PARTIAL) 3676e94d4478SAnirudh Venkataramanan return features; 3677e94d4478SAnirudh Venkataramanan 3678e94d4478SAnirudh Venkataramanan /* We cannot support GSO if the MSS is going to be less than 3679e94d4478SAnirudh Venkataramanan * 64 bytes. If it is then we need to drop support for GSO. 3680e94d4478SAnirudh Venkataramanan */ 3681e94d4478SAnirudh Venkataramanan if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) 3682e94d4478SAnirudh Venkataramanan features &= ~NETIF_F_GSO_MASK; 3683e94d4478SAnirudh Venkataramanan 3684e94d4478SAnirudh Venkataramanan len = skb_network_header(skb) - skb->data; 3685e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_MACLEN_MAX)) 3686e94d4478SAnirudh Venkataramanan goto out_rm_features; 3687e94d4478SAnirudh Venkataramanan 3688e94d4478SAnirudh Venkataramanan len = skb_transport_header(skb) - skb_network_header(skb); 3689e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_IPLEN_MAX)) 3690e94d4478SAnirudh Venkataramanan goto out_rm_features; 3691e94d4478SAnirudh Venkataramanan 3692e94d4478SAnirudh Venkataramanan if (skb->encapsulation) { 3693e94d4478SAnirudh Venkataramanan len = skb_inner_network_header(skb) - skb_transport_header(skb); 3694e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_L4LEN_MAX)) 3695e94d4478SAnirudh Venkataramanan goto out_rm_features; 3696e94d4478SAnirudh Venkataramanan 3697e94d4478SAnirudh Venkataramanan len = skb_inner_transport_header(skb) - 3698e94d4478SAnirudh Venkataramanan skb_inner_network_header(skb); 3699e94d4478SAnirudh Venkataramanan if (len & ~(ICE_TXD_IPLEN_MAX)) 3700e94d4478SAnirudh Venkataramanan goto out_rm_features; 3701e94d4478SAnirudh Venkataramanan } 3702e94d4478SAnirudh Venkataramanan 3703e94d4478SAnirudh Venkataramanan return features; 3704e94d4478SAnirudh Venkataramanan out_rm_features: 3705e94d4478SAnirudh Venkataramanan return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); 3706e94d4478SAnirudh Venkataramanan } 3707e94d4478SAnirudh Venkataramanan 3708cdedef59SAnirudh Venkataramanan static const struct net_device_ops ice_netdev_ops = { 3709cdedef59SAnirudh Venkataramanan .ndo_open = ice_open, 3710cdedef59SAnirudh Venkataramanan .ndo_stop = ice_stop, 37112b245cb2SAnirudh Venkataramanan .ndo_start_xmit = ice_start_xmit, 3712e94d4478SAnirudh Venkataramanan .ndo_features_check = ice_features_check, 3713e94d4478SAnirudh Venkataramanan .ndo_set_rx_mode = ice_set_rx_mode, 3714e94d4478SAnirudh Venkataramanan .ndo_set_mac_address = ice_set_mac_address, 3715e94d4478SAnirudh Venkataramanan .ndo_validate_addr = eth_validate_addr, 3716e94d4478SAnirudh Venkataramanan .ndo_change_mtu = ice_change_mtu, 3717fcea6f3dSAnirudh Venkataramanan .ndo_get_stats64 = ice_get_stats64, 3718d76a60baSAnirudh Venkataramanan .ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid, 3719d76a60baSAnirudh Venkataramanan .ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid, 3720d76a60baSAnirudh Venkataramanan .ndo_set_features = ice_set_features, 3721b1edc14aSMd Fahad Iqbal Polash .ndo_bridge_getlink = ice_bridge_getlink, 3722b1edc14aSMd Fahad Iqbal Polash .ndo_bridge_setlink = ice_bridge_setlink, 3723e94d4478SAnirudh Venkataramanan .ndo_fdb_add = ice_fdb_add, 3724e94d4478SAnirudh Venkataramanan .ndo_fdb_del = ice_fdb_del, 3725b3969fd7SSudheer Mogilappagari .ndo_tx_timeout = ice_tx_timeout, 3726cdedef59SAnirudh Venkataramanan }; 3727