Esempio n. 1
0
/*
 * Finds and reports the PHY address
 */
void phy_detect(
	struct net_device *dev,
	int				   id)
{
    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);

    DBG(2, KERN_INFO "phy_detect() %s: Entered\n", priv->netdev->name);

    priv->phy_type = PHY_TYPE_NONE;
	if (id != -1) {
		u32 phy_type;
		if (find_phy(priv->netdev, id, &phy_type)) {
			priv->mii.phy_id = id;
			priv->phy_type = phy_type;
		}
	} else {
		int phyaddr;
		// Scan all 31 PHY addresses if a PHY id wasn't specified
		for (phyaddr = 1; phyaddr < 32; ++phyaddr) {
			u32 phy_type;
			if (find_phy(priv->netdev, phyaddr, &phy_type)) {
				priv->mii.phy_id = phyaddr;
				priv->phy_type = phy_type;
				break;
			}
		}
	}
}
static int __devinit fs_enet_probe(struct of_device *ofdev,
                                   const struct of_device_id *match)
{
	struct net_device *ndev;
	struct fs_enet_private *fep;
	struct fs_platform_info *fpi;
	const u32 *data;
	const u8 *mac_addr;
	int privsize, len, ret = -ENODEV;

	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
	if (!fpi)
		return -ENOMEM;

	if (!IS_FEC(match)) {
		data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
		if (!data || len != 4)
			goto out_free_fpi;

		fpi->cp_command = *data;
	}

	fpi->rx_ring = 32;
	fpi->tx_ring = 32;
	fpi->rx_copybreak = 240;
	fpi->use_napi = 1;
	fpi->napi_weight = 17;

	ret = find_phy(ofdev->node, fpi);
	if (ret)
		goto out_free_fpi;

	privsize = sizeof(*fep) +
	           sizeof(struct sk_buff **) *
	           (fpi->rx_ring + fpi->tx_ring);

	ndev = alloc_etherdev(privsize);
	if (!ndev) {
		ret = -ENOMEM;
		goto out_free_fpi;
	}

	dev_set_drvdata(&ofdev->dev, ndev);

	fep = netdev_priv(ndev);
	fep->dev = &ofdev->dev;
	fep->ndev = ndev;
	fep->fpi = fpi;
	fep->ops = match->data;

	ret = fep->ops->setup_data(ndev);
	if (ret)
		goto out_free_dev;

	fep->rx_skbuff = (struct sk_buff **)&fep[1];
	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;

	spin_lock_init(&fep->lock);
	spin_lock_init(&fep->tx_lock);

	mac_addr = of_get_mac_address(ofdev->node);
	if (mac_addr)
		memcpy(ndev->dev_addr, mac_addr, 6);

	ret = fep->ops->allocate_bd(ndev);
	if (ret)
		goto out_cleanup_data;

	fep->rx_bd_base = fep->ring_base;
	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;

	fep->tx_ring = fpi->tx_ring;
	fep->rx_ring = fpi->rx_ring;

	ndev->netdev_ops = &fs_enet_netdev_ops;
	ndev->watchdog_timeo = 2 * HZ;
	if (fpi->use_napi)
		netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
		               fpi->napi_weight);

	ndev->ethtool_ops = &fs_ethtool_ops;

	init_timer(&fep->phy_timer_list);

	netif_carrier_off(ndev);

	ret = register_netdev(ndev);
	if (ret)
		goto out_free_bd;

	printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);

	return 0;

out_free_bd:
	fep->ops->free_bd(ndev);
out_cleanup_data:
	fep->ops->cleanup_data(ndev);
out_free_dev:
	free_netdev(ndev);
	dev_set_drvdata(&ofdev->dev, NULL);
out_free_fpi:
	kfree(fpi);
	return ret;
}