ramips: mtk_eth_soc: fix NULL pointer dereference for syncp
[openwrt/staging/jow.git] / target / linux / ramips / files / drivers / net / ethernet / ralink / mtk_eth_soc.c
index e07e5ed5a8f8924e8f4de62f26e4655d7d30e289..dda9abee493d47fdd67cd98ab2f06236e82c3e84 100644 (file)
@@ -61,8 +61,6 @@
 #define NEXT_TX_DESP_IDX(X)    (((X) + 1) & (ring->tx_ring_size - 1))
 #define NEXT_RX_DESP_IDX(X)    (((X) + 1) & (ring->rx_ring_size - 1))
 
-#define SYSC_REG_RSTCTRL       0x34
-
 static int fe_msg_level = -1;
 module_param_named(msg_level, fe_msg_level, int, 0);
 MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)");
@@ -127,29 +125,15 @@ void fe_m32(struct fe_priv *eth, u32 clear, u32 set, unsigned reg)
        spin_unlock(&eth->page_lock);
 }
 
-void fe_reset(u32 reset_bits)
-{
-       u32 t;
-
-       t = rt_sysc_r32(SYSC_REG_RSTCTRL);
-       t |= reset_bits;
-       rt_sysc_w32(t, SYSC_REG_RSTCTRL);
-       usleep_range(10, 20);
-
-       t &= ~reset_bits;
-       rt_sysc_w32(t, SYSC_REG_RSTCTRL);
-       usleep_range(10, 20);
-}
-
-void fe_reset_fe(struct fe_priv *priv)
+static void fe_reset_fe(struct fe_priv *priv)
 {
-       if (!priv->rst_fe)
+       if (!priv->resets)
                return;
 
-       reset_control_assert(priv->rst_fe);
-       usleep_range(60, 120);
-       reset_control_deassert(priv->rst_fe);
+       reset_control_assert(priv->resets);
        usleep_range(60, 120);
+       reset_control_deassert(priv->resets);
+       usleep_range(1000, 1200);
 }
 
 static inline void fe_int_disable(u32 mask)
@@ -168,7 +152,7 @@ static inline void fe_int_enable(u32 mask)
        fe_reg_r32(FE_REG_FE_INT_ENABLE);
 }
 
-static inline void fe_hw_set_macaddr(struct fe_priv *priv, unsigned char *mac)
+static inline void fe_hw_set_macaddr(struct fe_priv *priv, const unsigned char *mac)
 {
        unsigned long flags;
 
@@ -1096,11 +1080,7 @@ poll_again:
        return rx_done;
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
-static void fe_tx_timeout(struct net_device *dev)
-#else
 static void fe_tx_timeout(struct net_device *dev, unsigned int txqueue)
-#endif
 {
        struct fe_priv *priv = netdev_priv(dev);
        struct fe_tx_ring *ring = &priv->tx_ring;
@@ -1370,10 +1350,7 @@ static int __init fe_init(struct net_device *dev)
        struct device_node *port;
        int err;
 
-       if (priv->soc->reset_fe)
-               priv->soc->reset_fe(priv);
-       else
-               fe_reset_fe(priv);
+       fe_reset_fe(priv);
 
        if (priv->soc->switch_init) {
                err = priv->soc->switch_init(priv);
@@ -1388,10 +1365,8 @@ static int __init fe_init(struct net_device *dev)
 
        fe_reset_phy(priv);
 
-       of_get_mac_address(priv->dev->of_node, dev->dev_addr);
-
-       /* If the mac address is invalid, use random mac address  */
-       if (!is_valid_ether_addr(dev->dev_addr)) {
+       /* Set the MAC address if it is correct, if not use a random MAC address  */
+       if (of_get_ethdev_address(priv->dev->of_node, dev)) {
                eth_hw_addr_random(dev);
                dev_err(priv->dev, "generated random MAC address %pM\n",
                        dev->dev_addr);
@@ -1561,7 +1536,9 @@ static int fe_probe(struct platform_device *pdev)
        struct clk *sysclk;
        int err, napi_weight;
 
-       device_reset(&pdev->dev);
+       err = device_reset(&pdev->dev);
+       if (err)
+               dev_err(&pdev->dev, "failed to reset device\n");
 
        match = of_match_device(of_fe_match, &pdev->dev);
        soc = (struct fe_soc_data *)match->data;
@@ -1597,9 +1574,11 @@ static int fe_probe(struct platform_device *pdev)
 
        priv = netdev_priv(netdev);
        spin_lock_init(&priv->page_lock);
-       priv->rst_fe = devm_reset_control_get(&pdev->dev, "fe");
-       if (IS_ERR(priv->rst_fe))
-               priv->rst_fe = NULL;
+       priv->resets = devm_reset_control_array_get_exclusive(&pdev->dev);
+       if (IS_ERR(priv->resets)) {
+               dev_err(&pdev->dev, "Failed to get resets for FE and ESW cores: %pe\n", priv->resets);
+               priv->resets = NULL;
+       }
 
        if (soc->init_data)
                soc->init_data(soc, netdev);
@@ -1622,6 +1601,7 @@ static int fe_probe(struct platform_device *pdev)
                        goto err_free_dev;
                }
                spin_lock_init(&priv->hw_stats->stats_lock);
+               u64_stats_init(&priv->hw_stats->syncp);
        }
 
        sysclk = devm_clk_get(&pdev->dev, NULL);
@@ -1649,7 +1629,6 @@ static int fe_probe(struct platform_device *pdev)
        priv->tx_ring.tx_ring_size = NUM_DMA_DESC;
        priv->rx_ring.rx_ring_size = NUM_DMA_DESC;
        INIT_WORK(&priv->pending_work, fe_pending_work);
-       u64_stats_init(&priv->hw_stats->syncp);
 
        napi_weight = 16;
        if (priv->flags & FE_FLAG_NAPI_WEIGHT) {
@@ -1657,7 +1636,11 @@ static int fe_probe(struct platform_device *pdev)
                priv->tx_ring.tx_ring_size *= 4;
                priv->rx_ring.rx_ring_size *= 4;
        }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
+       netif_napi_add_weight(netdev, &priv->rx_napi, fe_poll, napi_weight);
+#else
        netif_napi_add(netdev, &priv->rx_napi, fe_poll, napi_weight);
+#endif
        fe_set_ethtool_ops(netdev);
 
        err = register_netdev(netdev);