be2net: Interpret and log new data that's added to the port misconfigure async event
authorAjit Khaparde <ajit.khaparde@broadcom.com>
Wed, 10 Feb 2016 17:15:54 +0000 (22:45 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Feb 2016 08:46:59 +0000 (03:46 -0500)
>From FW version 11.0. onwards, the PORT_MISCONFIG event generated by the FW
will carry more information about the event in the "data_word1"
and "data_word2" fields. This patch adds support in the driver to parse the
new information and log it accordingly. This patch also changes some of the
messages that are being logged currently.

Signed-off-by: Suresh Reddy <suresh.reddy@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Signed-off-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c

index 515e206..ab24f84 100644 (file)
 #define        RSS_INDIR_TABLE_LEN     128
 #define RSS_HASH_KEY_LEN       40
 
+#define BE_UNKNOWN_PHY_STATE   0xFF
+
 struct be_dma_mem {
        void *va;
        dma_addr_t dma;
@@ -390,7 +392,7 @@ enum vf_state {
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD            BIT(7)
 #define BE_FLAGS_VXLAN_OFFLOADS                        BIT(8)
 #define BE_FLAGS_SETUP_DONE                    BIT(9)
-#define BE_FLAGS_EVT_INCOMPATIBLE_SFP          BIT(10)
+#define BE_FLAGS_PHY_MISCONFIGURED             BIT(10)
 #define BE_FLAGS_ERR_DETECTION_SCHEDULED       BIT(11)
 #define BE_FLAGS_OS2BMC                                BIT(12)
 
@@ -603,6 +605,7 @@ struct be_adapter {
        u32 bmc_filt_mask;
        u32 fat_dump_len;
        u16 serial_num[CNTL_SERIAL_NUM_WORDS];
+       u8 phy_state; /* state of sfp optics (functional, faulted, etc.,) */
 };
 
 #define be_physfn(adapter)             (!adapter->virtfn)
index 33cbbde..66fa214 100644 (file)
 #include "be.h"
 #include "be_cmds.h"
 
-static char *be_port_misconfig_evt_desc[] = {
-       "A valid SFP module detected",
-       "Optics faulted/ incorrectly installed/ not installed.",
-       "Optics of two types installed.",
-       "Incompatible optics.",
-       "Unknown port SFP status"
+char *be_misconfig_evt_port_state[] = {
+       "Physical Link is functional",
+       "Optics faulted/incorrectly installed/not installed - Reseat optics. If issue not resolved, replace.",
+       "Optics of two types installed – Remove one optic or install matching pair of optics.",
+       "Incompatible optics – Replace with compatible optics for card to function.",
+       "Unqualified optics – Replace with Avago optics for Warranty and Technical Support.",
+       "Uncertified optics – Replace with Avago-certified optics to enable link operation."
 };
 
-static char *be_port_misconfig_remedy_desc[] = {
-       "",
-       "Reseat optics. If issue not resolved, replace",
-       "Remove one optic or install matching pair of optics",
-       "Replace with compatible optics for card to function",
+static char *be_port_misconfig_evt_severity[] = {
+       "KERN_WARN",
+       "KERN_INFO",
+       "KERN_ERR",
+       "KERN_WARN"
+};
+
+static char *phy_state_oper_desc[] = {
+       "Link is non-operational",
+       "Link is operational",
        ""
 };
 
@@ -297,22 +303,56 @@ static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
 {
        struct be_async_event_misconfig_port *evt =
                        (struct be_async_event_misconfig_port *)compl;
-       u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
+       u32 sfp_misconfig_evt_word1 = le32_to_cpu(evt->event_data_word1);
+       u32 sfp_misconfig_evt_word2 = le32_to_cpu(evt->event_data_word2);
+       u8 phy_oper_state = PHY_STATE_OPER_MSG_NONE;
        struct device *dev = &adapter->pdev->dev;
-       u8 port_misconfig_evt;
+       u8 msg_severity = DEFAULT_MSG_SEVERITY;
+       u8 phy_state_info;
+       u8 new_phy_state;
+
+       new_phy_state =
+               (sfp_misconfig_evt_word1 >> (adapter->hba_port_num * 8)) & 0xff;
+
+       if (new_phy_state == adapter->phy_state)
+               return;
+
+       adapter->phy_state = new_phy_state;
 
-       port_misconfig_evt =
-               ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
+       /* for older fw that doesn't populate link effect data */
+       if (!sfp_misconfig_evt_word2)
+               goto log_message;
 
+       phy_state_info =
+               (sfp_misconfig_evt_word2 >> (adapter->hba_port_num * 8)) & 0xff;
+
+       if (phy_state_info & PHY_STATE_INFO_VALID) {
+               msg_severity = (phy_state_info & PHY_STATE_MSG_SEVERITY) >> 1;
+
+               if (be_phy_unqualified(new_phy_state))
+                       phy_oper_state = (phy_state_info & PHY_STATE_OPER);
+       }
+
+log_message:
        /* Log an error message that would allow a user to determine
         * whether the SFPs have an issue
         */
-       dev_info(dev, "Port %c: %s %s", adapter->port_name,
-                be_port_misconfig_evt_desc[port_misconfig_evt],
-                be_port_misconfig_remedy_desc[port_misconfig_evt]);
-
-       if (port_misconfig_evt == INCOMPATIBLE_SFP)
-               adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
+       if (be_phy_state_unknown(new_phy_state))
+               dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
+                          "Port %c: Unrecognized Optics state: 0x%x. %s",
+                          adapter->port_name,
+                          new_phy_state,
+                          phy_state_oper_desc[phy_oper_state]);
+       else
+               dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
+                          "Port %c: %s %s",
+                          adapter->port_name,
+                          be_misconfig_evt_port_state[new_phy_state],
+                          phy_state_oper_desc[phy_oper_state]);
+
+       /* Log Vendor name and part no. if a misconfigured SFP is detected */
+       if (be_phy_misconfigured(new_phy_state))
+               adapter->flags |= BE_FLAGS_PHY_MISCONFIGURED;
 }
 
 /* Grp5 CoS Priority evt */
index f260ef3..0b9f741 100644 (file)
@@ -176,10 +176,53 @@ struct be_async_event_qnq {
        u32 flags;
 } __packed;
 
-#define INCOMPATIBLE_SFP               0x3
+enum {
+       BE_PHY_FUNCTIONAL       = 0,
+       BE_PHY_NOT_PRESENT      = 1,
+       BE_PHY_DIFF_MEDIA       = 2,
+       BE_PHY_INCOMPATIBLE     = 3,
+       BE_PHY_UNQUALIFIED      = 4,
+       BE_PHY_UNCERTIFIED      = 5
+};
+
+#define PHY_STATE_MSG_SEVERITY         0x6
+#define PHY_STATE_OPER                 0x1
+#define PHY_STATE_INFO_VALID           0x80
+#define        PHY_STATE_OPER_MSG_NONE         0x2
+#define DEFAULT_MSG_SEVERITY           0x1
+
+#define be_phy_state_unknown(phy_state) (phy_state > BE_PHY_UNCERTIFIED)
+#define be_phy_unqualified(phy_state)                          \
+                       (phy_state == BE_PHY_UNQUALIFIED ||     \
+                        phy_state == BE_PHY_UNCERTIFIED)
+#define be_phy_misconfigured(phy_state)                                \
+                       (phy_state == BE_PHY_INCOMPATIBLE ||    \
+                        phy_state == BE_PHY_UNQUALIFIED ||     \
+                        phy_state == BE_PHY_UNCERTIFIED)
+
+extern  char *be_misconfig_evt_port_state[];
+
 /* async event indicating misconfigured port */
 struct be_async_event_misconfig_port {
+ /* DATA_WORD1:
+  * phy state of port 0: bits 7 - 0
+  * phy state of port 1: bits 15 - 8
+  * phy state of port 2: bits 23 - 16
+  * phy state of port 3: bits 31 - 24
+  */
        u32 event_data_word1;
+ /* DATA_WORD2:
+  * phy state info of port 0: bits 7 - 0
+  * phy state info of port 1: bits 15 - 8
+  * phy state info of port 2: bits 23 - 16
+  * phy state info of port 3: bits 31 - 24
+  *
+  * PHY STATE INFO:
+  * Link operability    :bit 0
+  * Message severity    :bit 2 - 1
+  * Rsvd                        :bits 6 - 3
+  * phy state info valid        :bit 7
+  */
        u32 event_data_word2;
        u32 rsvd0;
        u32 flags;
index e4fc874..4ecd8c2 100644 (file)
@@ -4089,6 +4089,7 @@ static void be_setup_init(struct be_adapter *adapter)
        adapter->if_handle = -1;
        adapter->be3_native = false;
        adapter->if_flags = 0;
+       adapter->phy_state = BE_UNKNOWN_PHY_STATE;
        if (be_physfn(adapter))
                adapter->cmd_privileges = MAX_PRIVILEGES;
        else
@@ -4961,11 +4962,13 @@ static void be_log_sfp_info(struct be_adapter *adapter)
        status = be_cmd_query_sfp_info(adapter);
        if (!status) {
                dev_err(&adapter->pdev->dev,
-                       "Unqualified SFP+ detected on %c from %s part no: %s",
-                       adapter->port_name, adapter->phy.vendor_name,
+                       "Port %c: %s Vendor: %s part no: %s",
+                       adapter->port_name,
+                       be_misconfig_evt_port_state[adapter->phy_state],
+                       adapter->phy.vendor_name,
                        adapter->phy.vendor_pn);
        }
-       adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
+       adapter->flags &= ~BE_FLAGS_PHY_MISCONFIGURED;
 }
 
 static void be_worker(struct work_struct *work)
@@ -5009,7 +5012,7 @@ static void be_worker(struct work_struct *work)
        if (!skyhawk_chip(adapter))
                be_eqd_update(adapter, false);
 
-       if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
+       if (adapter->flags & BE_FLAGS_PHY_MISCONFIGURED)
                be_log_sfp_info(adapter);
 
 reschedule: