|
@@ -227,6 +227,9 @@ struct cpsw_priv {
|
|
|
struct cpsw_slave *slaves;
|
|
|
struct phy_device *phydev;
|
|
|
struct mii_dev *bus;
|
|
|
+
|
|
|
+ u32 mdio_link;
|
|
|
+ u32 phy_mask;
|
|
|
};
|
|
|
|
|
|
static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
|
|
@@ -598,10 +601,21 @@ static int cpsw_update_link(struct cpsw_priv *priv)
|
|
|
|
|
|
for_each_slave(slave, priv)
|
|
|
cpsw_slave_update_link(slave, priv, &link);
|
|
|
-
|
|
|
+ priv->mdio_link = readl(&mdio_regs->link);
|
|
|
return link;
|
|
|
}
|
|
|
|
|
|
+static int cpsw_check_link(struct cpsw_priv *priv)
|
|
|
+{
|
|
|
+ u32 link = 0;
|
|
|
+
|
|
|
+ link = __raw_readl(&mdio_regs->link) & priv->phy_mask;
|
|
|
+ if ((link) && (link == priv->mdio_link))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ return cpsw_update_link(priv);
|
|
|
+}
|
|
|
+
|
|
|
static inline u32 cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
|
|
|
{
|
|
|
if (priv->host_port == 0)
|
|
@@ -631,6 +645,8 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
|
|
|
cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);
|
|
|
|
|
|
cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave_port);
|
|
|
+
|
|
|
+ priv->phy_mask |= 1 << slave->data->phy_id;
|
|
|
}
|
|
|
|
|
|
static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
|
|
@@ -862,7 +878,7 @@ static int cpsw_send(struct eth_device *dev, void *packet, int length)
|
|
|
int len;
|
|
|
int timeout = CPDMA_TIMEOUT;
|
|
|
|
|
|
- if (!cpsw_update_link(priv))
|
|
|
+ if (!cpsw_check_link(priv))
|
|
|
return -EIO;
|
|
|
|
|
|
flush_dcache_range((unsigned long)packet,
|