From owner-svn-src-all@freebsd.org Fri Mar 31 18:04:36 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 44977D22578; Fri, 31 Mar 2017 18:04:36 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0956328A; Fri, 31 Mar 2017 18:04:35 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2VI4ZNs078938; Fri, 31 Mar 2017 18:04:35 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2VI4ZTF078937; Fri, 31 Mar 2017 18:04:35 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201703311804.v2VI4ZTF078937@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Fri, 31 Mar 2017 18:04:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r316336 - head/sys/dev/vnic X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 31 Mar 2017 18:04:36 -0000 Author: zbb Date: Fri Mar 31 18:04:34 2017 New Revision: 316336 URL: https://svnweb.freebsd.org/changeset/base/316336 Log: Rework BGX detection to support both new and old firmware Improve existing BGX detection and adjust it to support both new and older ThunderX firmwares. Match BGX FDT nodes by name and reg. Match PHY instances by qlm-mode and name. Tested on Firmware Version: 2016-09-30 09:12:11 Obtained from: Semihalf Differential Revision: https://reviews.freebsd.org/D9863 Modified: head/sys/dev/vnic/thunder_bgx_fdt.c Modified: head/sys/dev/vnic/thunder_bgx_fdt.c ============================================================================== --- head/sys/dev/vnic/thunder_bgx_fdt.c Fri Mar 31 15:46:47 2017 (r316335) +++ head/sys/dev/vnic/thunder_bgx_fdt.c Fri Mar 31 18:04:34 2017 (r316336) @@ -64,6 +64,8 @@ __FBSDID("$FreeBSD$"); #define BGX_NODE_NAME "bgx" #define BGX_MAXID 9 +/* BGX func. 0, i.e.: reg = <0x8000 0 0 0 0>; DEVFN = 0x80 */ +#define BGX_DEVFN_0 0x80 #define FDT_NAME_MAXLEN 31 @@ -82,57 +84,136 @@ bgx_fdt_get_macaddr(phandle_t phy, uint8 } static boolean_t -bgx_fdt_phy_mode_match(struct bgx *bgx, char *qlm_mode, size_t size) +bgx_fdt_phy_mode_match(struct bgx *bgx, char *qlm_mode, ssize_t size) { - - size -= CONN_TYPE_OFFSET; + const char *type; + ssize_t sz; + ssize_t offset; switch (bgx->qlm_mode) { case QLM_MODE_SGMII: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "sgmii", size) == 0) - return (TRUE); + type = "sgmii"; + sz = sizeof("sgmii") - 1; + offset = size - sz; break; case QLM_MODE_XAUI_1X4: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "xaui", size) == 0) - return (TRUE); - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "dxaui", size) == 0) + type = "xaui"; + sz = sizeof("xaui") - 1; + offset = size - sz; + if (offset < 0) + return (FALSE); + if (strncmp(&qlm_mode[offset], type, sz) == 0) return (TRUE); + type = "dxaui"; + sz = sizeof("dxaui") - 1; + offset = size - sz; break; case QLM_MODE_RXAUI_2X2: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "raui", size) == 0) - return (TRUE); + type = "raui"; + sz = sizeof("raui") - 1; + offset = size - sz; break; case QLM_MODE_XFI_4X1: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "xfi", size) == 0) - return (TRUE); + type = "xfi"; + sz = sizeof("xfi") - 1; + offset = size - sz; break; case QLM_MODE_XLAUI_1X4: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "xlaui", size) == 0) - return (TRUE); + type = "xlaui"; + sz = sizeof("xlaui") - 1; + offset = size - sz; break; case QLM_MODE_10G_KR_4X1: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "xfi-10g-kr", size) == 0) - return (TRUE); + type = "xfi-10g-kr"; + sz = sizeof("xfi-10g-kr") - 1; + offset = size - sz; break; case QLM_MODE_40G_KR4_1X4: - if (strncmp(&qlm_mode[CONN_TYPE_OFFSET], "xlaui-40g-kr", size) == 0) + type = "xlaui-40g-kr"; + sz = sizeof("xlaui-40g-kr") - 1; + offset = size - sz; + break; + default: + return (FALSE); + } + + if (offset < 0) + return (FALSE); + + if (strncmp(&qlm_mode[offset], type, sz) == 0) + return (TRUE); + + return (FALSE); +} + +static boolean_t +bgx_fdt_phy_name_match(struct bgx *bgx, char *phy_name, ssize_t size) +{ + const char *type; + ssize_t sz; + + switch (bgx->qlm_mode) { + case QLM_MODE_SGMII: + type = "sgmii"; + sz = sizeof("sgmii") - 1; + break; + case QLM_MODE_XAUI_1X4: + type = "xaui"; + sz = sizeof("xaui") - 1; + if (sz < size) + return (FALSE); + if (strncmp(phy_name, type, sz) == 0) return (TRUE); + type = "dxaui"; + sz = sizeof("dxaui") - 1; + break; + case QLM_MODE_RXAUI_2X2: + type = "raui"; + sz = sizeof("raui") - 1; + break; + case QLM_MODE_XFI_4X1: + type = "xfi"; + sz = sizeof("xfi") - 1; + break; + case QLM_MODE_XLAUI_1X4: + type = "xlaui"; + sz = sizeof("xlaui") - 1; + break; + case QLM_MODE_10G_KR_4X1: + type = "xfi-10g-kr"; + sz = sizeof("xfi-10g-kr") - 1; + break; + case QLM_MODE_40G_KR4_1X4: + type = "xlaui-40g-kr"; + sz = sizeof("xlaui-40g-kr") - 1; break; default: return (FALSE); } + if (sz > size) + return (FALSE); + if (strncmp(phy_name, type, sz) == 0) + return (TRUE); + return (FALSE); } static phandle_t -bgx_fdt_traverse_nodes(phandle_t start, char *name, size_t len) +bgx_fdt_traverse_nodes(uint8_t unit, phandle_t start, char *name, + size_t len) { phandle_t node, ret; + uint32_t *reg; size_t buf_size; + ssize_t proplen; char *node_name; int err; + /* + * Traverse all subordinate nodes of 'start' to find BGX instance. + * This supports both old (by name) and new (by reg) methods. + */ buf_size = sizeof(*node_name) * FDT_NAME_MAXLEN; if (len > buf_size) { /* @@ -148,17 +229,49 @@ bgx_fdt_traverse_nodes(phandle_t start, memset(node_name, 0, buf_size); /* Recurse to children */ if (OF_child(node) != 0) { - ret = bgx_fdt_traverse_nodes(node, name, len); + ret = bgx_fdt_traverse_nodes(unit, node, name, len); if (ret != 0) { free(node_name, M_BGX); return (ret); } } - err = OF_getprop(node, "name", node_name, FDT_NAME_MAXLEN); - if ((err > 0) && (strncmp(node_name, name, len) == 0)) { + /* + * Old way - by name + */ + proplen = OF_getproplen(node, "name"); + if ((proplen <= 0) || (proplen < len)) + continue; + + err = OF_getprop(node, "name", node_name, proplen); + if (err <= 0) + continue; + + if (strncmp(node_name, name, len) == 0) { free(node_name, M_BGX); return (node); } + /* + * New way - by reg + */ + /* Check if even BGX */ + if (strncmp(node_name, + BGX_NODE_NAME, sizeof(BGX_NODE_NAME) - 1) != 0) + continue; + /* Get reg */ + err = OF_getencprop_alloc(node, "reg", sizeof(*reg), + (void **)®); + if (err == -1) { + free(reg, M_OFWPROP); + continue; + } + + /* Match BGX device function */ + if ((BGX_DEVFN_0 + unit) == (reg[0] >> 8)) { + free(reg, M_OFWPROP); + free(node_name, M_BGX); + return (node); + } + free(reg, M_OFWPROP); } free(node_name, M_BGX); @@ -249,7 +362,7 @@ bgx_fdt_find_node(struct bgx *bgx) goto out; } - node = bgx_fdt_traverse_nodes(node, bgx_sel, len); + node = bgx_fdt_traverse_nodes(bgx->bgx_id, node, bgx_sel, len); out: free(bgx_sel, M_BGX); return (node); @@ -258,8 +371,10 @@ out: int bgx_fdt_init_phy(struct bgx *bgx) { + char *node_name; phandle_t node, child; phandle_t phy, mdio; + ssize_t len; uint8_t lmac; char qlm_mode[CONN_TYPE_MAXLEN]; @@ -272,20 +387,28 @@ bgx_fdt_init_phy(struct bgx *bgx) lmac = 0; for (child = OF_child(node); child > 0; child = OF_peer(child)) { - if (OF_getprop(child, "qlm-mode", qlm_mode, - sizeof(qlm_mode)) <= 0) { - /* Missing qlm-mode, skipping */ - continue; - } + len = OF_getprop(child, "qlm-mode", qlm_mode, sizeof(qlm_mode)); + if (len > 0) { + if (!bgx_fdt_phy_mode_match(bgx, qlm_mode, len)) { + /* + * Connection type not match with BGX mode. + */ + continue; + } + } else { + len = OF_getprop_alloc(child, "name", 1, + (void **)&node_name); + if (len <= 0) { + continue; + } - if (!bgx_fdt_phy_mode_match(bgx, qlm_mode, sizeof(qlm_mode))) { - /* - * Connection type not match with BGX mode. - */ - continue; + if (!bgx_fdt_phy_name_match(bgx, node_name, len)) { + free(node_name, M_OFWPROP); + continue; + } + free(node_name, M_OFWPROP); } - /* Acquire PHY address */ if (OF_getencprop(child, "reg", &bgx->lmac[lmac].phyaddr, sizeof(bgx->lmac[lmac].phyaddr)) <= 0) {