realtek: pcs: derive SerDes link count from DT at probe time
Previously, sds->num_of_links was incremented from rtpcs_create() as each DSA port bound its phylink_pcs. The count therefore relied on a temporal contract (DSA must finish enumerating before pcs_config runs) and on rtpcs_create() being the single chokepoint for all consumers. Replace this with a probe-time scan of pcs-handle references in the live OF tree: for every available consumer node carrying a pcs-handle property pointing at one of our SerDes subnodes, bump that SerDes' num_of_links. After the scan, the count is final regardless of when or whether DSA later calls in. To allow of_parse_phandle_with_args() to walk the property correctly, add #pcs-cells = <0> to every serdes@N node in the 838x/839x/930x/931x .dtsi files. A future cell-bearing form remains possible without touching the scan. Over-references (DT pointing more consumers at one SerDes than the hardware can carry) are clamped at RTPCS_MAX_LINKS_PER_SDS and warned about, but do not fail probe — the correctly-wired ports on that SerDes still come up, and only the surplus reference is dropped. The bounds check and the bare ++ in rtpcs_create() become redundant under the scan-driven count and are removed. This decouples num_of_links from DSA call ordering and is a prereq for migrating to fwnode_pcs providers, where rtpcs_create() goes away as the centralised counter. Link: https://github.com/openwrt/openwrt/pull/23484 Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
This commit is contained in:
parent
a7bd3b147e
commit
15593de376
@ -252,21 +252,27 @@
|
|||||||
|
|
||||||
serdes0: serdes@0 {
|
serdes0: serdes@0 {
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes1: serdes@1 {
|
serdes1: serdes@1 {
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes2: serdes@2 {
|
serdes2: serdes@2 {
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes3: serdes@3 {
|
serdes3: serdes@3 {
|
||||||
reg = <3>;
|
reg = <3>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes4: serdes@4 {
|
serdes4: serdes@4 {
|
||||||
reg = <4>;
|
reg = <4>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes5: serdes@5 {
|
serdes5: serdes@5 {
|
||||||
reg = <5>;
|
reg = <5>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -265,45 +265,59 @@
|
|||||||
|
|
||||||
serdes0: serdes@0 {
|
serdes0: serdes@0 {
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes1: serdes@1 {
|
serdes1: serdes@1 {
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes2: serdes@2 {
|
serdes2: serdes@2 {
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes3: serdes@3 {
|
serdes3: serdes@3 {
|
||||||
reg = <3>;
|
reg = <3>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes4: serdes@4 {
|
serdes4: serdes@4 {
|
||||||
reg = <4>;
|
reg = <4>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes5: serdes@5 {
|
serdes5: serdes@5 {
|
||||||
reg = <5>;
|
reg = <5>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes6: serdes@6 {
|
serdes6: serdes@6 {
|
||||||
reg = <6>;
|
reg = <6>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes7: serdes@7 {
|
serdes7: serdes@7 {
|
||||||
reg = <7>;
|
reg = <7>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes8: serdes@8 {
|
serdes8: serdes@8 {
|
||||||
reg = <8>;
|
reg = <8>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes9: serdes@9 {
|
serdes9: serdes@9 {
|
||||||
reg = <9>;
|
reg = <9>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes10: serdes@10 {
|
serdes10: serdes@10 {
|
||||||
reg = <10>;
|
reg = <10>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes11: serdes@11 {
|
serdes11: serdes@11 {
|
||||||
reg = <11>;
|
reg = <11>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes12: serdes@12 {
|
serdes12: serdes@12 {
|
||||||
reg = <12>;
|
reg = <12>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes13: serdes@13 {
|
serdes13: serdes@13 {
|
||||||
reg = <13>;
|
reg = <13>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -252,39 +252,51 @@
|
|||||||
|
|
||||||
serdes0: serdes@0 {
|
serdes0: serdes@0 {
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes1: serdes@1 {
|
serdes1: serdes@1 {
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes2: serdes@2 {
|
serdes2: serdes@2 {
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes3: serdes@3 {
|
serdes3: serdes@3 {
|
||||||
reg = <3>;
|
reg = <3>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes4: serdes@4 {
|
serdes4: serdes@4 {
|
||||||
reg = <4>;
|
reg = <4>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes5: serdes@5 {
|
serdes5: serdes@5 {
|
||||||
reg = <5>;
|
reg = <5>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes6: serdes@6 {
|
serdes6: serdes@6 {
|
||||||
reg = <6>;
|
reg = <6>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes7: serdes@7 {
|
serdes7: serdes@7 {
|
||||||
reg = <7>;
|
reg = <7>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes8: serdes@8 {
|
serdes8: serdes@8 {
|
||||||
reg = <8>;
|
reg = <8>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes9: serdes@9 {
|
serdes9: serdes@9 {
|
||||||
reg = <9>;
|
reg = <9>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes10: serdes@10 {
|
serdes10: serdes@10 {
|
||||||
reg = <10>;
|
reg = <10>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes11: serdes@11 {
|
serdes11: serdes@11 {
|
||||||
reg = <11>;
|
reg = <11>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -284,45 +284,59 @@
|
|||||||
|
|
||||||
serdes0: serdes@0 {
|
serdes0: serdes@0 {
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes1: serdes@1 {
|
serdes1: serdes@1 {
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes2: serdes@2 {
|
serdes2: serdes@2 {
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes3: serdes@3 {
|
serdes3: serdes@3 {
|
||||||
reg = <3>;
|
reg = <3>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes4: serdes@4 {
|
serdes4: serdes@4 {
|
||||||
reg = <4>;
|
reg = <4>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes5: serdes@5 {
|
serdes5: serdes@5 {
|
||||||
reg = <5>;
|
reg = <5>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes6: serdes@6 {
|
serdes6: serdes@6 {
|
||||||
reg = <6>;
|
reg = <6>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes7: serdes@7 {
|
serdes7: serdes@7 {
|
||||||
reg = <7>;
|
reg = <7>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes8: serdes@8 {
|
serdes8: serdes@8 {
|
||||||
reg = <8>;
|
reg = <8>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes9: serdes@9 {
|
serdes9: serdes@9 {
|
||||||
reg = <9>;
|
reg = <9>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes10: serdes@10 {
|
serdes10: serdes@10 {
|
||||||
reg = <10>;
|
reg = <10>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes11: serdes@11 {
|
serdes11: serdes@11 {
|
||||||
reg = <11>;
|
reg = <11>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes12: serdes@12 {
|
serdes12: serdes@12 {
|
||||||
reg = <12>;
|
reg = <12>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
serdes13: serdes@13 {
|
serdes13: serdes@13 {
|
||||||
reg = <13>;
|
reg = <13>;
|
||||||
|
#pcs-cells = <0>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4107,8 +4107,6 @@ struct phylink_pcs *rtpcs_create(struct device *dev, struct device_node *np, int
|
|||||||
sds = &ctrl->serdes[sds_id];
|
sds = &ctrl->serdes[sds_id];
|
||||||
if (rtpcs_sds_read(sds, 0, 0) < 0)
|
if (rtpcs_sds_read(sds, 0, 0) < 0)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
if (sds->num_of_links >= RTPCS_MAX_LINKS_PER_SDS)
|
|
||||||
return ERR_PTR(-ERANGE);
|
|
||||||
|
|
||||||
link = devm_kzalloc(ctrl->dev, sizeof(*link), GFP_KERNEL);
|
link = devm_kzalloc(ctrl->dev, sizeof(*link), GFP_KERNEL);
|
||||||
if (!link) {
|
if (!link) {
|
||||||
@ -4118,7 +4116,6 @@ struct phylink_pcs *rtpcs_create(struct device *dev, struct device_node *np, int
|
|||||||
|
|
||||||
device_link_add(dev, ctrl->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
|
device_link_add(dev, ctrl->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
|
||||||
|
|
||||||
sds->num_of_links++;
|
|
||||||
link->ctrl = ctrl;
|
link->ctrl = ctrl;
|
||||||
link->port = port;
|
link->port = port;
|
||||||
link->sds = sds;
|
link->sds = sds;
|
||||||
@ -4166,6 +4163,41 @@ static void rtpcs_sds_put_of_node(void *data)
|
|||||||
of_node_put(sds->of_node);
|
of_node_put(sds->of_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtpcs_count_links(struct rtpcs_ctrl *ctrl)
|
||||||
|
{
|
||||||
|
struct device_node *consumer __free(device_node) = NULL;
|
||||||
|
struct of_phandle_args args;
|
||||||
|
|
||||||
|
for_each_node_with_property(consumer, "pcs-handle") {
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
if (!of_device_is_available(consumer))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
while (!of_parse_phandle_with_args(consumer, "pcs-handle",
|
||||||
|
"#pcs-cells", idx++, &args)) {
|
||||||
|
struct device_node *arg_np __free(device_node) = args.np;
|
||||||
|
|
||||||
|
for (int s = 0; s < ctrl->cfg->serdes_count; s++) {
|
||||||
|
struct rtpcs_serdes *sds = &ctrl->serdes[s];
|
||||||
|
|
||||||
|
if (arg_np != sds->of_node)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sds->num_of_links >= RTPCS_MAX_LINKS_PER_SDS) {
|
||||||
|
dev_warn(ctrl->dev,
|
||||||
|
"%pOF: pcs-handle to sds%u exceeds max %u, clamping\n",
|
||||||
|
consumer, sds->id, RTPCS_MAX_LINKS_PER_SDS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sds->num_of_links++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int rtpcs_probe(struct platform_device *pdev)
|
static int rtpcs_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
@ -4220,6 +4252,8 @@ static int rtpcs_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtpcs_count_links(ctrl);
|
||||||
|
|
||||||
if (ctrl->cfg->init) {
|
if (ctrl->cfg->init) {
|
||||||
ret = ctrl->cfg->init(ctrl);
|
ret = ctrl->cfg->init(ctrl);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user