]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/net/ethernet/broadcom/bnxt/bnxt.c
bnxt_en: use link_lock instead of hwrm_cmd_lock to protect link_info
[mirror_ubuntu-jammy-kernel.git] / drivers / net / ethernet / broadcom / bnxt / bnxt.c
index 8a97640cdfe761e3d4be2af5114522733d591408..b9aa56cc10d2baad1368e7ec9a53a9182ea3bec2 100644 (file)
@@ -60,6 +60,7 @@
 
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_ulp.h"
 #include "bnxt_sriov.h"
 #include "bnxt_ethtool.h"
@@ -278,6 +279,8 @@ static const u16 bnxt_async_events_arr[] = {
        ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION,
        ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG,
        ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST,
+       ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP,
+       ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT,
 };
 
 static struct workqueue_struct *bnxt_pf_wq;
@@ -670,7 +673,7 @@ tx_dma_error:
        prod = txr->tx_prod;
        tx_buf = &txr->tx_buf_ring[prod];
        dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
-                        skb_headlen(skb), PCI_DMA_TODEVICE);
+                        skb_headlen(skb), DMA_TO_DEVICE);
        prod = NEXT_TX(prod);
 
        /* unmap remaining mapped pages */
@@ -679,7 +682,7 @@ tx_dma_error:
                tx_buf = &txr->tx_buf_ring[prod];
                dma_unmap_page(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
                               skb_frag_size(&skb_shinfo(skb)->frags[i]),
-                              PCI_DMA_TODEVICE);
+                              DMA_TO_DEVICE);
        }
 
 tx_free:
@@ -718,7 +721,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
                }
 
                dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
-                                skb_headlen(skb), PCI_DMA_TODEVICE);
+                                skb_headlen(skb), DMA_TO_DEVICE);
                last = tx_buf->nr_frags;
 
                for (j = 0; j < last; j++) {
@@ -728,7 +731,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
                                &pdev->dev,
                                dma_unmap_addr(tx_buf, mapping),
                                skb_frag_size(&skb_shinfo(skb)->frags[j]),
-                               PCI_DMA_TODEVICE);
+                               DMA_TO_DEVICE);
                }
                if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
                        if (bp->flags & BNXT_FLAG_CHIP_P5) {
@@ -901,7 +904,7 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp,
        }
 
        mapping = dma_map_page_attrs(&pdev->dev, page, offset,
-                                    BNXT_RX_PAGE_SIZE, PCI_DMA_FROMDEVICE,
+                                    BNXT_RX_PAGE_SIZE, DMA_FROM_DEVICE,
                                     DMA_ATTR_WEAK_ORDERING);
        if (dma_mapping_error(&pdev->dev, mapping)) {
                __free_page(page);
@@ -1141,7 +1144,7 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp,
                }
 
                dma_unmap_page_attrs(&pdev->dev, mapping, BNXT_RX_PAGE_SIZE,
-                                    PCI_DMA_FROMDEVICE,
+                                    DMA_FROM_DEVICE,
                                     DMA_ATTR_WEAK_ORDERING);
 
                skb->data_len += frag_len;
@@ -1649,6 +1652,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping);
                if (!skb) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        } else {
@@ -1658,6 +1662,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                new_data = __bnxt_alloc_rx_data(bp, &new_mapping, GFP_ATOMIC);
                if (!new_data) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
 
@@ -1673,6 +1678,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                if (!skb) {
                        kfree(data);
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
                skb_reserve(skb, bp->rx_offset);
@@ -1683,6 +1689,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_rx_pages(bp, cpr, skb, idx, agg_bufs, true);
                if (!skb) {
                        /* Page reuse already handled by bnxt_rx_pages(). */
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        }
@@ -1886,6 +1893,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        if (agg_bufs)
                                bnxt_reuse_rx_agg_bufs(cpr, cp_cons, 0,
                                                       agg_bufs, false);
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        rc = -ENOMEM;
                        goto next_rx;
                }
@@ -1899,6 +1907,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                skb = bp->rx_skb_func(bp, rxr, cons, data, data_ptr, dma_addr,
                                      payload | len);
                if (!skb) {
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        rc = -ENOMEM;
                        goto next_rx;
                }
@@ -1907,6 +1916,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        if (agg_bufs) {
                skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs, false);
                if (!skb) {
+                       cpr->sw_stats.rx.rx_oom_discards += 1;
                        rc = -ENOMEM;
                        goto next_rx;
                }
@@ -2001,6 +2011,7 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
        struct rx_cmp *rxcmp;
        u16 cp_cons;
        u8 cmp_type;
+       int rc;
 
        cp_cons = RING_CMP(tmp_raw_cons);
        rxcmp = (struct rx_cmp *)
@@ -2029,7 +2040,10 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
                tpa_end1->rx_tpa_end_cmp_errors_v2 |=
                        cpu_to_le32(RX_TPA_END_CMP_ERRORS);
        }
-       return bnxt_rx_pkt(bp, cpr, raw_cons, event);
+       rc = bnxt_rx_pkt(bp, cpr, raw_cons, event);
+       if (rc && rc != -EBUSY)
+               cpr->sw_stats.rx.rx_netpoll_discards += 1;
+       return rc;
 }
 
 u32 bnxt_fw_health_readl(struct bnxt *bp, int reg_idx)
@@ -2074,6 +2088,19 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id)
        return INVALID_HW_RING_ID;
 }
 
+static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
+{
+       switch (BNXT_EVENT_ERROR_REPORT_TYPE(data1)) {
+       case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL:
+               netdev_err(bp->dev, "1PPS: Received invalid signal on pin%lu from the external source. Please fix the signal and reconfigure the pin\n",
+                          BNXT_EVENT_INVALID_SIGNAL_DATA(data2));
+               break;
+       default:
+               netdev_err(bp->dev, "FW reported unknown error type\n");
+               break;
+       }
+}
+
 #define BNXT_GET_EVENT_PORT(data)      \
        ((data) &                       \
         ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
@@ -2234,6 +2261,14 @@ static int bnxt_async_event_process(struct bnxt *bp,
                }
                goto async_event_process_exit;
        }
+       case ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP: {
+               bnxt_ptp_pps_event(bp, data1, data2);
+               goto async_event_process_exit;
+       }
+       case ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT: {
+               bnxt_event_error_report(bp, data1, data2);
+               goto async_event_process_exit;
+       }
        default:
                goto async_event_process_exit;
        }
@@ -2690,7 +2725,7 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
                                dma_unmap_single(&pdev->dev,
                                        dma_unmap_addr(tx_buf, mapping),
                                        dma_unmap_len(tx_buf, len),
-                                       PCI_DMA_TODEVICE);
+                                       DMA_TO_DEVICE);
                                xdp_return_frame(tx_buf->xdpf);
                                tx_buf->action = 0;
                                tx_buf->xdpf = NULL;
@@ -2715,7 +2750,7 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
                        dma_unmap_single(&pdev->dev,
                                         dma_unmap_addr(tx_buf, mapping),
                                         skb_headlen(skb),
-                                        PCI_DMA_TODEVICE);
+                                        DMA_TO_DEVICE);
 
                        last = tx_buf->nr_frags;
                        j += 2;
@@ -2727,7 +2762,7 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
                                dma_unmap_page(
                                        &pdev->dev,
                                        dma_unmap_addr(tx_buf, mapping),
-                                       skb_frag_size(frag), PCI_DMA_TODEVICE);
+                                       skb_frag_size(frag), DMA_TO_DEVICE);
                        }
                        dev_kfree_skb(skb);
                }
@@ -2794,7 +2829,7 @@ skip_rx_tpa_free:
                        continue;
 
                dma_unmap_page_attrs(&pdev->dev, rx_agg_buf->mapping,
-                                    BNXT_RX_PAGE_SIZE, PCI_DMA_FROMDEVICE,
+                                    BNXT_RX_PAGE_SIZE, DMA_FROM_DEVICE,
                                     DMA_ATTR_WEAK_ORDERING);
 
                rx_agg_buf->page = NULL;
@@ -3176,6 +3211,58 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
        return 0;
 }
 
+static void bnxt_free_cp_arrays(struct bnxt_cp_ring_info *cpr)
+{
+       kfree(cpr->cp_desc_ring);
+       cpr->cp_desc_ring = NULL;
+       kfree(cpr->cp_desc_mapping);
+       cpr->cp_desc_mapping = NULL;
+}
+
+static int bnxt_alloc_cp_arrays(struct bnxt_cp_ring_info *cpr, int n)
+{
+       cpr->cp_desc_ring = kcalloc(n, sizeof(*cpr->cp_desc_ring), GFP_KERNEL);
+       if (!cpr->cp_desc_ring)
+               return -ENOMEM;
+       cpr->cp_desc_mapping = kcalloc(n, sizeof(*cpr->cp_desc_mapping),
+                                      GFP_KERNEL);
+       if (!cpr->cp_desc_mapping)
+               return -ENOMEM;
+       return 0;
+}
+
+static void bnxt_free_all_cp_arrays(struct bnxt *bp)
+{
+       int i;
+
+       if (!bp->bnapi)
+               return;
+       for (i = 0; i < bp->cp_nr_rings; i++) {
+               struct bnxt_napi *bnapi = bp->bnapi[i];
+
+               if (!bnapi)
+                       continue;
+               bnxt_free_cp_arrays(&bnapi->cp_ring);
+       }
+}
+
+static int bnxt_alloc_all_cp_arrays(struct bnxt *bp)
+{
+       int i, n = bp->cp_nr_pages;
+
+       for (i = 0; i < bp->cp_nr_rings; i++) {
+               struct bnxt_napi *bnapi = bp->bnapi[i];
+               int rc;
+
+               if (!bnapi)
+                       continue;
+               rc = bnxt_alloc_cp_arrays(&bnapi->cp_ring, n);
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
+
 static void bnxt_free_cp_rings(struct bnxt *bp)
 {
        int i;
@@ -3203,6 +3290,7 @@ static void bnxt_free_cp_rings(struct bnxt *bp)
                        if (cpr2) {
                                ring = &cpr2->cp_ring_struct;
                                bnxt_free_ring(bp, &ring->ring_mem);
+                               bnxt_free_cp_arrays(cpr2);
                                kfree(cpr2);
                                cpr->cp_ring_arr[j] = NULL;
                        }
@@ -3221,6 +3309,12 @@ static struct bnxt_cp_ring_info *bnxt_alloc_cp_sub_ring(struct bnxt *bp)
        if (!cpr)
                return NULL;
 
+       rc = bnxt_alloc_cp_arrays(cpr, bp->cp_nr_pages);
+       if (rc) {
+               bnxt_free_cp_arrays(cpr);
+               kfree(cpr);
+               return NULL;
+       }
        ring = &cpr->cp_ring_struct;
        rmem = &ring->ring_mem;
        rmem->nr_pages = bp->cp_nr_pages;
@@ -3231,6 +3325,7 @@ static struct bnxt_cp_ring_info *bnxt_alloc_cp_sub_ring(struct bnxt *bp)
        rc = bnxt_alloc_ring(bp, rmem);
        if (rc) {
                bnxt_free_ring(bp, rmem);
+               bnxt_free_cp_arrays(cpr);
                kfree(cpr);
                cpr = NULL;
        }
@@ -3663,9 +3758,15 @@ void bnxt_set_ring_params(struct bnxt *bp)
                if (jumbo_factor > agg_factor)
                        agg_factor = jumbo_factor;
        }
-       agg_ring_size = ring_size * agg_factor;
+       if (agg_factor) {
+               if (ring_size > BNXT_MAX_RX_DESC_CNT_JUM_ENA) {
+                       ring_size = BNXT_MAX_RX_DESC_CNT_JUM_ENA;
+                       netdev_warn(bp->dev, "RX ring size reduced from %d to %d because the jumbo ring is now enabled\n",
+                                   bp->rx_ring_size, ring_size);
+                       bp->rx_ring_size = ring_size;
+               }
+               agg_ring_size = ring_size * agg_factor;
 
-       if (agg_ring_size) {
                bp->rx_agg_nr_pages = bnxt_calc_nr_ring_pages(agg_ring_size,
                                                        RX_DESC_CNT);
                if (bp->rx_agg_nr_pages > MAX_RX_AGG_PAGES) {
@@ -3863,29 +3964,8 @@ static void bnxt_free_hwrm_resources(struct bnxt *bp)
                bp->hwrm_cmd_resp_addr = NULL;
        }
 
-       if (bp->hwrm_cmd_kong_resp_addr) {
-               dma_free_coherent(&pdev->dev, PAGE_SIZE,
-                                 bp->hwrm_cmd_kong_resp_addr,
-                                 bp->hwrm_cmd_kong_resp_dma_addr);
-               bp->hwrm_cmd_kong_resp_addr = NULL;
-       }
-}
-
-static int bnxt_alloc_kong_hwrm_resources(struct bnxt *bp)
-{
-       struct pci_dev *pdev = bp->pdev;
-
-       if (bp->hwrm_cmd_kong_resp_addr)
-               return 0;
-
-       bp->hwrm_cmd_kong_resp_addr =
-               dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
-                                  &bp->hwrm_cmd_kong_resp_dma_addr,
-                                  GFP_KERNEL);
-       if (!bp->hwrm_cmd_kong_resp_addr)
-               return -ENOMEM;
-
-       return 0;
+       dma_pool_destroy(bp->hwrm_dma_pool);
+       bp->hwrm_dma_pool = NULL;
 }
 
 static int bnxt_alloc_hwrm_resources(struct bnxt *bp)
@@ -3898,33 +3978,10 @@ static int bnxt_alloc_hwrm_resources(struct bnxt *bp)
        if (!bp->hwrm_cmd_resp_addr)
                return -ENOMEM;
 
-       return 0;
-}
-
-static void bnxt_free_hwrm_short_cmd_req(struct bnxt *bp)
-{
-       if (bp->hwrm_short_cmd_req_addr) {
-               struct pci_dev *pdev = bp->pdev;
-
-               dma_free_coherent(&pdev->dev, bp->hwrm_max_ext_req_len,
-                                 bp->hwrm_short_cmd_req_addr,
-                                 bp->hwrm_short_cmd_req_dma_addr);
-               bp->hwrm_short_cmd_req_addr = NULL;
-       }
-}
-
-static int bnxt_alloc_hwrm_short_cmd_req(struct bnxt *bp)
-{
-       struct pci_dev *pdev = bp->pdev;
-
-       if (bp->hwrm_short_cmd_req_addr)
-               return 0;
-
-       bp->hwrm_short_cmd_req_addr =
-               dma_alloc_coherent(&pdev->dev, bp->hwrm_max_ext_req_len,
-                                  &bp->hwrm_short_cmd_req_dma_addr,
-                                  GFP_KERNEL);
-       if (!bp->hwrm_short_cmd_req_addr)
+       bp->hwrm_dma_pool = dma_pool_create("bnxt_hwrm", &pdev->dev,
+                                           BNXT_HWRM_DMA_SIZE,
+                                           BNXT_HWRM_DMA_ALIGN, 0);
+       if (!bp->hwrm_dma_pool)
                return -ENOMEM;
 
        return 0;
@@ -4266,6 +4323,7 @@ static void bnxt_free_mem(struct bnxt *bp, bool irq_re_init)
        bnxt_free_tx_rings(bp);
        bnxt_free_rx_rings(bp);
        bnxt_free_cp_rings(bp);
+       bnxt_free_all_cp_arrays(bp);
        bnxt_free_ntp_fltrs(bp, irq_re_init);
        if (irq_re_init) {
                bnxt_free_ring_stats(bp);
@@ -4386,6 +4444,10 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
                        goto alloc_mem_err;
        }
 
+       rc = bnxt_alloc_all_cp_arrays(bp);
+       if (rc)
+               goto alloc_mem_err;
+
        bnxt_init_ring_struct(bp);
 
        rc = bnxt_alloc_rx_rings(bp);
@@ -4468,282 +4530,6 @@ static void bnxt_enable_int(struct bnxt *bp)
        }
 }
 
-void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type,
-                           u16 cmpl_ring, u16 target_id)
-{
-       struct input *req = request;
-
-       req->req_type = cpu_to_le16(req_type);
-       req->cmpl_ring = cpu_to_le16(cmpl_ring);
-       req->target_id = cpu_to_le16(target_id);
-       if (bnxt_kong_hwrm_message(bp, req))
-               req->resp_addr = cpu_to_le64(bp->hwrm_cmd_kong_resp_dma_addr);
-       else
-               req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
-}
-
-static int bnxt_hwrm_to_stderr(u32 hwrm_err)
-{
-       switch (hwrm_err) {
-       case HWRM_ERR_CODE_SUCCESS:
-               return 0;
-       case HWRM_ERR_CODE_RESOURCE_LOCKED:
-               return -EROFS;
-       case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
-               return -EACCES;
-       case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
-               return -ENOSPC;
-       case HWRM_ERR_CODE_INVALID_PARAMS:
-       case HWRM_ERR_CODE_INVALID_FLAGS:
-       case HWRM_ERR_CODE_INVALID_ENABLES:
-       case HWRM_ERR_CODE_UNSUPPORTED_TLV:
-       case HWRM_ERR_CODE_UNSUPPORTED_OPTION_ERR:
-               return -EINVAL;
-       case HWRM_ERR_CODE_NO_BUFFER:
-               return -ENOMEM;
-       case HWRM_ERR_CODE_HOT_RESET_PROGRESS:
-       case HWRM_ERR_CODE_BUSY:
-               return -EAGAIN;
-       case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
-               return -EOPNOTSUPP;
-       default:
-               return -EIO;
-       }
-}
-
-static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
-                                int timeout, bool silent)
-{
-       int i, intr_process, rc, tmo_count;
-       struct input *req = msg;
-       u32 *data = msg;
-       u8 *valid;
-       u16 cp_ring_id, len = 0;
-       struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr;
-       u16 max_req_len = BNXT_HWRM_MAX_REQ_LEN;
-       struct hwrm_short_input short_input = {0};
-       u32 doorbell_offset = BNXT_GRCPF_REG_CHIMP_COMM_TRIGGER;
-       u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
-       u16 dst = BNXT_HWRM_CHNL_CHIMP;
-
-       if (BNXT_NO_FW_ACCESS(bp) &&
-           le16_to_cpu(req->req_type) != HWRM_FUNC_RESET)
-               return -EBUSY;
-
-       if (msg_len > BNXT_HWRM_MAX_REQ_LEN) {
-               if (msg_len > bp->hwrm_max_ext_req_len ||
-                   !bp->hwrm_short_cmd_req_addr)
-                       return -EINVAL;
-       }
-
-       if (bnxt_hwrm_kong_chnl(bp, req)) {
-               dst = BNXT_HWRM_CHNL_KONG;
-               bar_offset = BNXT_GRCPF_REG_KONG_COMM;
-               doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER;
-               resp = bp->hwrm_cmd_kong_resp_addr;
-       }
-
-       memset(resp, 0, PAGE_SIZE);
-       cp_ring_id = le16_to_cpu(req->cmpl_ring);
-       intr_process = (cp_ring_id == INVALID_HW_RING_ID) ? 0 : 1;
-
-       req->seq_id = cpu_to_le16(bnxt_get_hwrm_seq_id(bp, dst));
-       /* currently supports only one outstanding message */
-       if (intr_process)
-               bp->hwrm_intr_seq_id = le16_to_cpu(req->seq_id);
-
-       if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) ||
-           msg_len > BNXT_HWRM_MAX_REQ_LEN) {
-               void *short_cmd_req = bp->hwrm_short_cmd_req_addr;
-               u16 max_msg_len;
-
-               /* Set boundary for maximum extended request length for short
-                * cmd format. If passed up from device use the max supported
-                * internal req length.
-                */
-               max_msg_len = bp->hwrm_max_ext_req_len;
-
-               memcpy(short_cmd_req, req, msg_len);
-               if (msg_len < max_msg_len)
-                       memset(short_cmd_req + msg_len, 0,
-                              max_msg_len - msg_len);
-
-               short_input.req_type = req->req_type;
-               short_input.signature =
-                               cpu_to_le16(SHORT_REQ_SIGNATURE_SHORT_CMD);
-               short_input.size = cpu_to_le16(msg_len);
-               short_input.req_addr =
-                       cpu_to_le64(bp->hwrm_short_cmd_req_dma_addr);
-
-               data = (u32 *)&short_input;
-               msg_len = sizeof(short_input);
-
-               /* Sync memory write before updating doorbell */
-               wmb();
-
-               max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
-       }
-
-       /* Write request msg to hwrm channel */
-       __iowrite32_copy(bp->bar0 + bar_offset, data, msg_len / 4);
-
-       for (i = msg_len; i < max_req_len; i += 4)
-               writel(0, bp->bar0 + bar_offset + i);
-
-       /* Ring channel doorbell */
-       writel(1, bp->bar0 + doorbell_offset);
-
-       if (!pci_is_enabled(bp->pdev))
-               return -ENODEV;
-
-       if (!timeout)
-               timeout = DFLT_HWRM_CMD_TIMEOUT;
-       /* Limit timeout to an upper limit */
-       timeout = min(timeout, HWRM_CMD_MAX_TIMEOUT);
-       /* convert timeout to usec */
-       timeout *= 1000;
-
-       i = 0;
-       /* Short timeout for the first few iterations:
-        * number of loops = number of loops for short timeout +
-        * number of loops for standard timeout.
-        */
-       tmo_count = HWRM_SHORT_TIMEOUT_COUNTER;
-       timeout = timeout - HWRM_SHORT_MIN_TIMEOUT * HWRM_SHORT_TIMEOUT_COUNTER;
-       tmo_count += DIV_ROUND_UP(timeout, HWRM_MIN_TIMEOUT);
-
-       if (intr_process) {
-               u16 seq_id = bp->hwrm_intr_seq_id;
-
-               /* Wait until hwrm response cmpl interrupt is processed */
-               while (bp->hwrm_intr_seq_id != (u16)~seq_id &&
-                      i++ < tmo_count) {
-                       /* Abort the wait for completion if the FW health
-                        * check has failed.
-                        */
-                       if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
-                               return -EBUSY;
-                       /* on first few passes, just barely sleep */
-                       if (i < HWRM_SHORT_TIMEOUT_COUNTER) {
-                               usleep_range(HWRM_SHORT_MIN_TIMEOUT,
-                                            HWRM_SHORT_MAX_TIMEOUT);
-                       } else {
-                               if (HWRM_WAIT_MUST_ABORT(bp, req))
-                                       break;
-                               usleep_range(HWRM_MIN_TIMEOUT,
-                                            HWRM_MAX_TIMEOUT);
-                       }
-               }
-
-               if (bp->hwrm_intr_seq_id != (u16)~seq_id) {
-                       if (!silent)
-                               netdev_err(bp->dev, "Resp cmpl intr err msg: 0x%x\n",
-                                          le16_to_cpu(req->req_type));
-                       return -EBUSY;
-               }
-               len = le16_to_cpu(resp->resp_len);
-               valid = ((u8 *)resp) + len - 1;
-       } else {
-               int j;
-
-               /* Check if response len is updated */
-               for (i = 0; i < tmo_count; i++) {
-                       /* Abort the wait for completion if the FW health
-                        * check has failed.
-                        */
-                       if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
-                               return -EBUSY;
-                       len = le16_to_cpu(resp->resp_len);
-                       if (len)
-                               break;
-                       /* on first few passes, just barely sleep */
-                       if (i < HWRM_SHORT_TIMEOUT_COUNTER) {
-                               usleep_range(HWRM_SHORT_MIN_TIMEOUT,
-                                            HWRM_SHORT_MAX_TIMEOUT);
-                       } else {
-                               if (HWRM_WAIT_MUST_ABORT(bp, req))
-                                       goto timeout_abort;
-                               usleep_range(HWRM_MIN_TIMEOUT,
-                                            HWRM_MAX_TIMEOUT);
-                       }
-               }
-
-               if (i >= tmo_count) {
-timeout_abort:
-                       if (!silent)
-                               netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n",
-                                          HWRM_TOTAL_TIMEOUT(i),
-                                          le16_to_cpu(req->req_type),
-                                          le16_to_cpu(req->seq_id), len);
-                       return -EBUSY;
-               }
-
-               /* Last byte of resp contains valid bit */
-               valid = ((u8 *)resp) + len - 1;
-               for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; j++) {
-                       /* make sure we read from updated DMA memory */
-                       dma_rmb();
-                       if (*valid)
-                               break;
-                       usleep_range(1, 5);
-               }
-
-               if (j >= HWRM_VALID_BIT_DELAY_USEC) {
-                       if (!silent)
-                               netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n",
-                                          HWRM_TOTAL_TIMEOUT(i),
-                                          le16_to_cpu(req->req_type),
-                                          le16_to_cpu(req->seq_id), len,
-                                          *valid);
-                       return -EBUSY;
-               }
-       }
-
-       /* Zero valid bit for compatibility.  Valid bit in an older spec
-        * may become a new field in a newer spec.  We must make sure that
-        * a new field not implemented by old spec will read zero.
-        */
-       *valid = 0;
-       rc = le16_to_cpu(resp->error_code);
-       if (rc && !silent)
-               netdev_err(bp->dev, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n",
-                          le16_to_cpu(resp->req_type),
-                          le16_to_cpu(resp->seq_id), rc);
-       return bnxt_hwrm_to_stderr(rc);
-}
-
-int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout)
-{
-       return bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, false);
-}
-
-int _hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 msg_len,
-                             int timeout)
-{
-       return bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, true);
-}
-
-int hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout)
-{
-       int rc;
-
-       mutex_lock(&bp->hwrm_cmd_lock);
-       rc = _hwrm_send_message(bp, msg, msg_len, timeout);
-       mutex_unlock(&bp->hwrm_cmd_lock);
-       return rc;
-}
-
-int hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 msg_len,
-                            int timeout)
-{
-       int rc;
-
-       mutex_lock(&bp->hwrm_cmd_lock);
-       rc = bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, true);
-       mutex_unlock(&bp->hwrm_cmd_lock);
-       return rc;
-}
-
 int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap, int bmap_size,
                            bool async_only)
 {
@@ -7531,9 +7317,14 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
                rc = -ENODEV;
                goto no_ptp;
        }
-       return 0;
+       rc = bnxt_ptp_init(bp);
+       if (!rc)
+               return 0;
+
+       netdev_warn(bp->dev, "PTP initialization failed.\n");
 
 no_ptp:
+       bnxt_ptp_clear(bp);
        kfree(ptp);
        bp->ptp_cfg = NULL;
        return rc;
@@ -7576,6 +7367,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
        flags_ext = le32_to_cpu(resp->flags_ext);
        if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_EXT_HW_STATS_SUPPORTED)
                bp->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED;
+       if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_PTP_PPS_SUPPORTED))
+               bp->fw_cap |= BNXT_FW_CAP_PTP_PPS;
 
        bp->tx_push_thresh = 0;
        if ((flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) &&
@@ -7613,6 +7406,7 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
                if (flags & FUNC_QCAPS_RESP_FLAGS_PTP_SUPPORTED) {
                        __bnxt_hwrm_ptp_qcfg(bp);
                } else {
+                       bnxt_ptp_clear(bp);
                        kfree(bp->ptp_cfg);
                        bp->ptp_cfg = NULL;
                }
@@ -7951,7 +7745,7 @@ qportcfg_exit:
        return rc;
 }
 
-static int __bnxt_hwrm_ver_get(struct bnxt *bp, bool silent)
+static int bnxt_hwrm_poll(struct bnxt *bp)
 {
        struct hwrm_ver_get_input req = {0};
        int rc;
@@ -7961,21 +7755,26 @@ static int __bnxt_hwrm_ver_get(struct bnxt *bp, bool silent)
        req.hwrm_intf_min = HWRM_VERSION_MINOR;
        req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
 
-       rc = bnxt_hwrm_do_send_msg(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT,
-                                  silent);
+       rc = _hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        return rc;
 }
 
 static int bnxt_hwrm_ver_get(struct bnxt *bp)
 {
        struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr;
+       struct hwrm_ver_get_input req = {0};
        u16 fw_maj, fw_min, fw_bld, fw_rsv;
        u32 dev_caps_cfg, hwrm_ver;
        int rc, len;
 
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET, -1, -1);
        bp->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
+       req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
+       req.hwrm_intf_min = HWRM_VERSION_MINOR;
+       req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
+
        mutex_lock(&bp->hwrm_cmd_lock);
-       rc = __bnxt_hwrm_ver_get(bp, false);
+       rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
                goto hwrm_ver_get_exit;
 
@@ -9706,7 +9505,7 @@ static int bnxt_try_recover_fw(struct bnxt *bp)
                mutex_lock(&bp->hwrm_cmd_lock);
                do {
                        sts = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
-                       rc = __bnxt_hwrm_ver_get(bp, true);
+                       rc = bnxt_hwrm_poll(bp);
                        if (!BNXT_FW_IS_BOOTING(sts) &&
                            !BNXT_FW_IS_RECOVERING(sts))
                                break;
@@ -10209,7 +10008,9 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
        bnxt_tx_enable(bp);
        mod_timer(&bp->timer, jiffies + bp->current_interval);
        /* Poll link status and check for SFP+ module status */
+       mutex_lock(&bp->link_lock);
        bnxt_get_port_module_status(bp);
+       mutex_unlock(&bp->link_lock);
 
        /* VF-reps may need to be re-opened after the PF is re-opened */
        if (BNXT_PF(bp))
@@ -10316,15 +10117,9 @@ static int bnxt_open(struct net_device *dev)
        if (rc)
                return rc;
 
-       if (bnxt_ptp_init(bp)) {
-               netdev_warn(dev, "PTP initialization failed.\n");
-               kfree(bp->ptp_cfg);
-               bp->ptp_cfg = NULL;
-       }
        rc = __bnxt_open_nic(bp, true, true);
        if (rc) {
                bnxt_hwrm_if_change(bp, false);
-               bnxt_ptp_clear(bp);
        } else {
                if (test_and_clear_bit(BNXT_STATE_FW_RESET_DET, &bp->state)) {
                        if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
@@ -10415,7 +10210,6 @@ static int bnxt_close(struct net_device *dev)
 {
        struct bnxt *bp = netdev_priv(dev);
 
-       bnxt_ptp_clear(bp);
        bnxt_hwmon_close(bp);
        bnxt_close_nic(bp, true, true);
        bnxt_hwrm_shutdown_link(bp);
@@ -10551,6 +10345,10 @@ static void bnxt_get_ring_stats(struct bnxt *bp,
                stats->multicast += BNXT_GET_RING_STATS64(sw, rx_mcast_pkts);
 
                stats->tx_dropped += BNXT_GET_RING_STATS64(sw, tx_error_pkts);
+
+               stats->rx_dropped +=
+                       cpr->sw_stats.rx.rx_netpoll_discards +
+                       cpr->sw_stats.rx.rx_oom_discards;
        }
 }
 
@@ -10565,6 +10363,7 @@ static void bnxt_add_prev_stats(struct bnxt *bp,
        stats->tx_bytes += prev_stats->tx_bytes;
        stats->rx_missed_errors += prev_stats->rx_missed_errors;
        stats->multicast += prev_stats->multicast;
+       stats->rx_dropped += prev_stats->rx_dropped;
        stats->tx_dropped += prev_stats->tx_dropped;
 }
 
@@ -11405,7 +11204,6 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
                bnxt_clear_int_mode(bp);
                pci_disable_device(bp->pdev);
        }
-       bnxt_ptp_clear(bp);
        __bnxt_close_nic(bp, true, false);
        bnxt_vf_reps_free(bp);
        bnxt_clear_int_mode(bp);
@@ -11441,13 +11239,20 @@ static bool is_bnxt_fw_ok(struct bnxt *bp)
 static void bnxt_force_fw_reset(struct bnxt *bp)
 {
        struct bnxt_fw_health *fw_health = bp->fw_health;
+       struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
        u32 wait_dsecs;
 
        if (!test_bit(BNXT_STATE_OPEN, &bp->state) ||
            test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
                return;
 
-       set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+       if (ptp) {
+               spin_lock_bh(&ptp->ptp_lock);
+               set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+               spin_unlock_bh(&ptp->ptp_lock);
+       } else {
+               set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+       }
        bnxt_fw_reset_close(bp);
        wait_dsecs = fw_health->master_func_wait_dsecs;
        if (fw_health->master) {
@@ -11503,9 +11308,16 @@ void bnxt_fw_reset(struct bnxt *bp)
        bnxt_rtnl_lock_sp(bp);
        if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
            !test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+               struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
                int n = 0, tmo;
 
-               set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+               if (ptp) {
+                       spin_lock_bh(&ptp->ptp_lock);
+                       set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+                       spin_unlock_bh(&ptp->ptp_lock);
+               } else {
+                       set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+               }
                if (bp->pf.active_vfs &&
                    !test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
                        n = bnxt_get_registered_vfs(bp);
@@ -11824,18 +11636,6 @@ static int bnxt_fw_init_one_p1(struct bnxt *bp)
                        return rc;
        }
 
-       if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) {
-               rc = bnxt_alloc_kong_hwrm_resources(bp);
-               if (rc)
-                       bp->fw_cap &= ~BNXT_FW_CAP_KONG_MB_CHNL;
-       }
-
-       if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) ||
-           bp->hwrm_max_ext_req_len > BNXT_HWRM_MAX_REQ_LEN) {
-               rc = bnxt_alloc_hwrm_short_cmd_req(bp);
-               if (rc)
-                       return rc;
-       }
        bnxt_nvm_cfg_ver_get(bp);
 
        rc = bnxt_hwrm_func_reset(bp);
@@ -12012,8 +11812,8 @@ static void bnxt_reset_all(struct bnxt *bp)
        } else if (fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU) {
                struct hwrm_fw_reset_input req = {0};
 
-               bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FW_RESET, -1, -1);
-               req.resp_addr = cpu_to_le64(bp->hwrm_cmd_kong_resp_dma_addr);
+               bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FW_RESET, -1,
+                                      HWRM_TARGET_ID_KONG);
                req.embedded_proc_type = FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIP;
                req.selfrst_status = FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP;
                req.flags = FW_RESET_REQ_FLAGS_RESET_GRACEFUL;
@@ -12144,7 +11944,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                fallthrough;
        case BNXT_FW_RESET_STATE_POLL_FW:
                bp->hwrm_cmd_timeout = SHORT_HWRM_CMD_TIMEOUT;
-               rc = __bnxt_hwrm_ver_get(bp, true);
+               rc = bnxt_hwrm_poll(bp);
                if (rc) {
                        if (bnxt_fw_reset_timeout(bp)) {
                                netdev_err(bp->dev, "Firmware reset aborted\n");
@@ -12177,6 +11977,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                bnxt_reenable_sriov(bp);
                bnxt_vf_reps_alloc(bp);
                bnxt_vf_reps_open(bp);
+               bnxt_ptp_reapply_pps(bp);
                bnxt_dl_health_recovery_done(bp);
                bnxt_dl_health_status_update(bp, true);
                rtnl_unlock();
@@ -12708,7 +12509,7 @@ static const struct net_device_ops bnxt_netdev_ops = {
        .ndo_stop               = bnxt_close,
        .ndo_get_stats64        = bnxt_get_stats64,
        .ndo_set_rx_mode        = bnxt_set_rx_mode,
-       .ndo_do_ioctl           = bnxt_ioctl,
+       .ndo_eth_ioctl          = bnxt_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = bnxt_change_mac_addr,
        .ndo_change_mtu         = bnxt_change_mtu,
@@ -12747,6 +12548,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        if (BNXT_PF(bp))
                devlink_port_type_clear(&bp->dl_port);
 
+       bnxt_ptp_clear(bp);
        pci_disable_pcie_error_reporting(pdev);
        unregister_netdev(dev);
        clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
@@ -12762,7 +12564,6 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        bnxt_clear_int_mode(bp);
        bnxt_hwrm_func_drv_unrgtr(bp);
        bnxt_free_hwrm_resources(bp);
-       bnxt_free_hwrm_short_cmd_req(bp);
        bnxt_ethtool_free(bp);
        bnxt_dcb_free(bp);
        kfree(bp->edev);
@@ -12800,8 +12601,10 @@ static int bnxt_probe_phy(struct bnxt *bp, bool fw_dflt)
        if (!fw_dflt)
                return 0;
 
+       mutex_lock(&bp->link_lock);
        rc = bnxt_update_link(bp, false);
        if (rc) {
+               mutex_unlock(&bp->link_lock);
                netdev_err(bp->dev, "Probe phy can't update link (rc: %x)\n",
                           rc);
                return rc;
@@ -12814,6 +12617,7 @@ static int bnxt_probe_phy(struct bnxt *bp, bool fw_dflt)
                link_info->support_auto_speeds = link_info->support_speeds;
 
        bnxt_init_ethtool_link_settings(bp);
+       mutex_unlock(&bp->link_lock);
        return 0;
 }
 
@@ -13085,6 +12889,12 @@ static void bnxt_vpd_read_info(struct bnxt *bp)
                goto exit;
        }
 
+       i = pci_vpd_find_tag(vpd_data, vpd_size, PCI_VPD_LRDT_RO_DATA);
+       if (i < 0) {
+               netdev_err(bp->dev, "VPD READ-Only not found\n");
+               goto exit;
+       }
+
        ro_size = pci_vpd_lrdt_size(&vpd_data[i]);
        i += PCI_VPD_LRDT_TAG_SIZE;
        if (i + ro_size > vpd_size)
@@ -13356,9 +13166,9 @@ init_err_cleanup:
 
 init_err_pci_clean:
        bnxt_hwrm_func_drv_unrgtr(bp);
-       bnxt_free_hwrm_short_cmd_req(bp);
        bnxt_free_hwrm_resources(bp);
        bnxt_ethtool_free(bp);
+       bnxt_ptp_clear(bp);
        kfree(bp->ptp_cfg);
        bp->ptp_cfg = NULL;
        kfree(bp->fw_health);