Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137055194
D5066.id12796.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D5066.id12796.diff
View Options
Index: head/sys/dev/vnic/thunder_bgx.c
===================================================================
--- head/sys/dev/vnic/thunder_bgx.c
+++ head/sys/dev/vnic/thunder_bgx.c
@@ -68,7 +68,7 @@
#define THUNDER_BGX_DEVSTR "ThunderX BGX Ethernet I/O Interface"
-static MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory");
+MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory");
#define BGX_NODE_ID_MASK 0x1
#define BGX_NODE_ID_SHIFT 24
Index: head/sys/dev/vnic/thunder_bgx_fdt.c
===================================================================
--- head/sys/dev/vnic/thunder_bgx_fdt.c
+++ head/sys/dev/vnic/thunder_bgx_fdt.c
@@ -53,6 +53,7 @@
#include <net/if_media.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/mii/miivar.h>
#include "thunder_bgx.h"
@@ -61,6 +62,11 @@
#define CONN_TYPE_MAXLEN 16
#define CONN_TYPE_OFFSET 2
+#define BGX_NODE_NAME "bgx"
+#define BGX_MAXID 9
+
+#define FDT_NAME_MAXLEN 31
+
int bgx_fdt_init_phy(struct bgx *);
static void
@@ -119,28 +125,152 @@
return (FALSE);
}
+static phandle_t
+bgx_fdt_traverse_nodes(phandle_t start, char *name, size_t len)
+{
+ phandle_t node, ret;
+ size_t buf_size;
+ char *node_name;
+ int err;
+
+ buf_size = sizeof(*node_name) * FDT_NAME_MAXLEN;
+ if (len > buf_size) {
+ /*
+ * This is an erroneous situation since the string
+ * to compare cannot be longer than FDT_NAME_MAXLEN.
+ */
+ return (0);
+ }
+
+ node_name = malloc(buf_size, M_BGX, M_WAITOK);
+ for (node = OF_child(start); node != 0; node = OF_peer(node)) {
+ /* Clean-up the buffer */
+ memset(node_name, 0, buf_size);
+ /* Recurse to children */
+ if (OF_child(node) != 0) {
+ ret = bgx_fdt_traverse_nodes(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)) {
+ free(node_name, M_BGX);
+ return (node);
+ }
+ }
+ free(node_name, M_BGX);
+
+ return (0);
+}
+
+/*
+ * Similar functionality to pci_find_pcie_root_port()
+ * but this one works for ThunderX.
+ */
+static device_t
+bgx_find_root_pcib(device_t dev)
+{
+ devclass_t pci_class;
+ device_t pcib, bus;
+
+ pci_class = devclass_find("pci");
+ KASSERT(device_get_devclass(device_get_parent(dev)) == pci_class,
+ ("%s: non-pci device %s", __func__, device_get_nameunit(dev)));
+
+ /* Walk the bridge hierarchy until we find a non-PCI device */
+ for (;;) {
+ bus = device_get_parent(dev);
+ KASSERT(bus != NULL, ("%s: null parent of %s", __func__,
+ device_get_nameunit(dev)));
+
+ if (device_get_devclass(bus) != pci_class)
+ return (NULL);
+
+ pcib = device_get_parent(bus);
+ KASSERT(pcib != NULL, ("%s: null bridge of %s", __func__,
+ device_get_nameunit(bus)));
+
+ /*
+ * If the parent of this PCIB is not PCI
+ * then we found our root PCIB.
+ */
+ if (device_get_devclass(device_get_parent(pcib)) != pci_class)
+ return (pcib);
+
+ dev = pcib;
+ }
+}
+
+static __inline phandle_t
+bgx_fdt_find_node(struct bgx *bgx)
+{
+ device_t root_pcib;
+ phandle_t node;
+ char *bgx_sel;
+ size_t len;
+
+ KASSERT(bgx->bgx_id <= BGX_MAXID,
+ ("Invalid BGX ID: %d, max: %d", bgx->bgx_id, BGX_MAXID));
+
+ len = sizeof(BGX_NODE_NAME) + 1; /* <bgx_name>+<digit>+<\0> */
+ /* Allocate memory for BGX node name + "/" character */
+ bgx_sel = malloc(sizeof(*bgx_sel) * (len + 1), M_BGX,
+ M_ZERO | M_WAITOK);
+
+ /* Prepare node's name */
+ snprintf(bgx_sel, len + 1, "/"BGX_NODE_NAME"%d", bgx->bgx_id);
+ /* First try the root node */
+ node = OF_finddevice(bgx_sel);
+ if ((int)node > 0) {
+ /* Found relevant node */
+ goto out;
+ }
+ /*
+ * Clean-up and try to find BGX in DT
+ * starting from the parent PCI bridge node.
+ */
+ memset(bgx_sel, 0, sizeof(*bgx_sel) * (len + 1));
+ snprintf(bgx_sel, len, BGX_NODE_NAME"%d", bgx->bgx_id);
+
+ /* Find PCI bridge that we are connected to */
+
+ root_pcib = bgx_find_root_pcib(bgx->dev);
+ if (root_pcib == NULL) {
+ device_printf(bgx->dev, "Unable to find BGX root bridge\n");
+ node = 0;
+ goto out;
+ }
+
+ node = ofw_bus_get_node(root_pcib);
+ if (node == 0) {
+ device_printf(bgx->dev, "No parent FDT node for BGX\n");
+ goto out;
+ }
+
+ node = bgx_fdt_traverse_nodes(node, bgx_sel, len);
+out:
+ free(bgx_sel, M_BGX);
+ return (node);
+}
+
int
bgx_fdt_init_phy(struct bgx *bgx)
{
phandle_t node, child;
phandle_t phy, mdio;
uint8_t lmac;
- char bgx_sel[6];
char qlm_mode[CONN_TYPE_MAXLEN];
- const char *mac;
-
- (void)mac;
- lmac = 0;
- /* Get BGX node from DT */
- snprintf(bgx_sel, 6, "/bgx%d", bgx->bgx_id);
- node = OF_finddevice(bgx_sel);
- if (node == 0 || node == -1) {
+ node = bgx_fdt_find_node(bgx);
+ if (node == 0) {
device_printf(bgx->dev,
- "Could not find %s node in FDT\n", bgx_sel);
+ "Could not find bgx%d node in FDT\n", bgx->bgx_id);
return (ENXIO);
}
+ 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) {
Index: head/sys/dev/vnic/thunder_bgx_var.h
===================================================================
--- head/sys/dev/vnic/thunder_bgx_var.h
+++ head/sys/dev/vnic/thunder_bgx_var.h
@@ -30,6 +30,8 @@
#ifndef __THUNDER_BGX_VAR_H__
#define __THUNDER_BGX_VAR_H__
+MALLOC_DECLARE(M_BGX);
+
struct lmac {
struct bgx *bgx;
int dmac;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 22, 1:41 AM (11 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25862449
Default Alt Text
D5066.id12796.diff (5 KB)
Attached To
Mode
D5066: Fix finding appropriate BGX node in DTB and move it to a separate function
Attached
Detach File
Event Timeline
Log In to Comment