Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-2.6-microblaze.git] / drivers / net / ethernet / intel / ice / ice_main.c
index 0eb2307..0d6c143 100644 (file)
 #include "ice_dcb_lib.h"
 #include "ice_dcb_nl.h"
 #include "ice_devlink.h"
+/* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the
+ * ice tracepoint functions. This must be done exactly once across the
+ * ice driver.
+ */
+#define CREATE_TRACE_POINTS
+#include "ice_trace.h"
 
 #define DRV_SUMMARY    "Intel(R) Ethernet Connection E800 Series Linux Driver"
 static const char ice_driver_string[] = DRV_SUMMARY;
@@ -35,6 +41,8 @@ MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXX
 MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)");
 #endif /* !CONFIG_DYNAMIC_DEBUG */
 
+static DEFINE_IDA(ice_aux_ida);
+
 static struct workqueue_struct *ice_wq;
 static const struct net_device_ops ice_netdev_safe_mode_ops;
 static const struct net_device_ops ice_netdev_ops;
@@ -183,6 +191,14 @@ static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr)
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_vsi *vsi = np->vsi;
 
+       /* Under some circumstances, we might receive a request to delete our
+        * own device address from our uc list. Because we store the device
+        * address in the VSI's MAC filter list, we need to ignore such
+        * requests and not delete our device address from this list.
+        */
+       if (ether_addr_equal(addr, netdev->dev_addr))
+               return 0;
+
        if (ice_fltr_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr,
                                     ICE_FWD_TO_VSI))
                return -EINVAL;
@@ -454,6 +470,8 @@ ice_prepare_for_reset(struct ice_pf *pf)
        if (test_bit(ICE_PREPARED_FOR_RESET, pf->state))
                return;
 
+       ice_unplug_aux_dev(pf);
+
        /* Notify VFs of impending reset */
        if (ice_check_sq_alive(hw, &hw->mailboxq))
                ice_vc_notify_reset(pf);
@@ -467,6 +485,9 @@ ice_prepare_for_reset(struct ice_pf *pf)
        /* disable the VSIs and their queues that are not already DOWN */
        ice_pf_dis_all_vsi(pf, false);
 
+       if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
+               ice_ptp_release(pf);
+
        if (hw->port_info)
                ice_sched_clear_port(hw->port_info);
 
@@ -499,6 +520,7 @@ static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
                clear_bit(ICE_PFR_REQ, pf->state);
                clear_bit(ICE_CORER_REQ, pf->state);
                clear_bit(ICE_GLOBR_REQ, pf->state);
+               wake_up(&pf->reset_wait_queue);
                return;
        }
 
@@ -511,6 +533,7 @@ static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
                ice_rebuild(pf, reset_type);
                clear_bit(ICE_PREPARED_FOR_RESET, pf->state);
                clear_bit(ICE_PFR_REQ, pf->state);
+               wake_up(&pf->reset_wait_queue);
                ice_reset_all_vfs(pf, true);
        }
 }
@@ -561,6 +584,7 @@ static void ice_reset_subtask(struct ice_pf *pf)
                        clear_bit(ICE_PFR_REQ, pf->state);
                        clear_bit(ICE_CORER_REQ, pf->state);
                        clear_bit(ICE_GLOBR_REQ, pf->state);
+                       wake_up(&pf->reset_wait_queue);
                        ice_reset_all_vfs(pf, true);
                }
 
@@ -857,6 +881,38 @@ static void ice_set_dflt_mib(struct ice_pf *pf)
        kfree(lldpmib);
 }
 
+/**
+ * ice_check_module_power
+ * @pf: pointer to PF struct
+ * @link_cfg_err: bitmap from the link info structure
+ *
+ * check module power level returned by a previous call to aq_get_link_info
+ * and print error messages if module power level is not supported
+ */
+static void ice_check_module_power(struct ice_pf *pf, u8 link_cfg_err)
+{
+       /* if module power level is supported, clear the flag */
+       if (!(link_cfg_err & (ICE_AQ_LINK_INVAL_MAX_POWER_LIMIT |
+                             ICE_AQ_LINK_MODULE_POWER_UNSUPPORTED))) {
+               clear_bit(ICE_FLAG_MOD_POWER_UNSUPPORTED, pf->flags);
+               return;
+       }
+
+       /* if ICE_FLAG_MOD_POWER_UNSUPPORTED was previously set and the
+        * above block didn't clear this bit, there's nothing to do
+        */
+       if (test_bit(ICE_FLAG_MOD_POWER_UNSUPPORTED, pf->flags))
+               return;
+
+       if (link_cfg_err & ICE_AQ_LINK_INVAL_MAX_POWER_LIMIT) {
+               dev_err(ice_pf_to_dev(pf), "The installed module is incompatible with the device's NVM image. Cannot start link\n");
+               set_bit(ICE_FLAG_MOD_POWER_UNSUPPORTED, pf->flags);
+       } else if (link_cfg_err & ICE_AQ_LINK_MODULE_POWER_UNSUPPORTED) {
+               dev_err(ice_pf_to_dev(pf), "The module's power requirements exceed the device's power supply. Cannot start link\n");
+               set_bit(ICE_FLAG_MOD_POWER_UNSUPPORTED, pf->flags);
+       }
+}
+
 /**
  * ice_link_event - process the link event
  * @pf: PF that the link event is associated with
@@ -892,6 +948,8 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
                        pi->lport, ice_stat_str(status),
                        ice_aq_str(pi->hw->adminq.sq_last_status));
 
+       ice_check_module_power(pf, pi->phy.link_info.link_cfg_err);
+
        /* Check if the link state is up after updating link info, and treat
         * this event as an UP event since the link is actually UP now.
         */
@@ -1190,6 +1248,10 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type)
                cq = &hw->adminq;
                qtype = "Admin";
                break;
+       case ICE_CTL_Q_SB:
+               cq = &hw->sbq;
+               qtype = "Sideband";
+               break;
        case ICE_CTL_Q_MAILBOX:
                cq = &hw->mailboxq;
                qtype = "Mailbox";
@@ -1363,6 +1425,34 @@ static void ice_clean_mailboxq_subtask(struct ice_pf *pf)
        ice_flush(hw);
 }
 
+/**
+ * ice_clean_sbq_subtask - clean the Sideband Queue rings
+ * @pf: board private structure
+ */
+static void ice_clean_sbq_subtask(struct ice_pf *pf)
+{
+       struct ice_hw *hw = &pf->hw;
+
+       /* Nothing to do here if sideband queue is not supported */
+       if (!ice_is_sbq_supported(hw)) {
+               clear_bit(ICE_SIDEBANDQ_EVENT_PENDING, pf->state);
+               return;
+       }
+
+       if (!test_bit(ICE_SIDEBANDQ_EVENT_PENDING, pf->state))
+               return;
+
+       if (__ice_clean_ctrlq(pf, ICE_CTL_Q_SB))
+               return;
+
+       clear_bit(ICE_SIDEBANDQ_EVENT_PENDING, pf->state);
+
+       if (ice_ctrlq_pending(hw, &hw->sbq))
+               __ice_clean_ctrlq(pf, ICE_CTL_Q_SB);
+
+       ice_flush(hw);
+}
+
 /**
  * ice_service_task_schedule - schedule the service task to wake up
  * @pf: board private structure
@@ -2006,6 +2096,8 @@ static void ice_check_media_subtask(struct ice_pf *pf)
        if (err)
                return;
 
+       ice_check_module_power(pf, pi->phy.link_info.link_cfg_err);
+
        if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
                if (!test_bit(ICE_PHY_INIT_COMPLETE, pf->state))
                        ice_init_phy_user_cfg(pi);
@@ -2063,6 +2155,7 @@ static void ice_service_task(struct work_struct *work)
 
        ice_process_vflr_event(pf);
        ice_clean_mailboxq_subtask(pf);
+       ice_clean_sbq_subtask(pf);
        ice_sync_arfs_fltrs(pf);
        ice_flush_fdir_ctx(pf);
 
@@ -2078,6 +2171,7 @@ static void ice_service_task(struct work_struct *work)
            test_bit(ICE_VFLR_EVENT_PENDING, pf->state) ||
            test_bit(ICE_MAILBOXQ_EVENT_PENDING, pf->state) ||
            test_bit(ICE_FD_VF_FLUSH_CTX, pf->state) ||
+           test_bit(ICE_SIDEBANDQ_EVENT_PENDING, pf->state) ||
            test_bit(ICE_ADMINQ_EVENT_PENDING, pf->state))
                mod_timer(&pf->serv_tmr, jiffies);
 }
@@ -2096,6 +2190,10 @@ static void ice_set_ctrlq_len(struct ice_hw *hw)
        hw->mailboxq.num_sq_entries = ICE_MBXSQ_LEN;
        hw->mailboxq.rq_buf_size = ICE_MBXQ_MAX_BUF_LEN;
        hw->mailboxq.sq_buf_size = ICE_MBXQ_MAX_BUF_LEN;
+       hw->sbq.num_rq_entries = ICE_SBQ_LEN;
+       hw->sbq.num_sq_entries = ICE_SBQ_LEN;
+       hw->sbq.rq_buf_size = ICE_SBQ_MAX_BUF_LEN;
+       hw->sbq.sq_buf_size = ICE_SBQ_MAX_BUF_LEN;
 }
 
 /**
@@ -2118,6 +2216,8 @@ int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset)
                return -EBUSY;
        }
 
+       ice_unplug_aux_dev(pf);
+
        switch (reset) {
        case ICE_RESET_PFR:
                set_bit(ICE_PFR_REQ, pf->state);
@@ -2622,6 +2722,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)
               PFINT_OICR_PCI_EXCEPTION_M |
               PFINT_OICR_VFLR_M |
               PFINT_OICR_HMC_ERR_M |
+              PFINT_OICR_PE_PUSH_M |
               PFINT_OICR_PE_CRITERR_M);
 
        wr32(hw, PFINT_OICR_ENA, val);
@@ -2647,6 +2748,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
        dev = ice_pf_to_dev(pf);
        set_bit(ICE_ADMINQ_EVENT_PENDING, pf->state);
        set_bit(ICE_MAILBOXQ_EVENT_PENDING, pf->state);
+       set_bit(ICE_SIDEBANDQ_EVENT_PENDING, pf->state);
 
        oicr = rd32(hw, PFINT_OICR);
        ena_mask = rd32(hw, PFINT_OICR_ENA);
@@ -2692,8 +2794,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
 
                /* If a reset cycle isn't already in progress, we set a bit in
                 * pf->state so that the service task can start a reset/rebuild.
-                * We also make note of which reset happened so that peer
-                * devices/drivers can be informed.
                 */
                if (!test_and_set_bit(ICE_RESET_OICR_RECV, pf->state)) {
                        if (reset == ICE_RESET_CORER)
@@ -2720,11 +2820,36 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
                }
        }
 
-       if (oicr & PFINT_OICR_HMC_ERR_M) {
-               ena_mask &= ~PFINT_OICR_HMC_ERR_M;
-               dev_dbg(dev, "HMC Error interrupt - info 0x%x, data 0x%x\n",
-                       rd32(hw, PFHMC_ERRORINFO),
-                       rd32(hw, PFHMC_ERRORDATA));
+       if (oicr & PFINT_OICR_TSYN_TX_M) {
+               ena_mask &= ~PFINT_OICR_TSYN_TX_M;
+               ice_ptp_process_ts(pf);
+       }
+
+       if (oicr & PFINT_OICR_TSYN_EVNT_M) {
+               u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+               u32 gltsyn_stat = rd32(hw, GLTSYN_STAT(tmr_idx));
+
+               /* Save EVENTs from GTSYN register */
+               pf->ptp.ext_ts_irq |= gltsyn_stat & (GLTSYN_STAT_EVENT0_M |
+                                                    GLTSYN_STAT_EVENT1_M |
+                                                    GLTSYN_STAT_EVENT2_M);
+               ena_mask &= ~PFINT_OICR_TSYN_EVNT_M;
+               kthread_queue_work(pf->ptp.kworker, &pf->ptp.extts_work);
+       }
+
+#define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M)
+       if (oicr & ICE_AUX_CRIT_ERR) {
+               struct iidc_event *event;
+
+               ena_mask &= ~ICE_AUX_CRIT_ERR;
+               event = kzalloc(sizeof(*event), GFP_KERNEL);
+               if (event) {
+                       set_bit(IIDC_EVENT_CRIT_ERR, event->type);
+                       /* report the entire OICR value to AUX driver */
+                       event->reg = oicr;
+                       ice_send_event_to_aux(pf, event);
+                       kfree(event);
+               }
        }
 
        /* Report any remaining unexpected interrupts */
@@ -2734,8 +2859,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
                /* If a critical error is pending there is no choice but to
                 * reset the device.
                 */
-               if (oicr & (PFINT_OICR_PE_CRITERR_M |
-                           PFINT_OICR_PCI_EXCEPTION_M |
+               if (oicr & (PFINT_OICR_PCI_EXCEPTION_M |
                            PFINT_OICR_ECC_ERR_M)) {
                        set_bit(ICE_PFR_REQ, pf->state);
                        ice_service_task_schedule(pf);
@@ -2763,6 +2887,9 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw)
        wr32(hw, PFINT_MBX_CTL,
             rd32(hw, PFINT_MBX_CTL) & ~PFINT_MBX_CTL_CAUSE_ENA_M);
 
+       wr32(hw, PFINT_SB_CTL,
+            rd32(hw, PFINT_SB_CTL) & ~PFINT_SB_CTL_CAUSE_ENA_M);
+
        /* disable Control queue Interrupt causes */
        wr32(hw, PFINT_OICR_CTL,
             rd32(hw, PFINT_OICR_CTL) & ~PFINT_OICR_CTL_CAUSE_ENA_M);
@@ -2817,6 +2944,11 @@ static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 reg_idx)
               PFINT_MBX_CTL_CAUSE_ENA_M);
        wr32(hw, PFINT_MBX_CTL, val);
 
+       /* This enables Sideband queue Interrupt causes */
+       val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) |
+              PFINT_SB_CTL_CAUSE_ENA_M);
+       wr32(hw, PFINT_SB_CTL, val);
+
        ice_flush(hw);
 }
 
@@ -2986,7 +3118,6 @@ static void ice_set_netdev_features(struct net_device *netdev)
  */
 static int ice_cfg_netdev(struct ice_vsi *vsi)
 {
-       struct ice_pf *pf = vsi->back;
        struct ice_netdev_priv *np;
        struct net_device *netdev;
        u8 mac_addr[ETH_ALEN];
@@ -3006,7 +3137,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
        ice_set_ops(netdev);
 
        if (vsi->type == ICE_VSI_PF) {
-               SET_NETDEV_DEV(netdev, ice_pf_to_dev(pf));
+               SET_NETDEV_DEV(netdev, ice_pf_to_dev(vsi->back));
                ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr);
                ether_addr_copy(netdev->dev_addr, mac_addr);
                ether_addr_copy(netdev->perm_addr, mac_addr);
@@ -3280,6 +3411,9 @@ static void ice_deinit_pf(struct ice_pf *pf)
                bitmap_free(pf->avail_rxqs);
                pf->avail_rxqs = NULL;
        }
+
+       if (pf->ptp.clock)
+               ptp_clock_unregister(pf->ptp.clock);
 }
 
 /**
@@ -3290,6 +3424,12 @@ static void ice_set_pf_caps(struct ice_pf *pf)
 {
        struct ice_hw_func_caps *func_caps = &pf->hw.func_caps;
 
+       clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+       clear_bit(ICE_FLAG_AUX_ENA, pf->flags);
+       if (func_caps->common_cap.rdma) {
+               set_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+               set_bit(ICE_FLAG_AUX_ENA, pf->flags);
+       }
        clear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
        if (func_caps->common_cap.dcb)
                set_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
@@ -3320,6 +3460,10 @@ static void ice_set_pf_caps(struct ice_pf *pf)
                                       func_caps->fd_fltr_best_effort);
        }
 
+       clear_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags);
+       if (func_caps->common_cap.ieee_1588)
+               set_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags);
+
        pf->max_pf_txqs = func_caps->common_cap.num_txq;
        pf->max_pf_rxqs = func_caps->common_cap.num_rxq;
 }
@@ -3339,6 +3483,8 @@ static int ice_init_pf(struct ice_pf *pf)
        spin_lock_init(&pf->aq_wait_lock);
        init_waitqueue_head(&pf->aq_wait_queue);
 
+       init_waitqueue_head(&pf->reset_wait_queue);
+
        /* setup service timer and periodic service task */
        timer_setup(&pf->serv_tmr, ice_service_timer, 0);
        pf->serv_tmr_period = HZ;
@@ -3369,11 +3515,12 @@ static int ice_init_pf(struct ice_pf *pf)
  */
 static int ice_ena_msix_range(struct ice_pf *pf)
 {
-       int v_left, v_actual, v_other, v_budget = 0;
+       int num_cpus, v_left, v_actual, v_other, v_budget = 0;
        struct device *dev = ice_pf_to_dev(pf);
        int needed, err, i;
 
        v_left = pf->hw.func_caps.common_cap.num_msix_vectors;
+       num_cpus = num_online_cpus();
 
        /* reserve for LAN miscellaneous handler */
        needed = ICE_MIN_LAN_OICR_MSIX;
@@ -3395,13 +3542,23 @@ static int ice_ena_msix_range(struct ice_pf *pf)
        v_other = v_budget;
 
        /* reserve vectors for LAN traffic */
-       needed = min_t(int, num_online_cpus(), v_left);
+       needed = num_cpus;
        if (v_left < needed)
                goto no_hw_vecs_left_err;
        pf->num_lan_msix = needed;
        v_budget += needed;
        v_left -= needed;
 
+       /* reserve vectors for RDMA auxiliary driver */
+       if (test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) {
+               needed = num_cpus + ICE_RDMA_NUM_AEQ_MSIX;
+               if (v_left < needed)
+                       goto no_hw_vecs_left_err;
+               pf->num_rdma_msix = needed;
+               v_budget += needed;
+               v_left -= needed;
+       }
+
        pf->msix_entries = devm_kcalloc(dev, v_budget,
                                        sizeof(*pf->msix_entries), GFP_KERNEL);
        if (!pf->msix_entries) {
@@ -3431,16 +3588,46 @@ static int ice_ena_msix_range(struct ice_pf *pf)
                        err = -ERANGE;
                        goto msix_err;
                } else {
-                       int v_traffic = v_actual - v_other;
+                       int v_remain = v_actual - v_other;
+                       int v_rdma = 0, v_min_rdma = 0;
+
+                       if (test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) {
+                               /* Need at least 1 interrupt in addition to
+                                * AEQ MSIX
+                                */
+                               v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1;
+                               v_min_rdma = ICE_MIN_RDMA_MSIX;
+                       }
 
                        if (v_actual == ICE_MIN_MSIX ||
-                           v_traffic < ICE_MIN_LAN_TXRX_MSIX)
+                           v_remain < ICE_MIN_LAN_TXRX_MSIX + v_min_rdma) {
+                               dev_warn(dev, "Not enough MSI-X vectors to support RDMA.\n");
+                               clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+
+                               pf->num_rdma_msix = 0;
                                pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX;
-                       else
-                               pf->num_lan_msix = v_traffic;
+                       } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) ||
+                                  (v_remain - v_rdma < v_rdma)) {
+                               /* Support minimum RDMA and give remaining
+                                * vectors to LAN MSIX
+                                */
+                               pf->num_rdma_msix = v_min_rdma;
+                               pf->num_lan_msix = v_remain - v_min_rdma;
+                       } else {
+                               /* Split remaining MSIX with RDMA after
+                                * accounting for AEQ MSIX
+                                */
+                               pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 +
+                                                   ICE_RDMA_NUM_AEQ_MSIX;
+                               pf->num_lan_msix = v_remain - pf->num_rdma_msix;
+                       }
 
                        dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n",
                                   pf->num_lan_msix);
+
+                       if (test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
+                               dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n",
+                                          pf->num_rdma_msix);
                }
        }
 
@@ -3455,6 +3642,7 @@ no_hw_vecs_left_err:
                needed, v_left);
        err = -ERANGE;
 exit_err:
+       pf->num_rdma_msix = 0;
        pf->num_lan_msix = 0;
        return err;
 }
@@ -4014,6 +4202,11 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
        struct ice_hw *hw;
        int i, err;
 
+       if (pdev->is_virtfn) {
+               dev_err(dev, "can't probe a virtual function\n");
+               return -EINVAL;
+       }
+
        /* this driver uses devres, see
         * Documentation/driver-api/driver-model/devres.rst
         */
@@ -4218,6 +4411,8 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
 
        ice_init_link_dflt_override(pf->hw.port_info);
 
+       ice_check_module_power(pf, pf->hw.port_info->phy.link_info.link_cfg_err);
+
        /* if media available, initialize PHY settings */
        if (pf->hw.port_info->phy.link_info.link_info &
            ICE_AQ_MEDIA_AVAILABLE) {
@@ -4256,6 +4451,8 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
        }
 
        /* initialize DDP driven features */
+       if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
+               ice_ptp_init(pf);
 
        /* Note: Flow director init failure is non-fatal to load */
        if (ice_init_fdir(pf))
@@ -4282,8 +4479,29 @@ probe_done:
 
        /* ready to go, so clear down state bit */
        clear_bit(ICE_DOWN, pf->state);
+       if (ice_is_aux_ena(pf)) {
+               pf->aux_idx = ida_alloc(&ice_aux_ida, GFP_KERNEL);
+               if (pf->aux_idx < 0) {
+                       dev_err(dev, "Failed to allocate device ID for AUX driver\n");
+                       err = -ENOMEM;
+                       goto err_netdev_reg;
+               }
+
+               err = ice_init_rdma(pf);
+               if (err) {
+                       dev_err(dev, "Failed to initialize RDMA: %d\n", err);
+                       err = -EIO;
+                       goto err_init_aux_unroll;
+               }
+       } else {
+               dev_warn(dev, "RDMA is not supported on this device\n");
+       }
+
        return 0;
 
+err_init_aux_unroll:
+       pf->adev = NULL;
+       ida_free(&ice_aux_ida, pf->aux_idx);
 err_netdev_reg:
 err_send_version_unroll:
        ice_vsi_release_all(pf);
@@ -4393,13 +4611,17 @@ static void ice_remove(struct pci_dev *pdev)
                ice_free_vfs(pf);
        }
 
-       set_bit(ICE_DOWN, pf->state);
        ice_service_task_stop(pf);
 
        ice_aq_cancel_waiting_tasks(pf);
+       ice_unplug_aux_dev(pf);
+       ida_free(&ice_aux_ida, pf->aux_idx);
+       set_bit(ICE_DOWN, pf->state);
 
        mutex_destroy(&(&pf->hw)->fdir_fltr_lock);
        ice_deinit_lag(pf);
+       if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
+               ice_ptp_release(pf);
        if (!ice_is_safe_mode(pf))
                ice_remove_arfs(pf);
        ice_setup_mc_magic_wake(pf);
@@ -4552,6 +4774,8 @@ static int __maybe_unused ice_suspend(struct device *dev)
         */
        disabled = ice_service_task_stop(pf);
 
+       ice_unplug_aux_dev(pf);
+
        /* Already suspended?, then there is nothing to do */
        if (test_and_set_bit(ICE_SUSPENDED, pf->state)) {
                if (!disabled)
@@ -4898,6 +5122,7 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
        struct ice_hw *hw = &pf->hw;
        struct sockaddr *addr = pi;
        enum ice_status status;
+       u8 old_mac[ETH_ALEN];
        u8 flags = 0;
        int err = 0;
        u8 *mac;
@@ -4908,7 +5133,7 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
                return -EADDRNOTAVAIL;
 
        if (ether_addr_equal(netdev->dev_addr, mac)) {
-               netdev_warn(netdev, "already using mac %pM\n", mac);
+               netdev_dbg(netdev, "already using mac %pM\n", mac);
                return 0;
        }
 
@@ -4919,8 +5144,14 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
                return -EBUSY;
        }
 
+       netif_addr_lock_bh(netdev);
+       ether_addr_copy(old_mac, netdev->dev_addr);
+       /* change the netdev's MAC address */
+       memcpy(netdev->dev_addr, mac, netdev->addr_len);
+       netif_addr_unlock_bh(netdev);
+
        /* Clean up old MAC filter. Not an error if old filter doesn't exist */
-       status = ice_fltr_remove_mac(vsi, netdev->dev_addr, ICE_FWD_TO_VSI);
+       status = ice_fltr_remove_mac(vsi, old_mac, ICE_FWD_TO_VSI);
        if (status && status != ICE_ERR_DOES_NOT_EXIST) {
                err = -EADDRNOTAVAIL;
                goto err_update_filters;
@@ -4928,30 +5159,27 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
 
        /* Add filter for new MAC. If filter exists, return success */
        status = ice_fltr_add_mac(vsi, mac, ICE_FWD_TO_VSI);
-       if (status == ICE_ERR_ALREADY_EXISTS) {
+       if (status == ICE_ERR_ALREADY_EXISTS)
                /* Although this MAC filter is already present in hardware it's
                 * possible in some cases (e.g. bonding) that dev_addr was
                 * modified outside of the driver and needs to be restored back
                 * to this value.
                 */
-               memcpy(netdev->dev_addr, mac, netdev->addr_len);
                netdev_dbg(netdev, "filter for MAC %pM already exists\n", mac);
-               return 0;
-       }
-
-       /* error if the new filter addition failed */
-       if (status)
+       else if (status)
+               /* error if the new filter addition failed */
                err = -EADDRNOTAVAIL;
 
 err_update_filters:
        if (err) {
                netdev_err(netdev, "can't set MAC %pM. filter update failed\n",
                           mac);
+               netif_addr_lock_bh(netdev);
+               ether_addr_copy(netdev->dev_addr, old_mac);
+               netif_addr_unlock_bh(netdev);
                return err;
        }
 
-       /* change the netdev's MAC address */
-       memcpy(netdev->dev_addr, mac, netdev->addr_len);
        netdev_dbg(vsi->netdev, "updated MAC address to %pM\n",
                   netdev->dev_addr);
 
@@ -5284,6 +5512,7 @@ static void ice_tx_dim_work(struct work_struct *work)
        itr = tx_profile[dim->profile_ix].itr;
        intrl = tx_profile[dim->profile_ix].intrl;
 
+       ice_trace(tx_dim_work, q_vector, dim);
        ice_write_itr(rc, itr);
        ice_write_intrl(q_vector, intrl);
 
@@ -5308,6 +5537,7 @@ static void ice_rx_dim_work(struct work_struct *work)
        itr = rx_profile[dim->profile_ix].itr;
        intrl = rx_profile[dim->profile_ix].intrl;
 
+       ice_trace(rx_dim_work, q_vector, dim);
        ice_write_itr(rc, itr);
        ice_write_intrl(q_vector, intrl);
 
@@ -5451,7 +5681,6 @@ ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, struct ice_ring **rings,
 static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
 {
        struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
-       struct ice_ring *ring;
        u64 pkts, bytes;
        int i;
 
@@ -5475,7 +5704,8 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
 
        /* update Rx rings counters */
        ice_for_each_rxq(vsi, i) {
-               ring = READ_ONCE(vsi->rx_rings[i]);
+               struct ice_ring *ring = READ_ONCE(vsi->rx_rings[i]);
+
                ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
                vsi_stats->rx_packets += pkts;
                vsi_stats->rx_bytes += bytes;
@@ -6142,6 +6372,12 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
 
        ice_clear_pxe_mode(hw);
 
+       ret = ice_init_nvm(hw);
+       if (ret) {
+               dev_err(dev, "ice_init_nvm failed %s\n", ice_stat_str(ret));
+               goto err_init_ctrlq;
+       }
+
        ret = ice_get_caps(hw);
        if (ret) {
                dev_err(dev, "ice_get_caps failed %s\n", ice_stat_str(ret));
@@ -6183,6 +6419,13 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
        if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
                ice_dcb_rebuild(pf);
 
+       /* If the PF previously had enabled PTP, PTP init needs to happen before
+        * the VSI rebuild. If not, this causes the PTP link status events to
+        * fail.
+        */
+       if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
+               ice_ptp_init(pf);
+
        /* rebuild PF VSI */
        err = ice_vsi_rebuild_by_type(pf, ICE_VSI_PF);
        if (err) {
@@ -6222,6 +6465,8 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
 
        /* if we get here, reset flow is successful */
        clear_bit(ICE_RESET_FAILED, pf->state);
+
+       ice_plug_aux_dev(pf);
        return;
 
 err_vsi_rebuild:
@@ -6260,7 +6505,9 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_vsi *vsi = np->vsi;
        struct ice_pf *pf = vsi->back;
+       struct iidc_event *event;
        u8 count = 0;
+       int err = 0;
 
        if (new_mtu == (int)netdev->mtu) {
                netdev_warn(netdev, "MTU is already %u\n", netdev->mtu);
@@ -6293,27 +6540,59 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
                return -EBUSY;
        }
 
+       event = kzalloc(sizeof(*event), GFP_KERNEL);
+       if (!event)
+               return -ENOMEM;
+
+       set_bit(IIDC_EVENT_BEFORE_MTU_CHANGE, event->type);
+       ice_send_event_to_aux(pf, event);
+       clear_bit(IIDC_EVENT_BEFORE_MTU_CHANGE, event->type);
+
        netdev->mtu = (unsigned int)new_mtu;
 
        /* if VSI is up, bring it down and then back up */
        if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {
-               int err;
-
                err = ice_down(vsi);
                if (err) {
                        netdev_err(netdev, "change MTU if_down err %d\n", err);
-                       return err;
+                       goto event_after;
                }
 
                err = ice_up(vsi);
                if (err) {
                        netdev_err(netdev, "change MTU if_up err %d\n", err);
-                       return err;
+                       goto event_after;
                }
        }
 
        netdev_dbg(netdev, "changed MTU to %d\n", new_mtu);
-       return 0;
+event_after:
+       set_bit(IIDC_EVENT_AFTER_MTU_CHANGE, event->type);
+       ice_send_event_to_aux(pf, event);
+       kfree(event);
+
+       return err;
+}
+
+/**
+ * ice_eth_ioctl - Access the hwtstamp interface
+ * @netdev: network interface device structure
+ * @ifr: interface request data
+ * @cmd: ioctl command
+ */
+static int ice_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+       struct ice_netdev_priv *np = netdev_priv(netdev);
+       struct ice_pf *pf = np->vsi->back;
+
+       switch (cmd) {
+       case SIOCGHWTSTAMP:
+               return ice_ptp_get_ts_config(pf, ifr);
+       case SIOCSHWTSTAMP:
+               return ice_ptp_set_ts_config(pf, ifr);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 /**
@@ -6832,6 +7111,8 @@ int ice_open_internal(struct net_device *netdev)
                return -EIO;
        }
 
+       ice_check_module_power(pf, pi->phy.link_info.link_cfg_err);
+
        /* Set PHY if there is media, otherwise, turn off PHY */
        if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
                clear_bit(ICE_FLAG_NO_MEDIA, pf->flags);
@@ -6965,6 +7246,7 @@ static const struct net_device_ops ice_netdev_ops = {
        .ndo_change_mtu = ice_change_mtu,
        .ndo_get_stats64 = ice_get_stats64,
        .ndo_set_tx_maxrate = ice_set_tx_maxrate,
+       .ndo_eth_ioctl = ice_eth_ioctl,
        .ndo_set_vf_spoofchk = ice_set_vf_spoofchk,
        .ndo_set_vf_mac = ice_set_vf_mac,
        .ndo_get_vf_config = ice_get_vf_cfg,