static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
{
	const char *model;
	const void *mac_addr;
	int err = 0, i;
	phy_interface_t interface;
	struct net_device *dev = NULL;
	struct gfar_private *priv = NULL;
	struct device_node *np = ofdev->dev.of_node;
	struct device_node *child = NULL;
	u32 stash_len = 0;
	u32 stash_idx = 0;
	unsigned int num_tx_qs, num_rx_qs;
	unsigned short mode, poll_mode;

	if (!np)
		return -ENODEV;

	if (of_device_is_compatible(np, "fsl,etsec2")) {
		mode = MQ_MG_MODE;
		poll_mode = GFAR_SQ_POLLING;
	} else {
		mode = SQ_SG_MODE;
		poll_mode = GFAR_SQ_POLLING;
	}

	if (mode == SQ_SG_MODE) {
		num_tx_qs = 1;
		num_rx_qs = 1;
	} else { /* MQ_MG_MODE */
		/* get the actual number of supported groups */
		unsigned int num_grps = gfar_of_group_count(np);

		if (num_grps == 0 || num_grps > MAXGROUPS) {
			dev_err(&ofdev->dev, "Invalid # of int groups(%d)\n",
				num_grps);
			pr_err("Cannot do alloc_etherdev, aborting\n");
			return -EINVAL;
		}

		if (poll_mode == GFAR_SQ_POLLING) {
			num_tx_qs = num_grps; /* one txq per int group */
			num_rx_qs = num_grps; /* one rxq per int group */
		} else { /* GFAR_MQ_POLLING */
			u32 tx_queues, rx_queues;
			int ret;

			/* parse the num of HW tx and rx queues */
			ret = of_property_read_u32(np, "fsl,num_tx_queues",
						   &tx_queues);
			num_tx_qs = ret ? 1 : tx_queues;

			ret = of_property_read_u32(np, "fsl,num_rx_queues",
						   &rx_queues);
			num_rx_qs = ret ? 1 : rx_queues;
		}
	}

	if (num_tx_qs > MAX_TX_QS) {
		pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
		       num_tx_qs, MAX_TX_QS);
		pr_err("Cannot do alloc_etherdev, aborting\n");
		return -EINVAL;
	}

	if (num_rx_qs > MAX_RX_QS) {
		pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
		       num_rx_qs, MAX_RX_QS);
		pr_err("Cannot do alloc_etherdev, aborting\n");
		return -EINVAL;
	}

	*pdev = alloc_etherdev_mq(sizeof(*priv), num_tx_qs);
	dev = *pdev;
	if (NULL == dev)
		return -ENOMEM;

	priv = netdev_priv(dev);
	priv->ndev = dev;

	priv->mode = mode;
	priv->poll_mode = poll_mode;

	priv->num_tx_queues = num_tx_qs;
	netif_set_real_num_rx_queues(dev, num_rx_qs);
	priv->num_rx_queues = num_rx_qs;

	err = gfar_alloc_tx_queues(priv);
	if (err)
		goto tx_alloc_failed;

	err = gfar_alloc_rx_queues(priv);
	if (err)
		goto rx_alloc_failed;

	err = of_property_read_string(np, "model", &model);
	if (err) {
		pr_err("Device model property missing, aborting\n");
		goto rx_alloc_failed;
	}

	/* Init Rx queue filer rule set linked list */
	INIT_LIST_HEAD(&priv->rx_list.list);
	priv->rx_list.count = 0;
	mutex_init(&priv->rx_queue_access);

	for (i = 0; i < MAXGROUPS; i++)
		priv->gfargrp[i].regs = NULL;

	/* Parse and initialize group specific information */
	if (priv->mode == MQ_MG_MODE) {
		for_each_available_child_of_node(np, child) {
			if (!of_node_name_eq(child, "queue-group"))
				continue;

			err = gfar_parse_group(child, priv, model);
			if (err) {
				of_node_put(child);
				goto err_grp_init;
			}
		}
	} else { /* SQ_SG_MODE */
		err = gfar_parse_group(np, priv, model);
		if (err)
			goto err_grp_init;
	}

	if (of_property_read_bool(np, "bd-stash")) {
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING;
		priv->bd_stash_en = 1;
	}

	err = of_property_read_u32(np, "rx-stash-len", &stash_len);

	if (err == 0)
		priv->rx_stash_size = stash_len;

	err = of_property_read_u32(np, "rx-stash-idx", &stash_idx);

	if (err == 0)
		priv->rx_stash_index = stash_idx;

	if (stash_len || stash_idx)
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING;

	mac_addr = of_get_mac_address(np);

	if (!IS_ERR(mac_addr)) {
		ether_addr_copy(dev->dev_addr, mac_addr);
	} else {
		eth_hw_addr_random(dev);
		dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr);
	}

	if (model && !strcasecmp(model, "TSEC"))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
				     FSL_GIANFAR_DEV_HAS_COALESCE |
				     FSL_GIANFAR_DEV_HAS_RMON |
				     FSL_GIANFAR_DEV_HAS_MULTI_INTR;

	if (model && !strcasecmp(model, "eTSEC"))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
				     FSL_GIANFAR_DEV_HAS_COALESCE |
				     FSL_GIANFAR_DEV_HAS_RMON |
				     FSL_GIANFAR_DEV_HAS_MULTI_INTR |
				     FSL_GIANFAR_DEV_HAS_CSUM |
				     FSL_GIANFAR_DEV_HAS_VLAN |
				     FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
				     FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
				     FSL_GIANFAR_DEV_HAS_TIMER |
				     FSL_GIANFAR_DEV_HAS_RX_FILER;

	/* Use PHY connection type from the DT node if one is specified there.
	 * rgmii-id really needs to be specified. Other types can be
	 * detected by hardware
	 */
	err = of_get_phy_mode(np, &interface);
	if (!err)
		priv->interface = interface;
	else
		priv->interface = gfar_get_interface(dev);

	if (of_find_property(np, "fsl,magic-packet", NULL))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;

	if (of_get_property(np, "fsl,wake-on-filer", NULL))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER;

	priv->phy_node = of_parse_phandle(np, "phy-handle", 0);

	/* In the case of a fixed PHY, the DT node associated
	 * to the PHY is the Ethernet MAC DT node.
	 */
	if (!priv->phy_node && of_phy_is_fixed_link(np)) {
		err = of_phy_register_fixed_link(np);
		if (err)
			goto err_grp_init;

		priv->phy_node = of_node_get(np);
	}

	/* Find the TBI PHY.  If it's not there, we don't support SGMII */
	priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);

	return 0;

err_grp_init:
	unmap_group_regs(priv);
rx_alloc_failed:
	gfar_free_rx_queues(priv);
tx_alloc_failed:
	gfar_free_tx_queues(priv);
	free_gfar_dev(priv);
	return err;
}
static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
{
	const char *model;
	const void *mac_addr;
	int err = 0, i;
	phy_interface_t interface;
	struct net_device *dev = NULL;
	struct gfar_private *priv = NULL;
	struct device_node *np = ofdev->dev.of_node;
	struct device_node *child = NULL;
	u32 stash_len = 0;
	u32 stash_idx = 0;
	unsigned int num_tx_qs, num_rx_qs;
	unsigned short mode, poll_mode;

	if (!np)
		return -ENODEV;

	if (of_device_is_compatible(np, "fsl,etsec2")) {
		mode = MQ_MG_MODE;
		poll_mode = GFAR_SQ_POLLING;
	} else {
		mode = SQ_SG_MODE;
		poll_mode = GFAR_SQ_POLLING;
	}

	if (mode == SQ_SG_MODE) {
		num_tx_qs = 1;
		num_rx_qs = 1;
	} else {  
		 
		unsigned int num_grps = gfar_of_group_count(np);

		if (num_grps == 0 || num_grps > MAXGROUPS) {
			dev_err(&ofdev->dev, "Invalid # of int groups(%d)\n",
				num_grps);
			pr_err("Cannot do alloc_etherdev, aborting\n");
			return -EINVAL;
		}

		if (poll_mode == GFAR_SQ_POLLING) {
			num_tx_qs = num_grps;  
			num_rx_qs = num_grps;  
		} else {  
			u32 tx_queues, rx_queues;
			int ret;

			 
			ret = of_property_read_u32(np, "fsl,num_tx_queues",
						   &tx_queues);
			num_tx_qs = ret ? 1 : tx_queues;

			ret = of_property_read_u32(np, "fsl,num_rx_queues",
						   &rx_queues);
			num_rx_qs = ret ? 1 : rx_queues;
		}
	}

	if (num_tx_qs > MAX_TX_QS) {
		pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
		       num_tx_qs, MAX_TX_QS);
		pr_err("Cannot do alloc_etherdev, aborting\n");
		return -EINVAL;
	}

	if (num_rx_qs > MAX_RX_QS) {
		pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
		       num_rx_qs, MAX_RX_QS);
		pr_err("Cannot do alloc_etherdev, aborting\n");
		return -EINVAL;
	}

	*pdev = alloc_etherdev_mq(sizeof(*priv), num_tx_qs);
	dev = *pdev;
	if (NULL == dev)
		return -ENOMEM;

	priv = netdev_priv(dev);
	priv->ndev = dev;

	priv->mode = mode;
	priv->poll_mode = poll_mode;

	priv->num_tx_queues = num_tx_qs;
	netif_set_real_num_rx_queues(dev, num_rx_qs);
	priv->num_rx_queues = num_rx_qs;

	err = gfar_alloc_tx_queues(priv);
	if (err)
		goto tx_alloc_failed;

	err = gfar_alloc_rx_queues(priv);
	if (err)
		goto rx_alloc_failed;

	err = of_property_read_string(np, "model", &model);
	if (err) {
		pr_err("Device model property missing, aborting\n");
		goto rx_alloc_failed;
	}

	 
	INIT_LIST_HEAD(&priv->rx_list.list);
	priv->rx_list.count = 0;
	mutex_init(&priv->rx_queue_access);

	for (i = 0; i < MAXGROUPS; i++)
		priv->gfargrp[i].regs = NULL;

	 
	if (priv->mode == MQ_MG_MODE) {
		for_each_available_child_of_node(np, child) {
			if (!of_node_name_eq(child, "queue-group"))
				continue;

			err = gfar_parse_group(child, priv, model);
			if (err) {
				of_node_put(child);
				goto err_grp_init;
			}
		}
	} else {  
		err = gfar_parse_group(np, priv, model);
		if (err)
			goto err_grp_init;
	}

	if (of_property_read_bool(np, "bd-stash")) {
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING;
		priv->bd_stash_en = 1;
	}

	err = of_property_read_u32(np, "rx-stash-len", &stash_len);

	if (err == 0)
		priv->rx_stash_size = stash_len;

	err = of_property_read_u32(np, "rx-stash-idx", &stash_idx);

	if (err == 0)
		priv->rx_stash_index = stash_idx;

	if (stash_len || stash_idx)
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING;

	mac_addr = of_get_mac_address(np);

	if (!IS_ERR(mac_addr)) {
		ether_addr_copy(dev->dev_addr, mac_addr);
	} else {
		eth_hw_addr_random(dev);
		dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr);
	}

	if (model && !strcasecmp(model, "TSEC"))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
				     FSL_GIANFAR_DEV_HAS_COALESCE |
				     FSL_GIANFAR_DEV_HAS_RMON |
				     FSL_GIANFAR_DEV_HAS_MULTI_INTR;

	if (model && !strcasecmp(model, "eTSEC"))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
				     FSL_GIANFAR_DEV_HAS_COALESCE |
				     FSL_GIANFAR_DEV_HAS_RMON |
				     FSL_GIANFAR_DEV_HAS_MULTI_INTR |
				     FSL_GIANFAR_DEV_HAS_CSUM |
				     FSL_GIANFAR_DEV_HAS_VLAN |
				     FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
				     FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
				     FSL_GIANFAR_DEV_HAS_TIMER |
				     FSL_GIANFAR_DEV_HAS_RX_FILER;

	 
	err = of_get_phy_mode(np, &interface);
	if (!err)
		priv->interface = interface;
	else
		priv->interface = gfar_get_interface(dev);

	if (of_find_property(np, "fsl,magic-packet", NULL))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;

	if (of_get_property(np, "fsl,wake-on-filer", NULL))
		priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER;

	priv->phy_node = of_parse_phandle(np, "phy-handle", 0);

	 
	if (!priv->phy_node && of_phy_is_fixed_link(np)) {
		err = of_phy_register_fixed_link(np);
		if (err)
			goto err_grp_init;

		priv->phy_node = of_node_get(np);
	}

	 
	priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);

	return 0;

err_grp_init:
	unmap_group_regs(priv);
rx_alloc_failed:
	gfar_free_rx_queues(priv);
tx_alloc_failed:
	gfar_free_tx_queues(priv);
	free_gfar_dev(priv);
	return err;
}