]> git.baikalelectronics.ru Git - kernel.git/commitdiff
bnxt_en: move HWRM API implementation into separate file
authorEdwin Peer <edwin.peer@broadcom.com>
Sun, 29 Aug 2021 07:34:58 +0000 (03:34 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 30 Aug 2021 08:35:04 +0000 (09:35 +0100)
Move all firmware messaging functions and definitions to new
bnxt_hwrm.[ch].  The follow-on patches will make major modifications
to these APIs.

Signed-off-by: Edwin Peer <edwin.peer@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
13 files changed:
drivers/net/ethernet/broadcom/bnxt/Makefile
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c [new file with mode: 0644]
drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h [new file with mode: 0644]
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c

index 2b8ae687b3c1b027bc4d8a5a9f5fe9b9e7706163..c6ef7ec2c11515b00cc30359e9efb71782363ae0 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_BNXT) += bnxt_en.o
 
-bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o
+bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o
 bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
 bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o
index dd2f80c394f5c42bae28415d054c75a19b2f0f11..10c39801ad5f460c13d313533434525a9b4683da 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"
@@ -4549,278 +4550,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);
-       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_kong_hwrm_message(bp, req)) {
-               dst = BNXT_HWRM_CHNL_KONG;
-               bar_offset = BNXT_GRCPF_REG_KONG_COMM;
-               doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER;
-       }
-
-       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)
 {
index a4fb1aa12b2493e1c1c2d859bc9cabdc0992d4c9..5ff71eeffdd8a77085c32a3c6a97e750cbf1eb4e 100644 (file)
@@ -669,37 +669,7 @@ struct nqe_cn {
 #define RING_CMP(idx)          ((idx) & bp->cp_ring_mask)
 #define NEXT_CMP(idx)          RING_CMP(ADV_RAW_CMP(idx, 1))
 
-#define BNXT_HWRM_MAX_REQ_LEN          (bp->hwrm_max_req_len)
-#define BNXT_HWRM_SHORT_REQ_LEN                sizeof(struct hwrm_short_input)
 #define DFLT_HWRM_CMD_TIMEOUT          500
-#define HWRM_CMD_MAX_TIMEOUT           40000
-#define SHORT_HWRM_CMD_TIMEOUT         20
-#define HWRM_CMD_TIMEOUT               (bp->hwrm_cmd_timeout)
-#define HWRM_RESET_TIMEOUT             ((HWRM_CMD_TIMEOUT) * 4)
-#define HWRM_COREDUMP_TIMEOUT          ((HWRM_CMD_TIMEOUT) * 12)
-#define BNXT_HWRM_REQ_MAX_SIZE         128
-#define BNXT_HWRM_REQS_PER_PAGE                (BNXT_PAGE_SIZE /       \
-                                        BNXT_HWRM_REQ_MAX_SIZE)
-#define HWRM_SHORT_MIN_TIMEOUT         3
-#define HWRM_SHORT_MAX_TIMEOUT         10
-#define HWRM_SHORT_TIMEOUT_COUNTER     5
-
-#define HWRM_MIN_TIMEOUT               25
-#define HWRM_MAX_TIMEOUT               40
-
-#define HWRM_WAIT_MUST_ABORT(bp, req)                                  \
-       (le16_to_cpu((req)->req_type) != HWRM_VER_GET &&                \
-        !bnxt_is_fw_healthy(bp))
-
-#define HWRM_TOTAL_TIMEOUT(n)  (((n) <= HWRM_SHORT_TIMEOUT_COUNTER) ?  \
-       ((n) * HWRM_SHORT_MIN_TIMEOUT) :                                \
-       (HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT +          \
-        ((n) - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT))
-
-#define HWRM_VALID_BIT_DELAY_USEC      150
-
-#define BNXT_HWRM_CHNL_CHIMP   0
-#define BNXT_HWRM_CHNL_KONG    1
 
 #define BNXT_RX_EVENT          1
 #define BNXT_AGG_EVENT         2
@@ -2185,55 +2155,6 @@ static inline void bnxt_db_write(struct bnxt *bp, struct bnxt_db_info *db,
        }
 }
 
-static inline bool bnxt_cfa_hwrm_message(u16 req_type)
-{
-       switch (req_type) {
-       case HWRM_CFA_ENCAP_RECORD_ALLOC:
-       case HWRM_CFA_ENCAP_RECORD_FREE:
-       case HWRM_CFA_DECAP_FILTER_ALLOC:
-       case HWRM_CFA_DECAP_FILTER_FREE:
-       case HWRM_CFA_EM_FLOW_ALLOC:
-       case HWRM_CFA_EM_FLOW_FREE:
-       case HWRM_CFA_EM_FLOW_CFG:
-       case HWRM_CFA_FLOW_ALLOC:
-       case HWRM_CFA_FLOW_FREE:
-       case HWRM_CFA_FLOW_INFO:
-       case HWRM_CFA_FLOW_FLUSH:
-       case HWRM_CFA_FLOW_STATS:
-       case HWRM_CFA_METER_PROFILE_ALLOC:
-       case HWRM_CFA_METER_PROFILE_FREE:
-       case HWRM_CFA_METER_PROFILE_CFG:
-       case HWRM_CFA_METER_INSTANCE_ALLOC:
-       case HWRM_CFA_METER_INSTANCE_FREE:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static inline bool bnxt_kong_hwrm_message(struct bnxt *bp, struct input *req)
-{
-       return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
-               (bnxt_cfa_hwrm_message(le16_to_cpu(req->req_type)) ||
-                le16_to_cpu(req->target_id) == HWRM_TARGET_ID_KONG));
-}
-
-static inline void *bnxt_get_hwrm_resp_addr(struct bnxt *bp, void *req)
-{
-       return bp->hwrm_cmd_resp_addr;
-}
-
-static inline u16 bnxt_get_hwrm_seq_id(struct bnxt *bp, u16 dst)
-{
-       u16 seq_id;
-
-       if (dst == BNXT_HWRM_CHNL_CHIMP)
-               seq_id = bp->hwrm_cmd_seq++;
-       else
-               seq_id = bp->hwrm_cmd_kong_seq++;
-       return seq_id;
-}
-
 extern const u16 bnxt_lhint_arr[];
 
 int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
@@ -2243,11 +2164,6 @@ u32 bnxt_fw_health_readl(struct bnxt *bp, int reg_idx);
 void bnxt_set_tpa_flags(struct bnxt *bp);
 void bnxt_set_ring_params(struct bnxt *);
 int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
-void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
-int _hwrm_send_message(struct bnxt *, void *, u32, int);
-int _hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 len, int timeout);
-int hwrm_send_message(struct bnxt *, void *, u32, int);
-int hwrm_send_message_silent(struct bnxt *, void *, u32, int);
 int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap,
                            int bmap_size, bool async_only);
 int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings);
index 8a68df4d9e59cf2cf6670bffe01991fd0bbd649c..df898665763a01dfe45060a032a4b78e117967ac 100644 (file)
@@ -18,6 +18,7 @@
 #include <rdma/ib_verbs.h>
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_dcb.h"
 
 #ifdef CONFIG_BNXT_DCB
index 2cd8bb37e6410020ad6e5b9aa0c21a924605ec89..00b284a028c5930a912a8440c86fd4aab5259904 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/devlink.h>
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_vfr.h"
 #include "bnxt_devlink.h"
 #include "bnxt_ethtool.h"
index 5852ae3b26a229d992887908ecd414482886aae7..b6aaf14bd7fd1065c6b62d4453d5cecbccf3d5ff 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/timecounter.h>
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_xdp.h"
 #include "bnxt_ptp.h"
 #include "bnxt_ethtool.h"
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
new file mode 100644 (file)
index 0000000..b2a211b
--- /dev/null
@@ -0,0 +1,297 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2020 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/errno.h>
+#include <linux/ethtool.h>
+#include <linux/if_ether.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/skbuff.h>
+
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_hwrm.h"
+
+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);
+       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_kong_hwrm_message(bp, req)) {
+               dst = BNXT_HWRM_CHNL_KONG;
+               bar_offset = BNXT_GRCPF_REG_KONG_COMM;
+               doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER;
+       }
+
+       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;
+}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h
new file mode 100644 (file)
index 0000000..940c792
--- /dev/null
@@ -0,0 +1,100 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2020 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef BNXT_HWRM_H
+#define BNXT_HWRM_H
+
+#include "bnxt_hsi.h"
+
+#define BNXT_HWRM_MAX_REQ_LEN          (bp->hwrm_max_req_len)
+#define BNXT_HWRM_SHORT_REQ_LEN                sizeof(struct hwrm_short_input)
+#define HWRM_CMD_MAX_TIMEOUT           40000
+#define SHORT_HWRM_CMD_TIMEOUT         20
+#define HWRM_CMD_TIMEOUT               (bp->hwrm_cmd_timeout)
+#define HWRM_RESET_TIMEOUT             ((HWRM_CMD_TIMEOUT) * 4)
+#define HWRM_COREDUMP_TIMEOUT          ((HWRM_CMD_TIMEOUT) * 12)
+#define BNXT_HWRM_REQ_MAX_SIZE         128
+#define BNXT_HWRM_REQS_PER_PAGE                (BNXT_PAGE_SIZE /       \
+                                        BNXT_HWRM_REQ_MAX_SIZE)
+#define HWRM_SHORT_MIN_TIMEOUT         3
+#define HWRM_SHORT_MAX_TIMEOUT         10
+#define HWRM_SHORT_TIMEOUT_COUNTER     5
+
+#define HWRM_MIN_TIMEOUT               25
+#define HWRM_MAX_TIMEOUT               40
+
+#define HWRM_WAIT_MUST_ABORT(bp, req)                                  \
+       (le16_to_cpu((req)->req_type) != HWRM_VER_GET &&                \
+        !bnxt_is_fw_healthy(bp))
+
+#define HWRM_TOTAL_TIMEOUT(n)  (((n) <= HWRM_SHORT_TIMEOUT_COUNTER) ?  \
+       ((n) * HWRM_SHORT_MIN_TIMEOUT) :                                \
+       (HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT +          \
+        ((n) - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT))
+
+#define HWRM_VALID_BIT_DELAY_USEC      150
+
+#define BNXT_HWRM_CHNL_CHIMP   0
+#define BNXT_HWRM_CHNL_KONG    1
+
+static inline bool bnxt_cfa_hwrm_message(u16 req_type)
+{
+       switch (req_type) {
+       case HWRM_CFA_ENCAP_RECORD_ALLOC:
+       case HWRM_CFA_ENCAP_RECORD_FREE:
+       case HWRM_CFA_DECAP_FILTER_ALLOC:
+       case HWRM_CFA_DECAP_FILTER_FREE:
+       case HWRM_CFA_EM_FLOW_ALLOC:
+       case HWRM_CFA_EM_FLOW_FREE:
+       case HWRM_CFA_EM_FLOW_CFG:
+       case HWRM_CFA_FLOW_ALLOC:
+       case HWRM_CFA_FLOW_FREE:
+       case HWRM_CFA_FLOW_INFO:
+       case HWRM_CFA_FLOW_FLUSH:
+       case HWRM_CFA_FLOW_STATS:
+       case HWRM_CFA_METER_PROFILE_ALLOC:
+       case HWRM_CFA_METER_PROFILE_FREE:
+       case HWRM_CFA_METER_PROFILE_CFG:
+       case HWRM_CFA_METER_INSTANCE_ALLOC:
+       case HWRM_CFA_METER_INSTANCE_FREE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static inline bool bnxt_kong_hwrm_message(struct bnxt *bp, struct input *req)
+{
+       return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
+               (bnxt_cfa_hwrm_message(le16_to_cpu(req->req_type)) ||
+                le16_to_cpu(req->target_id) == HWRM_TARGET_ID_KONG));
+}
+
+static inline void *bnxt_get_hwrm_resp_addr(struct bnxt *bp, void *req)
+{
+       return bp->hwrm_cmd_resp_addr;
+}
+
+static inline u16 bnxt_get_hwrm_seq_id(struct bnxt *bp, u16 dst)
+{
+       u16 seq_id;
+
+       if (dst == BNXT_HWRM_CHNL_CHIMP)
+               seq_id = bp->hwrm_cmd_seq++;
+       else
+               seq_id = bp->hwrm_cmd_kong_seq++;
+       return seq_id;
+}
+
+void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
+int _hwrm_send_message(struct bnxt *bp, void *msg, u32 len, int timeout);
+int _hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 len, int timeout);
+int hwrm_send_message(struct bnxt *bp, void *msg, u32 len, int timeout);
+int hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 len, int timeout);
+#endif
index 2fe3c9081f8df943831338ecd88a1f18e6829030..4cc2379027cf5ddf53b0e9baa2ac084361d34cc7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ptp_classify.h>
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_ptp.h"
 
 int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off)
index 7fa881e1cd80ddde955303b3cc99e932ff35cd8e..7b0e308e44c2caa6469680fc61609e562ed8dfeb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/etherdevice.h>
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_ulp.h"
 #include "bnxt_sriov.h"
 #include "bnxt_vfr.h"
index 5e4429b14b8ca6378c2bbd1e43f0036bc35589ca..c0c3cc426f7ba749b9b43b6f43632737965fb648 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_sriov.h"
 #include "bnxt_tc.h"
 #include "bnxt_vfr.h"
index 187ff643ad2aeaf1f0bf8d3a6a24591c9545f549..f621cffccd3a536abb17c107b5f1d7c7ea961489 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_ulp.h"
 
 static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
index dd66302343a2c33397f12d94608ac4a9fba41524..3ed712a08207f29d140750d61d2562fd09907928 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_hwrm.h"
 #include "bnxt_vfr.h"
 #include "bnxt_devlink.h"
 #include "bnxt_tc.h"