static void ag71xx_phy_link_adjust(struct net_device *dev) { struct ag71xx *ag = netdev_priv(dev); struct phy_device *phydev = ag->phy_dev; unsigned long flags; int status_change = 0; spin_lock_irqsave(&ag->lock, flags); if (phydev->link) { if (ag->duplex != phydev->duplex || ag->speed != phydev->speed) { status_change = 1; } } if (phydev->link != ag->link) status_change = 1; ag->link = phydev->link; ag->duplex = phydev->duplex; ag->speed = phydev->speed; if (status_change) ag71xx_link_adjust(ag); spin_unlock_irqrestore(&ag->lock, flags); }
void ag71xx_phy_start(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); if (ag->phy_dev) { phy_start(ag->phy_dev); } else if (pdata->mii_bus_dev && pdata->switch_data) { ag71xx_ar7240_start(ag); } else { ag->link = 1; ag71xx_link_adjust(ag); } }
void ag71xx_phy_stop(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); unsigned long flags; if (ag->phy_dev) phy_stop(ag->phy_dev); else if (pdata->mii_bus_dev && pdata->switch_data) ag71xx_ar7240_stop(ag); spin_lock_irqsave(&ag->lock, flags); if (ag->link) { ag->link = 0; ag71xx_link_adjust(ag); } spin_unlock_irqrestore(&ag->lock, flags); }
static void link_function(struct work_struct *work) { struct ag71xx *ag = container_of(work, struct ag71xx, link_work.work); struct ar7240sw *as = ag->phy_priv; unsigned long flags; u8 mask; int i; int status = 0, link_up_count = 0; mask = ~as->swdata->phy_poll_mask; for (i = 0; i < AR7240_NUM_PHYS; i++) { int link; if (!(mask & BIT(i))) continue; link = ar7240sw_phy_read(ag->mii_bus, i, MII_BMSR); if (link & BMSR_LSTATUS) { status = 1; link_up_count++; } } if (link_up_count != 0 && as->num_ports_linkup != link_up_count) { /* Set flowcontrol threshold based on linkup count */ if (link_up_count == 1) ar7240sw_reg_write(as->mii_bus, 0x34, 0x16602090); else if (link_up_count == 2) ar7240sw_reg_write(as->mii_bus, 0x34, 0x90bcc0ff); else if (link_up_count > 2) ar7240sw_reg_write(as->mii_bus, 0x34, 0xb0c0c0ff); as->num_ports_linkup = link_up_count; } spin_lock_irqsave(&ag->lock, flags); if (status != ag->link) { ag->link = status; ag71xx_link_adjust(ag); } spin_unlock_irqrestore(&ag->lock, flags); schedule_delayed_work(&ag->link_work, HZ / 2); }