qed: Learn of RDMA capabilities per-device
authorMintz, Yuval <Yuval.Mintz@cavium.com>
Mon, 31 Oct 2016 05:14:25 +0000 (07:14 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 31 Oct 2016 19:52:36 +0000 (15:52 -0400)
Today, RDMA capabilities are learned from management firmware
which provides a per-device indication for all interfaces.
Newer management firmware is capable of providing a per-device
indication [would later be extended to either RoCE/iWARP].

Try using this newer learning mechanism, but fallback in case
management firmware is too old to retain current functionality.

Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qed/qed_hsi.h
drivers/net/ethernet/qlogic/qed/qed_mcp.c

index fdb7a099955b8098a6424eef390de08a39846f5c..1d113ce814e1c372e615a79f79bfdfe4900c7d37 100644 (file)
@@ -8601,6 +8601,7 @@ struct public_drv_mb {
 
 #define DRV_MSG_CODE_BIST_TEST                 0x001e0000
 #define DRV_MSG_CODE_SET_LED_MODE              0x00200000
+#define DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL      0x002b0000
 #define DRV_MSG_CODE_OS_WOL                    0x002e0000
 
 #define DRV_MSG_SEQ_NUMBER_MASK                        0x0000ffff
@@ -8705,6 +8706,12 @@ struct public_drv_mb {
 
        u32 fw_mb_param;
 
+       /* get pf rdma protocol command responce */
+#define FW_MB_PARAM_GET_PF_RDMA_NONE           0x0
+#define FW_MB_PARAM_GET_PF_RDMA_ROCE           0x1
+#define FW_MB_PARAM_GET_PF_RDMA_IWARP          0x2
+#define FW_MB_PARAM_GET_PF_RDMA_BOTH           0x3
+
        u32 drv_pulse_mb;
 #define DRV_PULSE_SEQ_MASK                     0x00007fff
 #define DRV_PULSE_SYSTEM_TIME_MASK             0xffff0000
index 768b35b1dca09bf37d3ccd7e457ab22b0b4be6da..092748832cafb871376a185d95a21cf7c0099073 100644 (file)
@@ -1024,28 +1024,89 @@ int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type)
        return 0;
 }
 
+/* Old MFW has a global configuration for all PFs regarding RDMA support */
+static void
+qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn,
+                              enum qed_pci_personality *p_proto)
+{
+       /* There wasn't ever a legacy MFW that published iwarp.
+        * So at this point, this is either plain l2 or RoCE.
+        */
+       if (test_bit(QED_DEV_CAP_ROCE, &p_hwfn->hw_info.device_capabilities))
+               *p_proto = QED_PCI_ETH_ROCE;
+       else
+               *p_proto = QED_PCI_ETH;
+
+       DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP,
+                  "According to Legacy capabilities, L2 personality is %08x\n",
+                  (u32) *p_proto);
+}
+
+static int
+qed_mcp_get_shmem_proto_mfw(struct qed_hwfn *p_hwfn,
+                           struct qed_ptt *p_ptt,
+                           enum qed_pci_personality *p_proto)
+{
+       u32 resp = 0, param = 0;
+       int rc;
+
+       rc = qed_mcp_cmd(p_hwfn, p_ptt,
+                        DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, &param);
+       if (rc)
+               return rc;
+       if (resp != FW_MSG_CODE_OK) {
+               DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP,
+                          "MFW lacks support for command; Returns %08x\n",
+                          resp);
+               return -EINVAL;
+       }
+
+       switch (param) {
+       case FW_MB_PARAM_GET_PF_RDMA_NONE:
+               *p_proto = QED_PCI_ETH;
+               break;
+       case FW_MB_PARAM_GET_PF_RDMA_ROCE:
+               *p_proto = QED_PCI_ETH_ROCE;
+               break;
+       case FW_MB_PARAM_GET_PF_RDMA_BOTH:
+               DP_NOTICE(p_hwfn,
+                         "Current day drivers don't support RoCE & iWARP. Default to RoCE-only\n");
+               *p_proto = QED_PCI_ETH_ROCE;
+               break;
+       case FW_MB_PARAM_GET_PF_RDMA_IWARP:
+       default:
+               DP_NOTICE(p_hwfn,
+                         "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n",
+                         param);
+               return -EINVAL;
+       }
+
+       DP_VERBOSE(p_hwfn,
+                  NETIF_MSG_IFUP,
+                  "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n",
+                  (u32) *p_proto, resp, param);
+       return 0;
+}
+
 static int
 qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
                        struct public_func *p_info,
+                       struct qed_ptt *p_ptt,
                        enum qed_pci_personality *p_proto)
 {
        int rc = 0;
 
        switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) {
        case FUNC_MF_CFG_PROTOCOL_ETHERNET:
-               if (test_bit(QED_DEV_CAP_ROCE,
-                            &p_hwfn->hw_info.device_capabilities))
-                       *p_proto = QED_PCI_ETH_ROCE;
-               else
-                       *p_proto = QED_PCI_ETH;
+               if (qed_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto))
+                       qed_mcp_get_shmem_proto_legacy(p_hwfn, p_proto);
                break;
        case FUNC_MF_CFG_PROTOCOL_ISCSI:
                *p_proto = QED_PCI_ISCSI;
                break;
        case FUNC_MF_CFG_PROTOCOL_ROCE:
                DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n");
-               rc = -EINVAL;
-               break;
+       /* Fallthrough */
        default:
                rc = -EINVAL;
        }
@@ -1065,7 +1126,8 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
        info->pause_on_host = (shmem_info.config &
                               FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0;
 
-       if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, &info->protocol)) {
+       if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
+                                   &info->protocol)) {
                DP_ERR(p_hwfn, "Unknown personality %08x\n",
                       (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK));
                return -EINVAL;