linux/drivers/net/ethernet/ti/davinci_emac.c
/**
 * emac_dev_open - EMAC device open
 * @ndev: The DaVinci EMAC network adapter
 *
 * Called when system wants to start the interface. We init TX/RX channels
 * and enable the hardware for packet reception/transmission and start the
 * network queue.
 *
 * Returns 0 for a successful open, or appropriate error code
 */
EMAC device open
@ndev: The DaVinci EMAC network adapter

Called when system wants to start the interface. We init TX/RX channels
and enable the hardware for packet reception/transmission and start the
network queue.

Returns 0 for a successful open, or appropriate error code
EMAC device open @ndev : The DaVinci EMAC network adapter Called when system wants to start the interface . We init TX / RX channels and enable the hardware for packet reception / transmission and start the network queue . Returns 0 for a successful open or appropriate error code
static int emac_dev_open(struct net_device *ndev)
{
	struct device *emac_dev = &ndev->dev;
	u32 cnt;
	struct resource *res;
	int q, m, ret;
	int res_num = 0, irq_num = 0;
	int i = 0;
	struct emac_priv *priv = netdev_priv(ndev);
	struct phy_device *phydev = NULL;
	struct device *phy = NULL;
	ret = pm_runtime_get_sync(&priv->pdev->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(&priv->pdev->dev);
		dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
			__func__, ret);
		return ret;
	}
	netif_carrier_off(ndev);
	for (cnt = 0; cnt < ETH_ALEN; cnt++)
		ndev->dev_addr[cnt] = priv->mac_addr[cnt];
	priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
	priv->mac_hash1 = 0;
	priv->mac_hash2 = 0;
	emac_write(EMAC_MACHASH1, 0);
	emac_write(EMAC_MACHASH2, 0);
	for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) {
		struct sk_buff *skb = emac_rx_alloc(priv);
		if (!skb)
			break;
		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
					skb_tailroom(skb), 0);
		if (WARN_ON(ret < 0))
			break;
	}
	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ,
					    res_num))) {
		for (irq_num = res->start; irq_num <= res->end; irq_num++) {
			if (request_irq(irq_num, emac_irq, 0, ndev->name,
					ndev)) {
				dev_err(emac_dev,
					"DaVinci EMAC: request_irq() failed\n");
				ret = -EBUSY;
				goto rollback;
			}
		}
		res_num++;
	}
	res_num--;
	irq_num--;
	emac_hw_enable(priv);
	if (priv->coal_intvl != 0) {
		struct ethtool_coalesce coal;
		coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
		emac_set_coalesce(ndev, &coal);
	}
	cpdma_ctlr_start(priv->dma);
	if (priv->phy_node) {
		phydev = of_phy_connect(ndev, priv->phy_node,
					&emac_adjust_link, 0, 0);
		if (!phydev) {
			dev_err(emac_dev, "could not connect to phy %pOF\n",
				priv->phy_node);
			ret = -ENODEV;
			goto err;
		}
	}
	if (!phydev && !priv->phy_id) {
		phy = bus_find_device(&mdio_bus_type, NULL, NULL,
				      match_first_device);
		if (phy) {
			priv->phy_id = dev_name(phy);
			if (!priv->phy_id || !*priv->phy_id)
				put_device(phy);
		}
	}
	if (!phydev && priv->phy_id && *priv->phy_id) {
		phydev = phy_connect(ndev, priv->phy_id,
				     &emac_adjust_link,
				     PHY_INTERFACE_MODE_MII);
		put_device(phy);	
		if (IS_ERR(phydev)) {
			dev_err(emac_dev, "could not connect to phy %s\n",
				priv->phy_id);
			ret = PTR_ERR(phydev);
			goto err;
		}
		priv->link = 0;
		priv->speed = 0;
		priv->duplex = ~0;
		phy_attached_info(phydev);
	}
	if (!phydev) {
		dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
		priv->link = 1;
		priv->speed = SPEED_100;
		priv->duplex = DUPLEX_FULL;
		emac_update_phystatus(priv);
	}
	if (netif_msg_drv(priv))
		dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
	if (phydev)
		phy_start(phydev);
	return 0;
err:
	emac_int_disable(priv);
	napi_disable(&priv->napi);
rollback:
	for (q = res_num; q >= 0; q--) {
		res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, q);
		if (q != res_num)
			irq_num = res->end;
		for (m = irq_num; m >= res->start; m--)
			free_irq(m, ndev);
	}
	cpdma_ctlr_stop(priv->dma);
	pm_runtime_put(&priv->pdev->dev);
	return ret;
}
static int emac_dev_open ( struct net_device * ndev ) { struct device * emac_dev = & ndev -> dev ; u32 cnt ; struct resource * res ; int q , m , ret ; int res_num = 0 , irq_num = 0 ; int i = 0 ; struct emac_priv * priv = netdev_priv ( ndev ) ; struct phy_device * phydev = NULL ; struct device * phy = NULL ; ret = pm_runtime_get_sync ( & priv -> pdev -> dev ) ; if ( ret < 0 ) { pm_runtime_put_noidle ( & priv -> pdev -> dev ) ; dev_err ( & priv -> pdev -> dev , " \n " , __func__ , ret ) ; return ret ; } netif_carrier_off ( ndev ) ; for ( cnt = 0 ; cnt < ETH_ALEN ; cnt ++ ) ndev -> dev_addr [ cnt ] = priv -> mac_addr [ cnt ] ; priv -> rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN ; priv -> mac_hash1 = 0 ; priv -> mac_hash2 = 0 ; emac_write ( EMAC_MACHASH1 , 0 ) ; emac_write ( EMAC_MACHASH2 , 0 ) ; for ( i = 0 ; i < EMAC_DEF_RX_NUM_DESC ; i ++ ) { struct sk_buff * skb = emac_rx_alloc ( priv ) ; if ( ! skb ) break ; ret = cpdma_chan_submit ( priv -> rxchan , skb , skb -> data , skb_tailroom ( skb ) , 0 ) ; if ( WARN_ON ( ret < 0 ) ) break ; } while ( ( res = platform_get_resource ( priv -> pdev , IORESOURCE_IRQ , res_num ) ) ) { for ( irq_num = res -> start ; irq_num <= res -> end ; irq_num ++ ) { if ( request_irq ( irq_num , emac_irq , 0 , ndev -> name , ndev ) ) { dev_err ( emac_dev , " \n " ) ; ret = - EBUSY ; goto rollback ; } } res_num ++ ; } res_num -- ; irq_num -- ; emac_hw_enable ( priv ) ; if ( priv -> coal_intvl != 0 ) { struct ethtool_coalesce coal ; coal . rx_coalesce_usecs = ( priv -> coal_intvl << 4 ) ; emac_set_coalesce ( ndev , & coal ) ; } cpdma_ctlr_start ( priv -> dma ) ; if ( priv -> phy_node ) { phydev = of_phy_connect ( ndev , priv -> phy_node , & emac_adjust_link , 0 , 0 ) ; if ( ! phydev ) { dev_err ( emac_dev , " \n " , priv -> phy_node ) ; ret = - ENODEV ; goto err ; } } if ( ! phydev && ! priv -> phy_id ) { phy = bus_find_device ( & mdio_bus_type , NULL , NULL , match_first_device ) ; if ( phy ) { priv -> phy_id = dev_name ( phy ) ; if ( ! priv -> phy_id || ! * priv -> phy_id ) put_device ( phy ) ; } } if ( ! phydev && priv -> phy_id && * priv -> phy_id ) { phydev = phy_connect ( ndev , priv -> phy_id , & emac_adjust_link , PHY_INTERFACE_MODE_MII ) ; put_device ( phy ) ; if ( IS_ERR ( phydev ) ) { dev_err ( emac_dev , " \n " , priv -> phy_id ) ; ret = PTR_ERR ( phydev ) ; goto err ; } priv -> link = 0 ; priv -> speed = 0 ; priv -> duplex = ~ 0 ; phy_attached_info ( phydev ) ; } if ( ! phydev ) { dev_notice ( emac_dev , " \n " ) ; priv -> link = 1 ; priv -> speed = SPEED_100 ; priv -> duplex = DUPLEX_FULL ; emac_update_phystatus ( priv ) ; } if ( netif_msg_drv ( priv ) ) dev_notice ( emac_dev , " \n " , ndev -> name ) ; if ( phydev ) phy_start ( phydev ) ; return 0 ; err : emac_int_disable ( priv ) ; napi_disable ( & priv -> napi ) ; rollback : for ( q = res_num ; q >= 0 ; q -- ) { res = platform_get_resource ( priv -> pdev , IORESOURCE_IRQ , q ) ; if ( q != res_num ) irq_num = res -> end ; for ( m = irq_num ; m >= res -> start ; m -- ) free_irq ( m , ndev ) ; } cpdma_ctlr_stop ( priv -> dma ) ; pm_runtime_put ( & priv -> pdev -> dev ) ; return ret ; }
emac_dev_open - EMAC device open
 @ndev: The DaVinci EMAC network adapter
emac_dev_open - EMAC device open @ndev : The DaVinci EMAC network adapter
/* Configuration items */ /* Request IRQ */ /* prepare counters for rollback in case of an error */ /* Start/Enable EMAC hardware */ /* Enable Interrupt pacing if configured */ /* use the first phy on the bus if pdata did not give us a phy id */ /* NOTE: we can't use bus_find_device_by_name() here because
		 * the device name is not guaranteed to be 'davinci_mdio'. On
		 * some systems it can be 'davinci_mdio.0' so we need to use
		 * strncmp() against the first part of the string to correctly
		 * match it.
		 */ /* reference taken by bus_find_device */ /* No PHY , fix the link, speed and duplex settings */ /* at the first iteration, irq_num is already set to the
		 * right value
		 */