ice: Refactor the LLDP MIB change event handling
authorUsha Ketineni <usha.k.ketineni@intel.com>
Tue, 16 Apr 2019 17:24:31 +0000 (10:24 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 23 May 2019 17:51:53 +0000 (10:51 -0700)
This patch fixes the LLDP MIB change event handling code by removing
the workarounds in the current code. Added ice_dcb_need_recfg() to
print the DCB configuration changes detected via MIB change event.

Signed-off-by: Usha Ketineni <usha.k.ketineni@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice_dcb.c
drivers/net/ethernet/intel/ice/ice_dcb.h
drivers/net/ethernet/intel/ice/ice_dcb_lib.c

index 8bf83134b0da2c9df8f058939a8c5027fc45e11a..49fbfe7c1ad7c22163c45ee0260b91895ee46521 100644 (file)
@@ -624,7 +624,8 @@ ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
  *
  * Parse DCB configuration from the LLDPDU
  */
-enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
+static enum ice_status
+ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
 {
        struct ice_lldp_org_tlv *tlv;
        enum ice_status ret = 0;
@@ -674,7 +675,7 @@ enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
  *
  * Query DCB configuration from the firmware
  */
-static enum ice_status
+enum ice_status
 ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
                   struct ice_dcbx_cfg *dcbcfg)
 {
index e8594a3bc22927f22da6371ead452178d049ac9e..522e1452abe24e00d924259496853e74ee664c36 100644 (file)
@@ -120,7 +120,9 @@ struct ice_cee_app_prio {
        u8 prio_map;
 } __packed;
 
-enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg);
+enum ice_status
+ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
+                  struct ice_dcbx_cfg *dcbcfg);
 enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi);
 enum ice_status ice_set_dcb_cfg(struct ice_port_info *pi);
 enum ice_status ice_init_dcb(struct ice_hw *hw);
index 8d849ef5cb0cb9af45dc41bc4acd4f531ad0536c..b97e3e8d499b860f7915c8e476a113f33612fe4b 100644 (file)
@@ -501,6 +501,55 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
        return 0;
 }
 
+/**
+ * ice_dcb_need_recfg - Check if DCB needs reconfig
+ * @pf: board private structure
+ * @old_cfg: current DCB config
+ * @new_cfg: new DCB config
+ */
+static bool ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
+                              struct ice_dcbx_cfg *new_cfg)
+{
+       bool need_reconfig = false;
+
+       /* Check if ETS configuration has changed */
+       if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg,
+                  sizeof(new_cfg->etscfg))) {
+               /* If Priority Table has changed reconfig is needed */
+               if (memcmp(&new_cfg->etscfg.prio_table,
+                          &old_cfg->etscfg.prio_table,
+                          sizeof(new_cfg->etscfg.prio_table))) {
+                       need_reconfig = true;
+                       dev_dbg(&pf->pdev->dev, "ETS UP2TC changed.\n");
+               }
+
+               if (memcmp(&new_cfg->etscfg.tcbwtable,
+                          &old_cfg->etscfg.tcbwtable,
+                          sizeof(new_cfg->etscfg.tcbwtable)))
+                       dev_dbg(&pf->pdev->dev, "ETS TC BW Table changed.\n");
+
+               if (memcmp(&new_cfg->etscfg.tsatable,
+                          &old_cfg->etscfg.tsatable,
+                          sizeof(new_cfg->etscfg.tsatable)))
+                       dev_dbg(&pf->pdev->dev, "ETS TSA Table changed.\n");
+       }
+
+       /* Check if PFC configuration has changed */
+       if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) {
+               need_reconfig = true;
+               dev_dbg(&pf->pdev->dev, "PFC config change detected.\n");
+       }
+
+       /* Check if APP Table has changed */
+       if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) {
+               need_reconfig = true;
+               dev_dbg(&pf->pdev->dev, "APP Table change detected.\n");
+       }
+
+       dev_dbg(&pf->pdev->dev, "dcb need_reconfig=%d\n", need_reconfig);
+       return need_reconfig;
+}
+
 /**
  * ice_dcb_process_lldp_set_mib_change - Process MIB change
  * @pf: ptr to ice_pf
@@ -510,29 +559,95 @@ void
 ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
                                    struct ice_rq_event_info *event)
 {
-       if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
-               struct ice_dcbx_cfg *dcbcfg, *prev_cfg;
-               int err;
-
-               prev_cfg = &pf->hw.port_info->local_dcbx_cfg;
-               dcbcfg = devm_kmemdup(&pf->pdev->dev, prev_cfg,
-                                     sizeof(*dcbcfg), GFP_KERNEL);
-               if (!dcbcfg)
+       struct ice_aqc_port_ets_elem buf = { 0 };
+       struct ice_aqc_lldp_get_mib *mib;
+       struct ice_dcbx_cfg tmp_dcbx_cfg;
+       bool need_reconfig = false;
+       struct ice_port_info *pi;
+       u8 type;
+       int ret;
+
+       /* Not DCB capable or capability disabled */
+       if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
+               return;
+
+       if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
+               dev_dbg(&pf->pdev->dev,
+                       "MIB Change Event in HOST mode\n");
+               return;
+       }
+
+       pi = pf->hw.port_info;
+       mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
+       /* Ignore if event is not for Nearest Bridge */
+       type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
+               ICE_AQ_LLDP_BRID_TYPE_M);
+       dev_dbg(&pf->pdev->dev, "LLDP event MIB bridge type 0x%x\n", type);
+       if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
+               return;
+
+       /* Check MIB Type and return if event for Remote MIB update */
+       type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
+       dev_dbg(&pf->pdev->dev,
+               "LLDP event mib type %s\n", type ? "remote" : "local");
+       if (type == ICE_AQ_LLDP_MIB_REMOTE) {
+               /* Update the remote cached instance and return */
+               ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
+                                        ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
+                                        &pi->remote_dcbx_cfg);
+               if (ret) {
+                       dev_err(&pf->pdev->dev, "Failed to get remote DCB config\n");
                        return;
+               }
+       }
 
-               err = ice_lldp_to_dcb_cfg(event->msg_buf, dcbcfg);
-               if (!err)
-                       ice_pf_dcb_cfg(pf, dcbcfg, false);
+       /* store the old configuration */
+       tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
 
-               devm_kfree(&pf->pdev->dev, dcbcfg);
+       /* Reset the old DCBx configuration data */
+       memset(&pi->local_dcbx_cfg, 0, sizeof(pi->local_dcbx_cfg));
 
-               /* Get updated DCBx data from firmware */
-               err = ice_get_dcb_cfg(pf->hw.port_info);
-               if (err)
-                       dev_err(&pf->pdev->dev,
-                               "Failed to get DCB config\n");
-       } else {
+       /* Get updated DCBx data from firmware */
+       ret = ice_get_dcb_cfg(pf->hw.port_info);
+       if (ret) {
+               dev_err(&pf->pdev->dev, "Failed to get DCB config\n");
+               return;
+       }
+
+       /* No change detected in DCBX configs */
+       if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
                dev_dbg(&pf->pdev->dev,
-                       "MIB Change Event in HOST mode\n");
+                       "No change detected in DCBX configuration.\n");
+               return;
        }
+
+       need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
+                                          &pi->local_dcbx_cfg);
+       if (!need_reconfig)
+               return;
+
+       /* Enable DCB tagging only when more than one TC */
+       if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
+               dev_dbg(&pf->pdev->dev, "DCB tagging enabled (num TC > 1)\n");
+               set_bit(ICE_FLAG_DCB_ENA, pf->flags);
+       } else {
+               dev_dbg(&pf->pdev->dev, "DCB tagging disabled (num TC = 1)\n");
+               clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
+       }
+
+       rtnl_lock();
+       ice_pf_dis_all_vsi(pf, true);
+
+       ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
+       if (ret) {
+               dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
+               rtnl_unlock();
+               return;
+       }
+
+       /* changes in configuration update VSI */
+       ice_pf_dcb_recfg(pf);
+
+       ice_pf_ena_all_vsi(pf, true);
+       rtnl_unlock();
 }