Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Apr 2017 16:15:50 +0000 (UTC)
From:      Sean Bruno <sbruno@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r316616 - head/sys/dev/bnxt
Message-ID:  <201704071615.v37GFoQ0036343@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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.duvvuru@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);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704071615.v37GFoQ0036343>