return (u8 __iomem *)ERR_PTR(err);
 }
 
+/**
+ * nfp_net_get_mac_addr() - Get the MAC address.
+ * @nn:       NFP Network structure
+ * @cpp:      NFP CPP handle
+ * @id:              NFP port id
+ *
+ * First try to get the MAC address from NSP ETH table. If that
+ * fails try HWInfo.  As a last resort generate a random address.
+ */
 static void
-nfp_net_get_mac_addr_hwinfo(struct nfp_net_dp *dp, struct nfp_cpp *cpp,
-                           unsigned int id)
+nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_cpp *cpp, unsigned int id)
 {
+       struct nfp_net_dp *dp = &nn->dp;
        u8 mac_addr[ETH_ALEN];
        const char *mac_str;
        char name[32];
 
+       if (nn->eth_port) {
+               ether_addr_copy(dp->netdev->dev_addr, nn->eth_port->mac_addr);
+               ether_addr_copy(dp->netdev->perm_addr, nn->eth_port->mac_addr);
+               return;
+       }
+
        snprintf(name, sizeof(name), "eth%d.mac", id);
 
        mac_str = nfp_hwinfo_lookup(cpp, name);
        ether_addr_copy(dp->netdev->perm_addr, mac_addr);
 }
 
-/**
- * nfp_net_get_mac_addr() - Get the MAC address.
- * @nn:       NFP Network structure
- * @pf:              NFP PF device structure
- * @id:              NFP port id
- *
- * First try to get the MAC address from NSP ETH table. If that
- * fails try HWInfo.  As a last resort generate a random address.
- */
-static void
-nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_pf *pf, unsigned int id)
+static struct nfp_eth_table_port *
+nfp_net_find_port(struct nfp_pf *pf, unsigned int id)
 {
        int i;
 
        for (i = 0; pf->eth_tbl && i < pf->eth_tbl->count; i++)
-               if (pf->eth_tbl->ports[i].eth_index == id) {
-                       const u8 *mac_addr = pf->eth_tbl->ports[i].mac_addr;
-
-                       nn->eth_port = &pf->eth_tbl->ports[i];
+               if (pf->eth_tbl->ports[i].eth_index == id)
+                       return &pf->eth_tbl->ports[i];
 
-                       ether_addr_copy(nn->dp.netdev->dev_addr, mac_addr);
-                       ether_addr_copy(nn->dp.netdev->perm_addr, mac_addr);
-                       return;
-               }
-
-       nfp_net_get_mac_addr_hwinfo(&nn->dp, pf->cpp, id);
+       return NULL;
 }
 
 static unsigned int nfp_net_pf_get_num_ports(struct nfp_pf *pf)
        while (!list_empty(&pf->ports)) {
                nn = list_first_entry(&pf->ports, struct nfp_net, port_list);
                list_del(&nn->port_list);
+               pf->num_netdevs--;
 
                nfp_net_netdev_free(nn);
        }
 static struct nfp_net *
 nfp_net_pf_alloc_port_netdev(struct nfp_pf *pf, void __iomem *ctrl_bar,
                             void __iomem *tx_bar, void __iomem *rx_bar,
-                            int stride, struct nfp_net_fw_version *fw_ver)
+                            int stride, struct nfp_net_fw_version *fw_ver,
+                            struct nfp_eth_table_port *eth_port)
 {
        u32 n_tx_rings, n_rx_rings;
        struct nfp_net *nn;
        nn->dp.is_vf = 0;
        nn->stride_rx = stride;
        nn->stride_tx = stride;
+       nn->eth_port = eth_port;
 
        return nn;
 }
        int err;
 
        /* Get MAC address */
-       nfp_net_get_mac_addr(nn, pf, id);
+       nfp_net_get_mac_addr(nn, pf->cpp, id);
 
        /* Get ME clock frequency from ctrl BAR
         * XXX for now frequency is hardcoded until we figure out how
                         int stride, struct nfp_net_fw_version *fw_ver)
 {
        u32 prev_tx_base, prev_rx_base, tgt_tx_base, tgt_rx_base;
+       struct nfp_eth_table_port *eth_port;
        struct nfp_net *nn;
        unsigned int i;
        int err;
                prev_tx_base = tgt_tx_base;
                prev_rx_base = tgt_rx_base;
 
-               nn = nfp_net_pf_alloc_port_netdev(pf, ctrl_bar, tx_bar, rx_bar,
-                                                 stride, fw_ver);
-               if (IS_ERR(nn)) {
-                       err = PTR_ERR(nn);
-                       goto err_free_prev;
+               eth_port = nfp_net_find_port(pf, i);
+               if (eth_port && eth_port->override_changed) {
+                       nfp_warn(pf->cpp, "Config changed for port #%d, reboot required before port will be operational\n", i);
+               } else {
+                       nn = nfp_net_pf_alloc_port_netdev(pf, ctrl_bar, tx_bar,
+                                                         rx_bar, stride,
+                                                         fw_ver, eth_port);
+                       if (IS_ERR(nn)) {
+                               err = PTR_ERR(nn);
+                               goto err_free_prev;
+                       }
+                       list_add_tail(&nn->port_list, &pf->ports);
+                       pf->num_netdevs++;
                }
-               list_add_tail(&nn->port_list, &pf->ports);
 
                ctrl_bar += NFP_PF_CSR_SLICE_SIZE;
        }
 
+       if (list_empty(&pf->ports))
+               return -ENODEV;
+
        return 0;
 
 err_free_prev:
        }
 
        num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries,
-                                     NFP_NET_MIN_PORT_IRQS * pf->num_ports,
+                                     NFP_NET_MIN_PORT_IRQS * pf->num_netdevs,
                                      wanted_irqs);
        if (!num_irqs) {
                nn_warn(nn, "Unable to allocate MSI-X Vectors. Exiting\n");
 
        /* Distribute IRQs to ports */
        irqs_left = num_irqs;
-       ports_left = pf->num_ports;
+       ports_left = pf->num_netdevs;
        list_for_each_entry(nn, &pf->ports, port_list) {
                unsigned int n;
 
 
 #define NSP_ETH_STATE_TX_ENABLED       BIT_ULL(2)
 #define NSP_ETH_STATE_RX_ENABLED       BIT_ULL(3)
 #define NSP_ETH_STATE_RATE             GENMASK_ULL(11, 8)
+#define NSP_ETH_STATE_OVRD_CHNG                BIT_ULL(22)
 
 #define NSP_ETH_CTRL_ENABLED           BIT_ULL(1)
 #define NSP_ETH_CTRL_TX_ENABLED                BIT_ULL(2)
 }
 
 static void
-nfp_eth_port_translate(const struct eth_table_entry *src, unsigned int index,
-                      struct nfp_eth_table_port *dst)
+nfp_eth_port_translate(struct nfp_nsp *nsp, const struct eth_table_entry *src,
+                      unsigned int index, struct nfp_eth_table_port *dst)
 {
        unsigned int rate;
        u64 port, state;
 
        dst->label_port = FIELD_GET(NSP_ETH_PORT_PHYLABEL, port);
        dst->label_subport = FIELD_GET(NSP_ETH_PORT_LABEL, port);
+
+       if (nfp_nsp_get_abi_ver_minor(nsp) < 17)
+               return;
+
+       dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state);
 }
 
 static void
        table->count = cnt;
        for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
                if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
-                       nfp_eth_port_translate(&entries[i], i,
+                       nfp_eth_port_translate(nsp, &entries[i], i,
                                               &table->ports[j++]);
 
        nfp_eth_mark_split_ports(cpp, table);