summaryrefslogtreecommitdiffstats
path: root/target/linux/generic/files/drivers
diff options
context:
space:
mode:
authorjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-02-11 16:11:30 +0000
committerjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-02-11 16:11:30 +0000
commit39c34fd7b3bd275cff53e1ea536af940d00fe940 (patch)
treee6b60000e8e0ddd4e7d7b00557efd67b78dc817f /target/linux/generic/files/drivers
parentddf1e04eecbd30dc2ae54207342c8b94ec7d091f (diff)
generic: ar8216: reuse the private data from ar8216_probe
The private data of the switch is already allocated in ar8216_priv, assign that to each PHY on the same MDIO bus. Also remove the redundant code from ar8216_config_init. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35559 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic/files/drivers')
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c
index 7fbc53124..baf752bf1 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -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,15 +1854,8 @@ 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;
@@ -1864,23 +1863,17 @@ ar8216_config_init(struct phy_device *phydev)
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);
+ if (!phydev)
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,16 +1881,13 @@ 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);
if (ret)
- goto err_free_priv;
+ goto err;
pr_info("%s: %s switch driver attached.\n",
phydev->attached_dev->name, swdev->name);
@@ -1928,9 +1918,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 +2024,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 +2055,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 +2090,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);
}