/* set MAC link settings according to information from phylib */ static void ax88172a_adjust_link(struct net_device *netdev) { struct phy_device *phydev = netdev->phydev; struct usbnet *dev = netdev_priv(netdev); struct ax88172a_private *priv = dev->driver_priv; u16 mode = 0; if (phydev->link) { mode = AX88772_MEDIUM_DEFAULT; if (phydev->duplex == DUPLEX_HALF) mode &= ~AX_MEDIUM_FD; if (phydev->speed != SPEED_100) mode &= ~AX_MEDIUM_PS; } if (mode != priv->oldmode) { asix_write_medium_mode(dev, mode, 0); priv->oldmode = mode; netdev_dbg(netdev, "speed %u duplex %d, setting mode to 0x%04x\n", phydev->speed, phydev->duplex, mode); phy_print_status(phydev); } }
static void dsa_slave_adjust_link(struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; unsigned int status_changed = 0; if (p->old_link != p->phy->link) { status_changed = 1; p->old_link = p->phy->link; } if (p->old_duplex != p->phy->duplex) { status_changed = 1; p->old_duplex = p->phy->duplex; } if (p->old_pause != p->phy->pause) { status_changed = 1; p->old_pause = p->phy->pause; } if (ds->drv->adjust_link && status_changed) ds->drv->adjust_link(ds, p->port, p->phy); if (status_changed) phy_print_status(p->phy); }
/*----------------------------------------------------------------------------- * generic link-change handler - should be sufficient for most cases *-----------------------------------------------------------------------------*/ static void generic_adjust_link(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); struct phy_device *phydev = fep->phydev; int new_state = 0; if (phydev->link) { /* adjust to duplex mode */ if (phydev->duplex != fep->oldduplex) { new_state = 1; fep->oldduplex = phydev->duplex; } if (phydev->speed != fep->oldspeed) { new_state = 1; fep->oldspeed = phydev->speed; } if (!fep->oldlink) { new_state = 1; fep->oldlink = 1; } if (new_state) fep->ops->restart(dev); } else if (fep->oldlink) { new_state = 1; fep->oldlink = 0; fep->oldspeed = 0; fep->oldduplex = -1; } if (new_state && netif_msg_link(fep)) phy_print_status(phydev); }
/** * arc_emac_adjust_link - Adjust the PHY link duplex. * @ndev: Pointer to the net_device structure. * * This function is called to change the duplex setting after auto negotiation * is done by the PHY. */ static void arc_emac_adjust_link(struct net_device *ndev) { struct arc_emac_priv *priv = netdev_priv(ndev); struct phy_device *phy_dev = ndev->phydev; unsigned int reg, state_changed = 0; if (priv->link != phy_dev->link) { priv->link = phy_dev->link; state_changed = 1; } if (priv->speed != phy_dev->speed) { priv->speed = phy_dev->speed; state_changed = 1; if (priv->set_mac_speed) priv->set_mac_speed(priv, priv->speed); } if (priv->duplex != phy_dev->duplex) { reg = arc_reg_get(priv, R_CTRL); if (phy_dev->duplex == DUPLEX_FULL) reg |= ENFL_MASK; else reg &= ~ENFL_MASK; arc_reg_set(priv, R_CTRL, reg); priv->duplex = phy_dev->duplex; state_changed = 1; } if (state_changed) phy_print_status(phy_dev); }
/* PHY state control function */ static void sh_eth_adjust_link(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); struct phy_device *phydev = mdp->phydev; u32 ioaddr = ndev->base_addr; int new_state = 0; if (phydev->link != PHY_DOWN) { if (phydev->duplex != mdp->duplex) { new_state = 1; mdp->duplex = phydev->duplex; #if defined(CONFIG_CPU_SUBTYPE_SH7763) if (mdp->duplex) { /* FULL */ ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); } else { /* Half */ ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); } #endif } if (phydev->speed != mdp->speed) { new_state = 1; mdp->speed = phydev->speed; #if defined(CONFIG_CPU_SUBTYPE_SH7763) switch (mdp->speed) { case 10: /* 10BASE */ ctrl_outl(GECMR_10, ioaddr + GECMR); break; case 100:/* 100BASE */ ctrl_outl(GECMR_100, ioaddr + GECMR); break; case 1000: /* 1000BASE */ ctrl_outl(GECMR_1000, ioaddr + GECMR); break; default: break; } #endif } if (mdp->link == PHY_DOWN) { ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF) | ECMR_DM, ioaddr + ECMR); new_state = 1; mdp->link = phydev->link; } } else if (mdp->link) { new_state = 1; mdp->link = PHY_DOWN; mdp->speed = 0; mdp->duplex = -1; } if (new_state) phy_print_status(phydev); }
static void hip04_adjust_link(struct net_device *ndev) { struct hip04_priv *priv = netdev_priv(ndev); struct phy_device *phy = priv->phy; if ((priv->speed != phy->speed) || (priv->duplex != phy->duplex)) { hip04_config_port(ndev, phy->speed, phy->duplex); phy_print_status(phy); } }
static void s6gmac_adjust_link(struct net_device *dev) { struct s6gmac *pd = netdev_priv(dev); struct phy_device *phydev = pd->phydev; if (pd->link.isup && (!phydev->link || (pd->link.mbit != phydev->speed) || (pd->link.full != phydev->duplex))) { pd->link.isup = 0; netif_tx_disable(dev); if (!phydev->link) { netif_carrier_off(dev); phy_print_status(phydev); } } if (!pd->link.isup && phydev->link) { if (pd->link.full != phydev->duplex) { u32 maccfg = readl(pd->reg + S6_GMAC_MACCONF2); if (phydev->duplex) maccfg |= 1 << S6_GMAC_MACCONF2_FULL; else maccfg &= ~(1 << S6_GMAC_MACCONF2_FULL); writel(maccfg, pd->reg + S6_GMAC_MACCONF2); } if (pd->link.giga != (phydev->speed == 1000)) { u32 fifocfg = readl(pd->reg + S6_GMAC_FIFOCONF5); u32 maccfg = readl(pd->reg + S6_GMAC_MACCONF2); maccfg &= ~(S6_GMAC_MACCONF2_IFMODE_MASK << S6_GMAC_MACCONF2_IFMODE); if (phydev->speed == 1000) { fifocfg |= 1 << S6_GMAC_FIFOCONF5_CFGBYTM; maccfg |= S6_GMAC_MACCONF2_IFMODE_BYTE << S6_GMAC_MACCONF2_IFMODE; } else { fifocfg &= ~(1 << S6_GMAC_FIFOCONF5_CFGBYTM); maccfg |= S6_GMAC_MACCONF2_IFMODE_NIBBLE << S6_GMAC_MACCONF2_IFMODE; } writel(fifocfg, pd->reg + S6_GMAC_FIFOCONF5); writel(maccfg, pd->reg + S6_GMAC_MACCONF2); } if (!s6dmac_fifo_full(pd->tx_dma, pd->tx_chan)) netif_wake_queue(dev); s6gmac_linkisup(dev, 1); } }
static inline void s6gmac_linkisup(struct net_device *dev, int isup) { struct s6gmac *pd = netdev_priv(dev); struct phy_device *phydev = pd->phydev; pd->link.full = phydev->duplex; pd->link.giga = (phydev->speed == 1000); if (pd->link.mbit != phydev->speed) { pd->link.mbit = phydev->speed; s6gmac_set_rgmii_txclock(pd); } pd->link.isup = isup; if (isup) netif_carrier_on(dev); phy_print_status(phydev); }
static void hisi_femac_adjust_link(struct net_device *dev) { struct hisi_femac_priv *priv = netdev_priv(dev); struct phy_device *phy = dev->phydev; u32 status = 0; if (phy->link) status |= MAC_PORTSET_LINKED; if (phy->duplex == DUPLEX_FULL) status |= MAC_PORTSET_DUPLEX_FULL; if (phy->speed == SPEED_100) status |= MAC_PORTSET_SPEED_100M; if ((status != priv->link_status) && ((status | priv->link_status) & MAC_PORTSET_LINKED)) { writel(status, priv->port_base + MAC_PORTSET); priv->link_status = status; phy_print_status(phy); } }
static void hieth_adjust_link(struct net_device *dev) { int stat = 0; struct hieth_netdev_local *ld = netdev_priv(dev); stat |= (ld->phy->link) ? HIETH_LINKED : 0; stat |= (ld->phy->duplex == DUPLEX_FULL) ? HIETH_DUP_FULL : 0; stat |= (ld->phy->speed == SPEED_100) ? HIETH_SPD_100M : 0; if (stat != ld->link_stat) { if (ld->phy->link == 0) { printk(KERN_INFO "***link down status changed***.\n"); writel(0x0, ld->iobase + 0x490); writel(0x0, ld->iobase + 0x484); } else { writel(0x1, ld->iobase + 0x490); hanbang_asshole(); #ifdef CONFIG_EEE_SUPPORT if (eee_available > NO_EEE) { int data = ld->driver->eee_enable(); if (DEBUG) printk(KERN_INFO "adjust_link " "data:(=2?): %d\n", data); if (eee_available == MAC_EEE) { writel(0x10, ld->iobase + 0x484); /* enable intr */ writel(0x1f, ld->iobase + 0x480); } else writel(0x0, ld->iobase + 0x484); } #endif } hieth_set_linkstat(ld, stat); phy_print_status(ld->phy); ld->link_stat = stat; } }
static void emac_handle_link_change(struct net_device *dev) { struct emac_board_info *db = netdev_priv(dev); struct phy_device *phydev = dev->phydev; unsigned long flags; int status_change = 0; if (phydev->link) { if (db->speed != phydev->speed) { spin_lock_irqsave(&db->lock, flags); db->speed = phydev->speed; emac_update_speed(dev); spin_unlock_irqrestore(&db->lock, flags); status_change = 1; } if (db->duplex != phydev->duplex) { spin_lock_irqsave(&db->lock, flags); db->duplex = phydev->duplex; emac_update_duplex(dev); spin_unlock_irqrestore(&db->lock, flags); status_change = 1; } } if (phydev->link != db->link) { if (!phydev->link) { db->speed = 0; db->duplex = -1; } db->link = phydev->link; status_change = 1; } if (status_change) phy_print_status(phydev); }
static void _cpsw_adjust_link(struct cpsw_slave *slave, struct cpsw_priv *priv, bool *link) { struct phy_device *phy = slave->phy; u32 mac_control = 0; u32 slave_port; if (!phy) return; slave_port = cpsw_get_slave_port(priv, slave->slave_num); if (phy->link) { mac_control = priv->data.mac_control; /* */ cpsw_ale_control_set(priv->ale, slave_port, ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); if (phy->speed == 1000) mac_control |= BIT(7); /* */ if (phy->duplex) mac_control |= BIT(0); /* */ *link = true; } else { mac_control = 0; /* */ cpsw_ale_control_set(priv->ale, slave_port, ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); } if (mac_control != slave->mac_control) { phy_print_status(phy); __raw_writel(mac_control, &slave->sliver->mac_control); } slave->mac_control = mac_control; }
static void bgmac_adjust_link(struct net_device *net_dev) { struct bgmac *bgmac = netdev_priv(net_dev); struct phy_device *phy_dev = bgmac->phy_dev; bool update = false; if (phy_dev->link) { if (phy_dev->speed != bgmac->mac_speed) { bgmac->mac_speed = phy_dev->speed; update = true; } if (phy_dev->duplex != bgmac->mac_duplex) { bgmac->mac_duplex = phy_dev->duplex; update = true; } } if (update) { bgmac_mac_speed(bgmac); phy_print_status(phy_dev); } }
/* PHY state control function */ static void sh_eth_adjust_link(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); struct phy_device *phydev = mdp->phydev; u32 ioaddr = ndev->base_addr; int new_state = 0; if (phydev->link != PHY_DOWN) { if (phydev->duplex != mdp->duplex) { new_state = 1; mdp->duplex = phydev->duplex; if (mdp->cd->set_duplex) mdp->cd->set_duplex(ndev); } if (phydev->speed != mdp->speed) { new_state = 1; mdp->speed = phydev->speed; if (mdp->cd->set_rate) mdp->cd->set_rate(ndev); } if (mdp->link == PHY_DOWN) { writel((readl(ioaddr + ECMR) & ~ECMR_TXF) | ECMR_DM, ioaddr + ECMR); new_state = 1; mdp->link = phydev->link; } } else if (mdp->link) { new_state = 1; mdp->link = PHY_DOWN; mdp->speed = 0; mdp->duplex = -1; } if (new_state) phy_print_status(phydev); }
/* PHY state control function */ static void sh_eth_adjust_link(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); struct phy_device *phydev = mdp->phydev; int new_state = 0; if (phydev->link != PHY_DOWN) { if (phydev->duplex != mdp->duplex) { new_state = 1; mdp->duplex = phydev->duplex; if (mdp->cd->set_duplex) mdp->cd->set_duplex(ndev); } if (phydev->speed != mdp->speed) { new_state = 1; mdp->speed = phydev->speed; if (mdp->cd->set_rate) mdp->cd->set_rate(ndev); } if (mdp->link == PHY_DOWN) { sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR); new_state = 1; mdp->link = phydev->link; } } else if (mdp->link) { new_state = 1; mdp->link = PHY_DOWN; mdp->speed = 0; mdp->duplex = -1; } if (new_state && netif_msg_link(mdp)) phy_print_status(phydev); }
/* setup netdev link state when PHY link status change and * update UMAC and RGMII block when link up */ void bcmgenet_mii_setup(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); struct phy_device *phydev = priv->phydev; u32 reg, cmd_bits = 0; bool status_changed = false; if (priv->old_link != phydev->link) { status_changed = true; priv->old_link = phydev->link; } if (phydev->link) { /* check speed/duplex/pause changes */ if (priv->old_speed != phydev->speed) { status_changed = true; priv->old_speed = phydev->speed; } if (priv->old_duplex != phydev->duplex) { status_changed = true; priv->old_duplex = phydev->duplex; } if (priv->old_pause != phydev->pause) { status_changed = true; priv->old_pause = phydev->pause; } /* done if nothing has changed */ if (!status_changed) return; /* speed */ if (phydev->speed == SPEED_1000) cmd_bits = UMAC_SPEED_1000; else if (phydev->speed == SPEED_100) cmd_bits = UMAC_SPEED_100; else cmd_bits = UMAC_SPEED_10; cmd_bits <<= CMD_SPEED_SHIFT; /* duplex */ if (phydev->duplex != DUPLEX_FULL) cmd_bits |= CMD_HD_EN; /* pause capability */ if (!phydev->pause) cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE; /* * Program UMAC and RGMII block based on established * link speed, duplex, and pause. The speed set in * umac->cmd tell RGMII block which clock to use for * transmit -- 25MHz(100Mbps) or 125MHz(1Gbps). * Receive clock is provided by the PHY. */ reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); reg &= ~OOB_DISABLE; reg |= RGMII_LINK; bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); reg = bcmgenet_umac_readl(priv, UMAC_CMD); reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) | CMD_HD_EN | CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE); reg |= cmd_bits; bcmgenet_umac_writel(priv, reg, UMAC_CMD); } else { /* done if nothing has changed */ if (!status_changed) return; /* needed for MoCA fixed PHY to reflect correct link status */ netif_carrier_off(dev); } phy_print_status(phydev); }
/* setup netdev link state when PHY link status change and * update UMAC and RGMII block when link up */ static void bcmgenet_mii_setup(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); struct phy_device *phydev = priv->phydev; u32 reg, cmd_bits = 0; unsigned int status_changed = 0; if (priv->old_link != phydev->link) { status_changed = 1; priv->old_link = phydev->link; } if (phydev->link) { /* program UMAC and RGMII block based on established link * speed, pause, and duplex. * the speed set in umac->cmd tell RGMII block which clock * 25MHz(100Mbps)/125MHz(1Gbps) to use for transmit. * receive clock is provided by PHY. */ reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); reg &= ~OOB_DISABLE; reg |= RGMII_LINK; bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); /* speed */ if (phydev->speed == SPEED_1000) cmd_bits = UMAC_SPEED_1000; else if (phydev->speed == SPEED_100) cmd_bits = UMAC_SPEED_100; else cmd_bits = UMAC_SPEED_10; cmd_bits <<= CMD_SPEED_SHIFT; if (priv->old_duplex != phydev->duplex) { status_changed = 1; priv->old_duplex = phydev->duplex; } /* duplex */ if (phydev->duplex != DUPLEX_FULL) cmd_bits |= CMD_HD_EN; if (priv->old_pause != phydev->pause) { status_changed = 1; priv->old_pause = phydev->pause; } /* pause capability */ if (!phydev->pause) cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE; } if (status_changed) { reg = bcmgenet_umac_readl(priv, UMAC_CMD); reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) | CMD_HD_EN | CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE); reg |= cmd_bits; bcmgenet_umac_writel(priv, reg, UMAC_CMD); phy_print_status(phydev); } }
static void bfin_mac_adjust_link(struct net_device *dev) { struct bfin_mac_local *lp = netdev_priv(dev); struct phy_device *phydev = lp->phydev; unsigned long flags; int new_state = 0; spin_lock_irqsave(&lp->lock, flags); if (phydev->link) { /* Now we make sure that we can be in full duplex mode. * If not, we operate in half-duplex mode. */ if (phydev->duplex != lp->old_duplex) { u32 opmode = bfin_read_EMAC_OPMODE(); new_state = 1; if (phydev->duplex) opmode |= FDMODE; else opmode &= ~(FDMODE); bfin_write_EMAC_OPMODE(opmode); lp->old_duplex = phydev->duplex; } if (phydev->speed != lp->old_speed) { #if defined(CONFIG_BFIN_MAC_RMII) u32 opmode = bfin_read_EMAC_OPMODE(); switch (phydev->speed) { case 10: opmode |= RMII_10; break; case 100: opmode &= ~(RMII_10); break; default: printk(KERN_WARNING "%s: Ack! Speed (%d) is not 10/100!\n", DRV_NAME, phydev->speed); break; } bfin_write_EMAC_OPMODE(opmode); #endif new_state = 1; lp->old_speed = phydev->speed; } if (!lp->old_link) { new_state = 1; lp->old_link = 1; } } else if (lp->old_link) { new_state = 1; lp->old_link = 0; lp->old_speed = 0; lp->old_duplex = -1; } if (new_state) { u32 opmode = bfin_read_EMAC_OPMODE(); phy_print_status(phydev); pr_debug("EMAC_OPMODE = 0x%08x\n", opmode); } spin_unlock_irqrestore(&lp->lock, flags); }
static void bfin_mac_adjust_link(struct net_device *dev) { struct bfin_mac_local *lp = netdev_priv(dev); struct phy_device *phydev = lp->phydev; unsigned long flags; int new_state = 0; spin_lock_irqsave(&lp->lock, flags); if (phydev->link) { if (phydev->duplex != lp->old_duplex) { u32 opmode = bfin_read_EMAC_OPMODE(); new_state = 1; if (phydev->duplex) opmode |= FDMODE; else opmode &= ~(FDMODE); bfin_write_EMAC_OPMODE(opmode); lp->old_duplex = phydev->duplex; } if (phydev->speed != lp->old_speed) { if (phydev->interface == PHY_INTERFACE_MODE_RMII) { u32 opmode = bfin_read_EMAC_OPMODE(); switch (phydev->speed) { case 10: opmode |= RMII_10; break; case 100: opmode &= ~RMII_10; break; default: netdev_warn(dev, "Ack! Speed (%d) is not 10/100!\n", phydev->speed); break; } bfin_write_EMAC_OPMODE(opmode); } new_state = 1; lp->old_speed = phydev->speed; } if (!lp->old_link) { new_state = 1; lp->old_link = 1; } } else if (lp->old_link) { new_state = 1; lp->old_link = 0; lp->old_speed = 0; lp->old_duplex = -1; } if (new_state) { u32 opmode = bfin_read_EMAC_OPMODE(); phy_print_status(phydev); pr_debug("EMAC_OPMODE = 0x%08x\n", opmode); } spin_unlock_irqrestore(&lp->lock, flags); }
static void tc_handle_link_change(struct net_device *dev) { struct tc35815_local *lp = netdev_priv(dev); struct phy_device *phydev = dev->phydev; unsigned long flags; int status_change = 0; spin_lock_irqsave(&lp->lock, flags); if (phydev->link && (lp->speed != phydev->speed || lp->duplex != phydev->duplex)) { struct tc35815_regs __iomem *tr = (struct tc35815_regs __iomem *)dev->base_addr; u32 reg; reg = tc_readl(&tr->MAC_Ctl); reg |= MAC_HaltReq; tc_writel(reg, &tr->MAC_Ctl); if (phydev->duplex == DUPLEX_FULL) reg |= MAC_FullDup; else reg &= ~MAC_FullDup; tc_writel(reg, &tr->MAC_Ctl); reg &= ~MAC_HaltReq; tc_writel(reg, &tr->MAC_Ctl); /* * TX4939 PCFG.SPEEDn bit will be changed on * NETDEV_CHANGE event. */ /* * WORKAROUND: enable LostCrS only if half duplex * operation. * (TX4939 does not have EnLCarr) */ if (phydev->duplex == DUPLEX_HALF && lp->chiptype != TC35815_TX4939) tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr, &tr->Tx_Ctl); lp->speed = phydev->speed; lp->duplex = phydev->duplex; status_change = 1; } if (phydev->link != lp->link) { if (phydev->link) { /* delayed promiscuous enabling */ if (dev->flags & IFF_PROMISC) tc35815_set_multicast_list(dev); } else { lp->speed = 0; lp->duplex = -1; } lp->link = phydev->link; status_change = 1; } spin_unlock_irqrestore(&lp->lock, flags); if (status_change && netif_msg_link(lp)) { phy_print_status(phydev); pr_debug("%s: MII BMCR %04x BMSR %04x LPA %04x\n", dev->name, phy_read(phydev, MII_BMCR), phy_read(phydev, MII_BMSR), phy_read(phydev, MII_LPA)); } }
/** * stmmac_adjust_link * @dev: net device structure * Description: it adjusts the link parameters. */ static void stmmac_adjust_link(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phydev = priv->phydev; unsigned long flags; int new_state = 0; unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; if (phydev == NULL) return; DBG(probe, DEBUG, "stmmac_adjust_link: called. address %d link %d\n", phydev->addr, phydev->link); spin_lock_irqsave(&priv->lock, flags); if (phydev->link) { u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); /* Now we make sure that we can be in full duplex mode. * If not, we operate in half-duplex mode. */ if (phydev->duplex != priv->oldduplex) { new_state = 1; if (!(phydev->duplex)) ctrl &= ~priv->hw->link.duplex; else ctrl |= priv->hw->link.duplex; priv->oldduplex = phydev->duplex; } /* Flow Control operation */ if (phydev->pause) priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex, fc, pause_time); if (phydev->speed != priv->speed) { new_state = 1; switch (phydev->speed) { case 1000: if (likely(priv->plat->has_gmac)) ctrl &= ~priv->hw->link.port; stmmac_hw_fix_mac_speed(priv); break; case 100: case 10: if (priv->plat->has_gmac) { ctrl |= priv->hw->link.port; if (phydev->speed == SPEED_100) { ctrl |= priv->hw->link.speed; } else { ctrl &= ~(priv->hw->link.speed); } } else { ctrl &= ~priv->hw->link.port; } stmmac_hw_fix_mac_speed(priv); break; default: if (netif_msg_link(priv)) pr_warning("%s: Speed (%d) is not 10" " or 100!\n", dev->name, phydev->speed); break; } priv->speed = phydev->speed; } writel(ctrl, priv->ioaddr + MAC_CTRL_REG); if (!priv->oldlink) { new_state = 1; priv->oldlink = 1; } } else if (priv->oldlink) { new_state = 1; priv->oldlink = 0; priv->speed = 0; priv->oldduplex = -1; } if (new_state && netif_msg_link(priv)) phy_print_status(phydev); spin_unlock_irqrestore(&priv->lock, flags); DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n"); }