ar8216: remove superfluous code from ar8216_config_init
[openwrt.git] / target / linux / generic / files / drivers / net / phy / ar8216.c
index 7fbc531..811e406 100644 (file)
@@ -101,6 +101,9 @@ struct ar8216_priv {
        int mib_next_port;
        u64 *mib_stats;
 
+       struct list_head list;
+       unsigned int use_count;
+
        /* all fields below are cleared on reset */
        bool vlan;
        u16 vlan_id[AR8X16_MAX_VLANS];
@@ -198,6 +201,9 @@ static const struct ar8xxx_mib_desc ar8236_mibs[] = {
        MIB_DESC(1, AR8236_STATS_TXLATECOL, "TxLateCol"),
 };
 
+static DEFINE_MUTEX(ar8xxx_dev_list_lock);
+static LIST_HEAD(ar8xxx_dev_list);
+
 static inline struct ar8216_priv *
 swdev_to_ar8216(struct switch_dev *swdev)
 {
@@ -1848,39 +1854,14 @@ ar8216_config_init(struct phy_device *phydev)
        struct switch_dev *swdev;
        int ret;
 
-       if (!priv) {
-               priv = ar8xxx_create_mii(phydev->bus);
-               if (priv == NULL)
-                       return -ENOMEM;
-
-               ret = ar8xxx_probe_switch(priv);
-               if (ret)
-                       goto err_free_priv;
-       }
+       if (WARN_ON(!priv))
+               return -ENODEV;
 
        priv->phy = phydev;
 
        if (phydev->addr != 0) {
                if (chip_is_ar8316(priv)) {
-                       /* check if we're attaching to the switch twice */
-                       phydev = phydev->bus->phy_map[0];
-                       if (!phydev) {
-                               ar8xxx_free(priv);
-                               return 0;
-                       }
-
-                       /* switch device has not been initialized, reuse priv */
-                       if (!phydev->priv) {
-                               priv->port4_phy = true;
-                               priv->dev.ports = (AR8216_NUM_PORTS - 1);
-                               phydev->priv = priv;
-                               return 0;
-                       }
-
-                       ar8xxx_free(priv);
-
                        /* switch device has been initialized, reinit */
-                       priv = phydev->priv;
                        priv->dev.ports = (AR8216_NUM_PORTS - 1);
                        priv->initialized = false;
                        priv->port4_phy = true;
@@ -1888,19 +1869,17 @@ ar8216_config_init(struct phy_device *phydev)
                        return 0;
                }
 
-               ar8xxx_free(priv);
                return 0;
        }
 
-       phydev->priv = priv;
-
        swdev = &priv->dev;
-       ret = register_switch(swdev, phydev->attached_dev);
+       swdev->alias = dev_name(&priv->mii_bus->dev);
+       ret = register_switch(swdev, NULL);
        if (ret)
-               goto err_free_priv;
+               goto err;
 
-       pr_info("%s: %s switch driver attached.\n",
-               phydev->attached_dev->name, swdev->name);
+       pr_info("%s: %s switch registered on %s\n",
+               swdev->devname, swdev->name, dev_name(&priv->mii_bus->dev));
 
        priv->init = true;
 
@@ -1928,9 +1907,7 @@ ar8216_config_init(struct phy_device *phydev)
 
 err_unregister_switch:
        unregister_switch(&priv->dev);
-err_free_priv:
-       ar8xxx_free(priv);
-       phydev->priv = NULL;
+err:
        return ret;
 }
 
@@ -2036,16 +2013,22 @@ ar8216_probe(struct phy_device *phydev)
        if (!ar8xxx_is_possible(phydev->bus))
                return -ENODEV;
 
-       priv = ar8xxx_create_mii(phydev->bus);
-       if (priv == NULL)
-               return -ENOMEM;
+       mutex_lock(&ar8xxx_dev_list_lock);
+       list_for_each_entry(priv, &ar8xxx_dev_list, list)
+               if (priv->mii_bus == phydev->bus)
+                       goto found;
 
-       priv->phy = phydev;
+       priv = ar8xxx_create_mii(phydev->bus);
+       if (priv == NULL) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
 
        ret = ar8xxx_probe_switch(priv);
        if (ret)
-               goto out;
+               goto free_priv;
 
+found:
        if (phydev->addr == 0) {
                if (ar8xxx_has_gige(priv)) {
                        phydev->supported = SUPPORTED_1000baseT_Full;
@@ -2061,10 +2044,19 @@ ar8216_probe(struct phy_device *phydev)
                }
        }
 
-       ret = 0;
+       phydev->priv = priv;
+       priv->use_count++;
 
-out:
+       list_add(&priv->list, &ar8xxx_dev_list);
+
+       mutex_unlock(&ar8xxx_dev_list_lock);
+
+       return 0;
+
+free_priv:
        ar8xxx_free(priv);
+unlock:
+       mutex_unlock(&ar8xxx_dev_list_lock);
        return ret;
 }
 
@@ -2087,14 +2079,18 @@ ar8216_remove(struct phy_device *phydev)
 {
        struct ar8216_priv *priv = phydev->priv;
 
-       if (!priv)
+       if (WARN_ON(!priv))
                return;
 
        phydev->priv = NULL;
+       if (--priv->use_count > 0)
+               return;
 
-       if (phydev->addr == 0)
-               unregister_switch(&priv->dev);
+       mutex_lock(&ar8xxx_dev_list_lock);
+       list_del(&priv->list);
+       mutex_unlock(&ar8xxx_dev_list_lock);
 
+       unregister_switch(&priv->dev);
        ar8xxx_mib_stop(priv);
        ar8xxx_free(priv);
 }