static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) { struct phylink_link_state config; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); u32 advertising; int ret; memset(&config, 0, sizeof(config)); ethtool_convert_legacy_u32_to_link_mode(supported, phy->supported); ethtool_convert_legacy_u32_to_link_mode(config.advertising, phy->advertising); config.interface = pl->link_config.interface; /* * This is the new way of dealing with flow control for PHYs, * as described by Timur Tabi in commit 529ed1275263 ("net: phy: * phy drivers should not set SUPPORTED_[Asym_]Pause") except * using our validate call to the MAC, we rely upon the MAC * clearing the bits from both supported and advertising fields. */ if (phylink_test(supported, Pause)) phylink_set(config.advertising, Pause); if (phylink_test(supported, Asym_Pause)) phylink_set(config.advertising, Asym_Pause); ret = phylink_validate(pl, supported, &config); if (ret) return ret; phy->phylink = pl; phy->phy_link_change = phylink_phy_change; netdev_info(pl->netdev, "PHY [%s] driver [%s]\n", dev_name(&phy->mdio.dev), phy->drv->name); mutex_lock(&phy->lock); mutex_lock(&pl->state_mutex); pl->netdev->phydev = phy; pl->phydev = phy; linkmode_copy(pl->supported, supported); linkmode_copy(pl->link_config.advertising, config.advertising); /* Restrict the phy advertisment according to the MAC support. */ ethtool_convert_link_mode_to_legacy_u32(&advertising, config.advertising); phy->advertising = advertising; mutex_unlock(&pl->state_mutex); mutex_unlock(&phy->lock); netdev_dbg(pl->netdev, "phy: setting supported %*pb advertising 0x%08x\n", __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, phy->advertising); phy_start_machine(phy); if (phy->irq > 0) phy_start_interrupts(phy); return 0; }
/* phy_connect: * * description: Convenience function for connecting ethernet * devices to PHY devices. The default behavior is for * the PHY infrastructure to handle everything, and only notify * the connected driver when the link status changes. If you * don't want, or can't use the provided functionality, you may * choose to call only the subset of functions which provide * the desired functionality. */ struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, void (*handler)(struct net_device *), u32 flags) { struct phy_device *phydev; phydev = phy_attach(dev, phy_id, flags); if (IS_ERR(phydev)) return phydev; phy_prepare_link(phydev, handler); phy_start_machine(phydev, NULL); if (phydev->irq > 0) phy_start_interrupts(phydev); return phydev; }
static int yatse_open(struct net_device *ndev){ struct yatse_private *priv = netdev_priv(ndev); int ret; unsigned long flags; printk(KERN_INFO "yatse: opening\n"); priv->link = 0; #if 0 ret = dma_set_mask(&ndev->dev, 0xffffffffULL); /* 32-bit DMA addresses */ if(ret) goto out; #endif spin_lock_irqsave(&priv->dma.rx_lock, flags); spin_lock(&priv->dma.tx_lock); ret = yatse_dma_init(ndev); spin_unlock(&priv->dma.tx_lock); spin_unlock_irqrestore(&priv->dma.rx_lock, flags); if(ret) goto out; tasklet_init(&priv->tx_tasklet, yatse_tx_complete, (unsigned long)ndev); ret = yatse_init_phy(ndev); if(ret) goto out; ret = yatse_init_mac(ndev); if(ret) goto out; napi_enable(&priv->napi); phy_start(priv->phydev); if(priv->phy_irq != PHY_POLL) phy_start_interrupts(priv->phydev); netif_start_queue(ndev); printk(KERN_INFO "yatse: open done, interface up\n"); out: return ret; }