Query the firmware version at init (already done in wait_ready), cache it in priv->fw_version, and provide MXL862XX_FW_VER_MIN() for version-gated code paths throughout the driver. The union mxl862xx_fw_version lays out major/minor/revision so that the u32 raw field compares with natural version ordering on both big- and little-endian machines. Signed-off-by: Daniel Golle --- drivers/net/dsa/mxl862xx/mxl862xx.c | 3 +++ drivers/net/dsa/mxl862xx/mxl862xx.h | 36 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/drivers/net/dsa/mxl862xx/mxl862xx.c b/drivers/net/dsa/mxl862xx/mxl862xx.c index b60482d93a85..2f22adedfbf6 100644 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c @@ -257,6 +257,9 @@ static int mxl862xx_wait_ready(struct dsa_switch *ds) ver.iv_major, ver.iv_minor, le16_to_cpu(ver.iv_revision), le32_to_cpu(ver.iv_build_num)); + priv->fw_version.major = ver.iv_major; + priv->fw_version.minor = ver.iv_minor; + priv->fw_version.revision = le16_to_cpu(ver.iv_revision); return 0; not_ready_yet: diff --git a/drivers/net/dsa/mxl862xx/mxl862xx.h b/drivers/net/dsa/mxl862xx/mxl862xx.h index 80053ab40e4c..79fd32c4db4e 100644 --- a/drivers/net/dsa/mxl862xx/mxl862xx.h +++ b/drivers/net/dsa/mxl862xx/mxl862xx.h @@ -3,6 +3,7 @@ #ifndef __MXL862XX_H #define __MXL862XX_H +#include #include #include #include @@ -241,6 +242,38 @@ struct mxl862xx_port { spinlock_t stats_lock; /* protects stats accumulators */ }; +/** + * union mxl862xx_fw_version - firmware version for comparison and display + * @major: firmware major version + * @minor: firmware minor version + * @revision: firmware revision number + * @raw: combined u32 for direct >= comparison (major most significant) + * + * The struct layout places major in the most-significant byte of the + * u32 on both big- and little-endian machines, so raw values compare + * with the natural major > minor > revision ordering. + */ +union mxl862xx_fw_version { + struct { +#if defined(__BIG_ENDIAN) + u8 major; + u8 minor; + u16 revision; +#elif defined(__LITTLE_ENDIAN) + u16 revision; + u8 minor; + u8 major; +#endif + }; + u32 raw; +}; + +#define MXL862XX_FW_VER(maj, min, rev) \ + ((union mxl862xx_fw_version){ .major = (maj), .minor = (min), \ + .revision = (rev) }).raw +#define MXL862XX_FW_VER_MIN(priv, maj, min, rev) \ + ((priv)->fw_version.raw >= MXL862XX_FW_VER(maj, min, rev)) + /* Bit indices for struct mxl862xx_priv::flags */ #define MXL862XX_FLAG_CRC_ERR 0 #define MXL862XX_FLAG_WORK_STOPPED 1 @@ -258,6 +291,8 @@ struct mxl862xx_port { * @drop_meter: index of the single shared zero-rate firmware meter * used to unconditionally drop traffic (used to block * flooding) + * @fw_version: cached firmware version, populated at probe and + * compared with MXL862XX_FW_VER_MIN() * @ports: per-port state, indexed by switch port number * @bridges: maps DSA bridge number to firmware bridge ID; * zero means no firmware bridge allocated for that @@ -275,6 +310,7 @@ struct mxl862xx_priv { struct work_struct crc_err_work; unsigned long flags; u16 drop_meter; + union mxl862xx_fw_version fw_version; struct mxl862xx_port ports[MXL862XX_MAX_PORTS]; u16 bridges[MXL862XX_MAX_BRIDGES + 1]; u16 evlan_ingress_size; -- 2.54.0