From: Andy Moreton <[email protected]>

Code analysis reports that *enum_hwp is not written on successful
return on some paths through this function. Refactor to simplify the
code, and adjust the annotations so it is clear that *enum_hwp is only
written on successful return. Adjust FEC handling in efx_np_link_ctrl
to allow for *supportedp always being updated.

Code analysis also reports that the optional filter_arg can be NULL
when invoking filter_cb, but the callback argument is not optional.
Check that filter_arg is non-NULL to ensure correct usage.

The refactoring adds an explicit default for the HW enum for the case when
no software capability bit is found in the map. For the link technology,
this default becomes AUTO, replacing the implicit NONE. This change is
intentional and yields the correct instruction to firmware.

Fixes: 8e79cd30230d ("common/sfc_efx/base: implement PHY link control for 
Medford4")
Cc: [email protected]

Signed-off-by: Andy Moreton <[email protected]>
Reviewed-by: Ivan Malov <[email protected]>
Reviewed-by: Viacheslav Galaktionov <[email protected]>
---
 drivers/common/sfc_efx/base/efx_np.c | 68 ++++++++++++++--------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_np.c 
b/drivers/common/sfc_efx/base/efx_np.c
index 6fc024e17b..06cb33e39b 100644
--- a/drivers/common/sfc_efx/base/efx_np.c
+++ b/drivers/common/sfc_efx/base/efx_np.c
@@ -1211,60 +1211,59 @@ efx_np_cap_mask_sw_to_hw(
            MC_CMD_##_hw_cap_section##_LEN, (_mask_sw),                 \
            (_filter_cb), (_filter_arg), (_mask_hwp))
 
-static                                 void
+__success(*supportedp != 0)    static  void
 efx_np_cap_sw_mask_to_hw_enum(
        __in_ecount(hw_sw_map_nentries) const struct efx_np_cap_map *hw_sw_map,
        __in                            unsigned int hw_sw_map_nentries,
        __in_bcount(hw_cap_data_nbytes) const uint8_t *hw_cap_data,
        __in                            size_t hw_cap_data_nbytes,
        __in                            uint32_t mask_sw,
+       __in                            uint16_t enum_hw_def,
        __in_opt                        efx_np_cap_filter_cb *filter_cb,
        __in_opt                        void *filter_arg,
        __out                           boolean_t *supportedp,
        __out_opt                       uint16_t *enum_hwp)
 {
-       unsigned int sw_nflags_req = 0;
-       uint32_t sw_check_mask = 0;
+       boolean_t supported = B_FALSE;
+       uint32_t matched_mask = 0;
+       uint32_t flags_seen = 0;
        unsigned int i;
 
        for (i = 0; i < hw_sw_map_nentries; ++i) {
-               uint32_t flag_sw = 1U << hw_sw_map->encm_sw;
-               unsigned int byte_idx = CAP_BYTE(hw_sw_map);
-               uint8_t flag_hw = CAP_FLAG(hw_sw_map);
+               uint32_t flag_sw = 1U << hw_sw_map[i].encm_sw;
+               unsigned int byte_idx = CAP_BYTE(&hw_sw_map[i]);
+               uint8_t flag_hw = CAP_FLAG(&hw_sw_map[i]);
 
-               if (byte_idx >= hw_cap_data_nbytes) {
-                       ++(hw_sw_map);
+               if (byte_idx >= hw_cap_data_nbytes)
                        continue;
-               }
 
-               if ((mask_sw & flag_sw) == flag_sw) {
-                       if ((sw_check_mask & flag_sw) == 0)
-                               ++(sw_nflags_req);
+               if ((mask_sw & flag_sw) != flag_sw)
+                       continue;
 
-                       sw_check_mask |= flag_sw;
+               flags_seen |= flag_sw;
 
-                       if ((hw_cap_data[byte_idx] & flag_hw) == flag_hw) {
-                               if (filter_cb == NULL ||
-                                   filter_cb(hw_sw_map->encm_hw, filter_arg) !=
-                                   B_FALSE) {
-                                       mask_sw &= ~(flag_sw);
+               if ((hw_cap_data[byte_idx] & flag_hw) != flag_hw)
+                       continue;
 
-                                       if (enum_hwp != NULL)
-                                               *enum_hwp = hw_sw_map->encm_hw;
-                               }
-                       }
-               }
+               if ((filter_cb != NULL) && (filter_arg != NULL) &&
+                   (filter_cb(hw_sw_map[i].encm_hw, filter_arg) == B_FALSE))
+                       continue;
 
-               ++(hw_sw_map);
+               if (enum_hwp != NULL && (matched_mask & flag_sw) == 0)
+                       *enum_hwp = hw_sw_map[i].encm_hw;
+
+               matched_mask |= flag_sw;
+               supported = B_TRUE;
        }
 
-       if (sw_check_mask != 0 && (mask_sw & sw_check_mask) == sw_check_mask) {
-               /* Failed to select the enum by at least one capability bit. */
-               *supportedp = B_FALSE;
-               return;
+       if (flags_seen == 0) {
+               if (enum_hwp != NULL)
+                       *enum_hwp = enum_hw_def;
+
+               supported = B_TRUE;
        }
 
-       *supportedp = B_TRUE;
+       *supportedp = supported;
 }
 
 /*
@@ -1276,12 +1275,13 @@ efx_np_cap_sw_mask_to_hw_enum(
  */
 #define        EFX_NP_CAP_SW_MASK_TO_HW_ENUM(                                  
\
            _hw_sw_cap_map, _hw_cap_section, _hw_cap_data,              \
-           _mask_sw, _filter_cb, _filter_arg, _supportedp, _enum_hwp)  \
+           _mask_sw, _enum_hw_def, _filter_cb, _filter_arg,            \
+           _supportedp, _enum_hwp)                                     \
        efx_np_cap_sw_mask_to_hw_enum((_hw_sw_cap_map),                 \
            EFX_ARRAY_SIZE(_hw_sw_cap_map),                             \
            MCDI_STRUCT_MEMBER((_hw_cap_data), const uint8_t,           \
                    MC_CMD_##_hw_cap_section),                          \
-           MC_CMD_##_hw_cap_section##_LEN, (_mask_sw),                 \
+           MC_CMD_##_hw_cap_section##_LEN, (_mask_sw), (_enum_hw_def), \
            (_filter_cb), (_filter_arg),                                \
            (_supportedp), (_enum_hwp))
 
@@ -1396,6 +1396,7 @@ efx_np_link_ctrl(
        } else {
                EFX_NP_CAP_SW_MASK_TO_HW_ENUM(efx_np_cap_map_tech,
                    ETH_AN_FIELDS_TECH_MASK, cap_data_raw, cap_mask_sw,
+                   MC_CMD_ETH_TECH_AUTO,
                    efx_np_filter_tech_by_lane_count_cb, &lane_count,
                    &supported, &link_tech);
 
@@ -1424,10 +1425,9 @@ efx_np_link_ctrl(
                 */
                EFX_NP_CAP_SW_MASK_TO_HW_ENUM(efx_np_cap_map_fec_req,
                    ETH_AN_FIELDS_FEC_MASK, cap_data_raw, cap_mask_sw,
-                   NULL, NULL, &supported, &cap_enum_hw);
+                   cap_enum_hw, NULL, NULL, &supported, &cap_enum_hw);
 
-               if ((cap_mask_sw & EFX_PHY_CAP_FEC_MASK) != 0
-                   && supported == B_FALSE) {
+               if (supported == B_FALSE) {
                        rc = ENOTSUP;
                        goto fail5;
                }
-- 
2.47.3

Reply via email to