bnxt(4): add support for WOL Magic.
Submitted by: venkatkumar.duvvuru@broadcom.com Differential Revision: https://reviews.freebsd.org/D10124
This commit is contained in:
parent
a9ea7aa142
commit
c51fe51dd0
@ -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 {
|
||||
|
@ -398,6 +398,10 @@ bnxt_hwrm_func_qcaps(struct bnxt_softc *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 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
|
||||
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));
|
||||
}
|
||||
|
@ -98,5 +98,8 @@ int bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year,
|
||||
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
|
||||
|
@ -189,6 +189,10 @@ static void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag);
|
||||
/* 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(struct bnxt_softc *softc,
|
||||
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_methods[] = {
|
||||
|
||||
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);
|
||||
@ -1549,6 +1566,58 @@ bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -2422,3 +2491,16 @@ bnxt_get_baudrate(struct bnxt_link_info *link)
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user