aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Cassel <niklas.cassel@axis.com>2018-02-19 12:11:14 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-20 14:13:21 -0500
commit2ee2132ffb83e38338a85fb6b4eea63d7bc9660c (patch)
tree95849d2f50a459c7c84a88342224d5d4751aba11
parent13138de01400762f706c5e956e70660770d61962 (diff)
net: stmmac: add error handling in stmmac_mtl_setup()
The device tree binding for stmmac says: - Multiple TX Queues parameters: below the list of all the parameters to configure the multiple TX queues: - snps,tx-queues-to-use: number of TX queues to be used in the driver [...] - For each TX queue [...] However, if one specifies snps,tx-queues-to-use = 2, but omits the queue subnodes, or defines just one queue subnode, since the driver appears to initialize queues with sane default values, we will get tx queue timeouts. This is because the initialization code only initializes as many queues as it finds subnodes. Potentially leaving some queues uninitialized. To avoid hard to debug issues, return an error if the number of subnodes differ from snps,tx-queues-to-use/snps,rx-queues-to-use. Signed-off-by: Niklas Cassel <niklas.cassel@axis.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 05f122b8424a..bcfac84cf6fb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -135,13 +135,14 @@ static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev)
135 * stmmac_mtl_setup - parse DT parameters for multiple queues configuration 135 * stmmac_mtl_setup - parse DT parameters for multiple queues configuration
136 * @pdev: platform device 136 * @pdev: platform device
137 */ 137 */
138static void stmmac_mtl_setup(struct platform_device *pdev, 138static int stmmac_mtl_setup(struct platform_device *pdev,
139 struct plat_stmmacenet_data *plat) 139 struct plat_stmmacenet_data *plat)
140{ 140{
141 struct device_node *q_node; 141 struct device_node *q_node;
142 struct device_node *rx_node; 142 struct device_node *rx_node;
143 struct device_node *tx_node; 143 struct device_node *tx_node;
144 u8 queue = 0; 144 u8 queue = 0;
145 int ret = 0;
145 146
146 /* For backwards-compatibility with device trees that don't have any 147 /* For backwards-compatibility with device trees that don't have any
147 * snps,mtl-rx-config or snps,mtl-tx-config properties, we fall back 148 * snps,mtl-rx-config or snps,mtl-tx-config properties, we fall back
@@ -159,12 +160,12 @@ static void stmmac_mtl_setup(struct platform_device *pdev,
159 160
160 rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0); 161 rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0);
161 if (!rx_node) 162 if (!rx_node)
162 return; 163 return ret;
163 164
164 tx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-tx-config", 0); 165 tx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-tx-config", 0);
165 if (!tx_node) { 166 if (!tx_node) {
166 of_node_put(rx_node); 167 of_node_put(rx_node);
167 return; 168 return ret;
168 } 169 }
169 170
170 /* Processing RX queues common config */ 171 /* Processing RX queues common config */
@@ -220,6 +221,11 @@ static void stmmac_mtl_setup(struct platform_device *pdev,
220 221
221 queue++; 222 queue++;
222 } 223 }
224 if (queue != plat->rx_queues_to_use) {
225 ret = -EINVAL;
226 dev_err(&pdev->dev, "Not all RX queues were configured\n");
227 goto out;
228 }
223 229
224 /* Processing TX queues common config */ 230 /* Processing TX queues common config */
225 if (of_property_read_u32(tx_node, "snps,tx-queues-to-use", 231 if (of_property_read_u32(tx_node, "snps,tx-queues-to-use",
@@ -281,10 +287,18 @@ static void stmmac_mtl_setup(struct platform_device *pdev,
281 287
282 queue++; 288 queue++;
283 } 289 }
290 if (queue != plat->tx_queues_to_use) {
291 ret = -EINVAL;
292 dev_err(&pdev->dev, "Not all TX queues were configured\n");
293 goto out;
294 }
284 295
296out:
285 of_node_put(rx_node); 297 of_node_put(rx_node);
286 of_node_put(tx_node); 298 of_node_put(tx_node);
287 of_node_put(q_node); 299 of_node_put(q_node);
300
301 return ret;
288} 302}
289 303
290/** 304/**
@@ -376,6 +390,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
376 struct device_node *np = pdev->dev.of_node; 390 struct device_node *np = pdev->dev.of_node;
377 struct plat_stmmacenet_data *plat; 391 struct plat_stmmacenet_data *plat;
378 struct stmmac_dma_cfg *dma_cfg; 392 struct stmmac_dma_cfg *dma_cfg;
393 int rc;
379 394
380 plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); 395 plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
381 if (!plat) 396 if (!plat)
@@ -499,7 +514,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
499 514
500 plat->axi = stmmac_axi_setup(pdev); 515 plat->axi = stmmac_axi_setup(pdev);
501 516
502 stmmac_mtl_setup(pdev, plat); 517 rc = stmmac_mtl_setup(pdev, plat);
518 if (rc) {
519 stmmac_remove_config_dt(pdev, plat);
520 return ERR_PTR(rc);
521 }
503 522
504 /* clock setup */ 523 /* clock setup */
505 plat->stmmac_clk = devm_clk_get(&pdev->dev, 524 plat->stmmac_clk = devm_clk_get(&pdev->dev,