Author: sbruno Date: Fri Apr 7 16:15:50 2017 New Revision: 316616 URL: https://svnweb.freebsd.org/changeset/base/316616
Log: bnxt(4): add support for WOL Magic. Submitted by: venkatkumar.duvv...@broadcom.com Differential Revision: https://reviews.freebsd.org/D10124 Modified: head/sys/dev/bnxt/bnxt.h head/sys/dev/bnxt/bnxt_hwrm.c head/sys/dev/bnxt/bnxt_hwrm.h head/sys/dev/bnxt/if_bnxt.c Modified: head/sys/dev/bnxt/bnxt.h ============================================================================== --- head/sys/dev/bnxt/bnxt.h Fri Apr 7 16:14:25 2017 (r316615) +++ head/sys/dev/bnxt/bnxt.h Fri Apr 7 16:15:50 2017 (r316616) @@ -100,6 +100,9 @@ __FBSDID("$FreeBSD$"); #define BNXT_RSS_HASH_TYPE_IPV6 5 #define BNXT_GET_RSS_PROFILE_ID(rss_hash_type) ((rss_hash_type >> 1) & 0x1F) +#define BNXT_NO_MORE_WOL_FILTERS 0xFFFF +#define bnxt_wol_supported(softc) ((softc)->flags & BNXT_FLAG_WOL_CAP) + /* Completion related defines */ #define CMP_VALID(cmp, v_bit) \ ((!!(((struct cmpl_base *)(cmp))->info3_v & htole32(CMPL_BASE_V))) == !!(v_bit) ) @@ -512,7 +515,8 @@ struct bnxt_softc { struct bnxt_bar_info hwrm_bar; struct bnxt_bar_info doorbell_bar; struct bnxt_link_info link_info; -#define BNXT_FLAG_NPAR 1 +#define BNXT_FLAG_NPAR 0x1 +#define BNXT_FLAG_WOL_CAP 0x2 uint32_t flags; uint32_t total_msix; @@ -562,6 +566,8 @@ struct bnxt_softc { struct bnxt_full_tpa_start *tpa_start; struct bnxt_ver_info *ver_info; struct bnxt_nvram_info *nvm_info; + bool wol; + uint8_t wol_filter_id; }; struct bnxt_filter_info { Modified: head/sys/dev/bnxt/bnxt_hwrm.c ============================================================================== --- head/sys/dev/bnxt/bnxt_hwrm.c Fri Apr 7 16:14:25 2017 (r316615) +++ head/sys/dev/bnxt/bnxt_hwrm.c Fri Apr 7 16:15:50 2017 (r316616) @@ -398,6 +398,10 @@ bnxt_hwrm_func_qcaps(struct bnxt_softc * if (rc) goto fail; + if (resp->flags & + htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED)) + softc->flags |= BNXT_FLAG_WOL_CAP; + func->fw_fid = le16toh(resp->fid); memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN); func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx); @@ -1483,3 +1487,63 @@ exit: BNXT_HWRM_UNLOCK(softc); return rc; } + +uint16_t +bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle) +{ + struct hwrm_wol_filter_qcfg_input req = {0}; + struct hwrm_wol_filter_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + uint16_t next_handle = 0; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG); + req.port_id = htole16(softc->pf.port_id); + req.handle = htole16(handle); + rc = hwrm_send_message(softc, &req, sizeof(req)); + if (!rc) { + next_handle = le16toh(resp->next_handle); + if (next_handle != 0) { + if (resp->wol_type == + HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) { + softc->wol = 1; + softc->wol_filter_id = resp->wol_filter_id; + } + } + } + return next_handle; +} + +int +bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc) +{ + struct hwrm_wol_filter_alloc_input req = {0}; + struct hwrm_wol_filter_alloc_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC); + req.port_id = htole16(softc->pf.port_id); + req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT; + req.enables = + htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS); + memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN); + rc = hwrm_send_message(softc, &req, sizeof(req)); + if (!rc) + softc->wol_filter_id = resp->wol_filter_id; + + return rc; +} + +int +bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc) +{ + struct hwrm_wol_filter_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE); + req.port_id = htole16(softc->pf.port_id); + req.enables = + htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID); + req.wol_filter_id = softc->wol_filter_id; + return hwrm_send_message(softc, &req, sizeof(req)); +} Modified: head/sys/dev/bnxt/bnxt_hwrm.h ============================================================================== --- head/sys/dev/bnxt/bnxt_hwrm.h Fri Apr 7 16:14:25 2017 (r316615) +++ head/sys/dev/bnxt/bnxt_hwrm.h Fri Apr 7 16:15:50 2017 (r316616) @@ -98,5 +98,8 @@ int bnxt_hwrm_fw_set_time(struct bnxt_so uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond, uint16_t zone); int bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc); +uint16_t bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle); +int bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc); +int bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc); #endif Modified: head/sys/dev/bnxt/if_bnxt.c ============================================================================== --- head/sys/dev/bnxt/if_bnxt.c Fri Apr 7 16:14:25 2017 (r316615) +++ head/sys/dev/bnxt/if_bnxt.c Fri Apr 7 16:15:50 2017 (r316616) @@ -189,6 +189,10 @@ static void bnxt_vlan_unregister(if_ctx_ /* ioctl */ static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); +static int bnxt_shutdown(if_ctx_t ctx); +static int bnxt_suspend(if_ctx_t ctx); +static int bnxt_resume(if_ctx_t ctx); + /* Internal support functions */ static int bnxt_probe_phy(struct bnxt_softc *softc); static void bnxt_add_media_types(struct bnxt_softc *softc); @@ -206,6 +210,8 @@ static void bnxt_handle_async_event(stru struct cmpl_base *cmpl); static uint8_t get_phy_type(struct bnxt_softc *softc); static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); +static void bnxt_get_wol_settings(struct bnxt_softc *softc); +static int bnxt_wol_config(if_ctx_t ctx); /* * Device Interface Declaration @@ -264,6 +270,10 @@ static device_method_t bnxt_iflib_method DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl), + DEVMETHOD(ifdi_suspend, bnxt_suspend), + DEVMETHOD(ifdi_shutdown, bnxt_shutdown), + DEVMETHOD(ifdi_resume, bnxt_resume), + DEVMETHOD_END }; @@ -678,6 +688,7 @@ bnxt_attach_pre(if_ctx_t ctx) rc = bnxt_hwrm_func_qcaps(softc); if (rc) goto failed; + iflib_set_mac(ctx, softc->func.mac_addr); scctx->isc_txrx = &bnxt_txrx; @@ -694,6 +705,9 @@ bnxt_attach_pre(if_ctx_t ctx) /* These likely get lost... */ IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU; + if (bnxt_wol_supported(softc)) + scctx->isc_capenable |= IFCAP_WOL_MAGIC; + /* Get the queue config */ rc = bnxt_hwrm_queue_qportcfg(softc); if (rc) { @@ -701,6 +715,8 @@ bnxt_attach_pre(if_ctx_t ctx) goto failed; } + bnxt_get_wol_settings(softc); + /* Now perform a function reset */ rc = bnxt_hwrm_func_reset(softc); bnxt_clear_ids(softc); @@ -839,6 +855,7 @@ bnxt_detach(if_ctx_t ctx) struct bnxt_vlan_tag *tmp; int i; + bnxt_wol_config(ctx); bnxt_do_disable_intr(&softc->def_cp_ring); bnxt_free_sysctl_ctx(softc); bnxt_hwrm_func_reset(softc); @@ -1550,6 +1567,58 @@ bnxt_vlan_unregister(if_ctx_t ctx, uint1 } static int +bnxt_wol_config(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + if_t ifp = iflib_get_ifp(ctx); + + if (!softc) + return -EBUSY; + + if (!bnxt_wol_supported(softc)) + return -ENOTSUP; + + if (if_getcapabilities(ifp) & IFCAP_WOL_MAGIC) { + if (!softc->wol) { + if (bnxt_hwrm_alloc_wol_fltr(softc)) + return -EBUSY; + softc->wol = 1; + } + } else { + if (softc->wol) { + if (bnxt_hwrm_free_wol_fltr(softc)) + return -EBUSY; + softc->wol = 0; + } + } + + return 0; +} + +static int +bnxt_shutdown(if_ctx_t ctx) +{ + bnxt_wol_config(ctx); + return 0; +} + +static int +bnxt_suspend(if_ctx_t ctx) +{ + bnxt_wol_config(ctx); + return 0; +} + +static int +bnxt_resume(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + + bnxt_get_wol_settings(softc); + return 0; +} + +static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) { struct bnxt_softc *softc = iflib_get_softc(ctx); @@ -2422,3 +2491,16 @@ bnxt_get_baudrate(struct bnxt_link_info } return IF_Gbps(100); } + +static void +bnxt_get_wol_settings(struct bnxt_softc *softc) +{ + uint16_t wol_handle = 0; + + if (!bnxt_wol_supported(softc)) + return; + + do { + wol_handle = bnxt_hwrm_get_wol_fltrs(softc, wol_handle); + } while (wol_handle && wol_handle != BNXT_NO_MORE_WOL_FILTERS); +} _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"