git: 98b5640786f8 - main - bnxt: Add led(4) identification support
Kevin Bowling <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm |
|---|---|
| Message-ID | <[email protected]> |
The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=98b5640786f874949e441bee7c4ad5740cd6a649 commit 98b5640786f874949e441bee7c4ad5740cd6a649 Author: Kevin Bowling <[email protected]> AuthorDate: 2026-08-12 01:29:31 +0000 Commit: Kevin Bowling <[email protected]> CommitDate: 2026-08-13 15:32:07 +0000 bnxt: Add led(4) identification support Query the firmware for the LEDs on each physical port and expose /dev/led/bnxt* only when alternate blinking is supported. Configure every LED in the advertised group for identification and restore its default firmware state before a function reset. This follows the DPDK and Linux bnxt HWRM identification paths. Reviewed against: DPDK, Linux Reviewed by: Sumit Saxena <[email protected]> MFC after: 2 weeks Sponsored by: BBOX.io --- share/man/man4/bnxt.4 | 7 ++- sys/dev/bnxt/bnxt_en/bnxt.h | 15 ++++++ sys/dev/bnxt/bnxt_en/bnxt_hwrm.c | 106 ++++++++++++++++++++++++++++++++++++++- sys/dev/bnxt/bnxt_en/bnxt_hwrm.h | 2 + sys/dev/bnxt/bnxt_en/if_bnxt.c | 41 +++++++++++++++ 5 files changed, 169 insertions(+), 2 deletions(-) diff --git a/share/man/man4/bnxt.4 b/share/man/man4/bnxt.4 index 5e3ee27426d5..cedab9b83d00 100644 --- a/share/man/man4/bnxt.4 +++ b/share/man/man4/bnxt.4 @@ -23,7 +23,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF .\" THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd December 10, 2025 +.Dd August 11, 2026 .Dt BNXT 4 .Os .Sh NAME @@ -52,6 +52,11 @@ BCM574XX, BCM575XX, and BCM576XX Ethernet controllers. .Pp For more information on configuring this device, see .Xr ifconfig 8 . +.Pp +On physical functions whose firmware reports identification LED support, +the LEDs for each port are controlled through its +.Pa /dev/led/bnxt* +device node. .Sh HARDWARE The .Nm diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h index 7e58139f1ab6..d4167301ffff 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt.h @@ -468,6 +468,18 @@ struct bnxt_link_info { uint8_t active_lanes; }; +#define BNXT_MAX_LED 4 + +/* Layout of one LED capability record returned by HWRM_PORT_LED_QCAPS. */ +struct bnxt_led_info { + uint8_t led_id; + uint8_t led_type; + uint8_t led_group_id; + uint8_t unused; + uint16_t led_state_caps; + uint16_t led_color_caps; +}; + enum bnxt_phy_type { BNXT_MEDIA_CR = 0, BNXT_MEDIA_LR, @@ -1099,6 +1111,9 @@ struct bnxt_softc { struct bnxt_bar_info hwrm_bar; struct bnxt_bar_info doorbell_bar; struct bnxt_link_info link_info; + struct bnxt_led_info leds[BNXT_MAX_LED]; + uint8_t num_leds; + bool led_active; #define BNXT_FLAG_VF 0x0001 #define BNXT_FLAG_NPAR 0x0002 #define BNXT_FLAG_WOL_CAP 0x0004 diff --git a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c index 5964511f8276..a6742b6ca37c 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c @@ -74,6 +74,31 @@ static void bnxt_hwrm_set_eee(struct bnxt_softc *softc, BNXT_TX_STATS_PRI_ENTRY(counter, 6), \ BNXT_TX_STATS_PRI_ENTRY(counter, 7) +#define BNXT_LED_DFLT_ENA \ + (HWRM_PORT_LED_CFG_INPUT_ENABLES_LED0_ID | \ + HWRM_PORT_LED_CFG_INPUT_ENABLES_LED0_STATE | \ + HWRM_PORT_LED_CFG_INPUT_ENABLES_LED0_BLINK_ON | \ + HWRM_PORT_LED_CFG_INPUT_ENABLES_LED0_BLINK_OFF | \ + HWRM_PORT_LED_CFG_INPUT_ENABLES_LED0_GROUP_ID) +#define BNXT_LED_DFLT_ENA_SHIFT 6 +#define BNXT_LED_DFLT_ENABLES(_i) \ + (BNXT_LED_DFLT_ENA << (BNXT_LED_DFLT_ENA_SHIFT * (_i))) +#define BNXT_LED_ALT_BLINK_CAP \ + HWRM_PORT_LED_QCAPS_OUTPUT_LED0_STATE_CAPS_BLINK_ALT_SUPPORTED + +struct bnxt_led_cfg { + uint8_t led_id; + uint8_t led_state; + uint8_t led_color; + uint8_t unused; + uint16_t led_blink_on; + uint16_t led_blink_off; + uint8_t led_group_id; + uint8_t reserved; +}; + +CTASSERT(sizeof(struct bnxt_led_info) == 8); +CTASSERT(sizeof(struct bnxt_led_cfg) == 10); long bnxt_rx_bytes_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_bytes)}; long bnxt_rx_pkts_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_packets)}; @@ -1331,6 +1356,86 @@ fail: return rc; } +int +bnxt_hwrm_port_led_qcaps(struct bnxt_softc *softc) +{ + struct hwrm_port_led_qcaps_output *resp; + struct hwrm_port_led_qcaps_input req = {0}; + struct bnxt_led_info *led; + uint16_t caps; + int i, rc; + + softc->num_leds = 0; + if (BNXT_VF(softc) || softc->hwrm_spec_code < 0x10601) + return (0); + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_LED_QCAPS); + req.port_id = htole16(softc->pf.port_id); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc != 0) + goto out; + + /* HWRM describes up to four LED records in both response and request. */ + if (resp->num_leds == 0 || resp->num_leds > BNXT_MAX_LED) + goto out; + memcpy(softc->leds, &resp->led0_id, + sizeof(softc->leds[0]) * resp->num_leds); + softc->num_leds = resp->num_leds; + for (i = 0; i < softc->num_leds; i++) { + led = &softc->leds[i]; + caps = le16toh(led->led_state_caps); + if (led->led_group_id == 0 || + (caps & BNXT_LED_ALT_BLINK_CAP) == 0) { + softc->num_leds = 0; + break; + } + } +out: + BNXT_HWRM_UNLOCK(softc); + return (rc); +} + +int +bnxt_hwrm_port_led_cfg(struct bnxt_softc *softc, bool led_on) +{ + struct hwrm_port_led_cfg_input req = {0}; + struct bnxt_led_cfg *led_cfg; + uint32_t enables; + uint16_t duration; + uint8_t led_state; + int i; + + if (BNXT_VF(softc) || softc->num_leds == 0) + return (EOPNOTSUPP); + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_LED_CFG); + req.port_id = htole16(softc->pf.port_id); + req.num_leds = softc->num_leds; + led_state = HWRM_PORT_LED_CFG_INPUT_LED0_STATE_DEFAULT; + duration = 0; + if (led_on) { + led_state = HWRM_PORT_LED_CFG_INPUT_LED0_STATE_BLINKALT; + duration = htole16(500); + } + + enables = 0; + led_cfg = (struct bnxt_led_cfg *)(void *)&req.led0_id; + for (i = 0; i < softc->num_leds; i++, led_cfg++) { + enables |= BNXT_LED_DFLT_ENABLES(i); + led_cfg->led_id = softc->leds[i].led_id; + led_cfg->led_state = led_state; + led_cfg->led_blink_on = duration; + led_cfg->led_blink_off = duration; + led_cfg->led_group_id = softc->leds[i].led_group_id; + } + req.enables = htole32(enables); + + return (hwrm_send_message(softc, &req, sizeof(req))); +} + int bnxt_hwrm_func_qcfg(struct bnxt_softc *softc) { @@ -3446,4 +3551,3 @@ bnxt_hwrm_get_dump_len(struct bnxt_softc *softc, uint16_t dump_type, get_dump_len_exit: return (rc); } - diff --git a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h index b10981d9d53f..641a1e9ebe3a 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h @@ -69,6 +69,8 @@ int bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr, int bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr); int bnxt_hwrm_port_qstats(struct bnxt_softc *softc); int bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc); +int bnxt_hwrm_port_led_qcaps(struct bnxt_softc *softc); +int bnxt_hwrm_port_led_cfg(struct bnxt_softc *softc, bool led_on); int bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp); int bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *gr); diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c index 8ecb4770fe0e..ec88b30edcde 100644 --- a/sys/dev/bnxt/bnxt_en/if_bnxt.c +++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c @@ -217,6 +217,9 @@ static int bnxt_detach(if_ctx_t ctx); static void bnxt_init(if_ctx_t ctx); static int bnxt_init_hw(if_ctx_t ctx); static void bnxt_stop(if_ctx_t ctx); +static void bnxt_if_led_func(if_ctx_t ctx, int onoff); +static bool bnxt_if_led_supported(if_ctx_t ctx); +static void bnxt_led_restore(struct bnxt_softc *softc); static void bnxt_multi_set(if_ctx_t ctx); static int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu); static void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); @@ -342,6 +345,8 @@ static device_method_t bnxt_iflib_methods[] = { DEVMETHOD(ifdi_init, bnxt_init), DEVMETHOD(ifdi_stop, bnxt_stop), + DEVMETHOD(ifdi_led_func, bnxt_if_led_func), + DEVMETHOD(ifdi_led_supported, bnxt_if_led_supported), DEVMETHOD(ifdi_multi_set, bnxt_multi_set), DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set), DEVMETHOD(ifdi_media_status, bnxt_media_status), @@ -2244,6 +2249,7 @@ static int bnxt_open(struct bnxt_softc *bp) rc = bnxt_hwrm_func_qcaps(bp); if (rc) return rc; + (void)bnxt_hwrm_port_led_qcaps(bp); bnxt_hwrm_dbg_qcaps(bp); @@ -2251,6 +2257,8 @@ static int bnxt_open(struct bnxt_softc *bp) rc = bnxt_drv_rgtr(bp); if (rc) return rc; + /* Retry a restore which could not complete before firmware reset. */ + bnxt_led_restore(bp); if (bp->hwrm_spec_code >= 0x10803) { rc = bnxt_alloc_ctx_mem(bp); if (rc) { @@ -2728,6 +2736,7 @@ bnxt_attach_pre(if_ctx_t ctx) rc = bnxt_hwrm_func_qcaps(softc); if (rc) goto failed; + (void)bnxt_hwrm_port_led_qcaps(softc); /* Inform PF to approve MAC as default VF MAC. */ if (BNXT_VF(softc)) { @@ -3151,6 +3160,7 @@ fail: static void bnxt_func_reset(struct bnxt_softc *softc) { + bnxt_led_restore(softc); if (!BNXT_CHIP_P5_PLUS(softc)) { bnxt_hwrm_func_reset(softc); @@ -3493,6 +3503,37 @@ bnxt_stop(if_ctx_t ctx) return; } +static void +bnxt_if_led_func(if_ctx_t ctx, int onoff) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + bool active; + + active = onoff != 0; + if (active == softc->led_active) + return; + if (bnxt_hwrm_port_led_cfg(softc, active) == 0) + softc->led_active = active; +} + +static void +bnxt_led_restore(struct bnxt_softc *softc) +{ + + if (!softc->led_active) + return; + if (bnxt_hwrm_port_led_cfg(softc, false) == 0) + softc->led_active = false; +} + +static bool +bnxt_if_led_supported(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + + return (softc->num_leds != 0); +} + static u_int bnxt_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) {