Example #1
0
/***********************************************************
 * eth_set_multicast_list --                             *
 *   Add multicast addresses or set promiscuous mode.      *
 *   This function should have been but was not included   *
 *   by Marvell. -bbozarth                                 *
 ***********************************************************/
void mv_eth_set_multicast_list(struct net_device *dev) {

     mv_eth_priv        *priv = MV_ETH_PRIV(dev);
     int                queue = ETH_DEF_RXQ;
     struct dev_mc_list *curr_addr = dev->mc_list;
     int                i;

     if (dev->flags & IFF_PROMISC)
     {
        mvEthRxFilterModeSet(priv->hal_priv, 1);
     }
     else if (dev->flags & IFF_ALLMULTI)
     {
        mvEthRxFilterModeSet(priv->hal_priv, 0);
        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
        mvEthSetSpecialMcastTable(priv->port, queue);
        mvEthSetOtherMcastTable(priv->port, queue);
     }
     else if (dev->mc_count)
     {
        mvEthRxFilterModeSet(priv->hal_priv, 0);
        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
        for (i=0; i<dev->mc_count; i++, curr_addr = curr_addr->next)
        {
            if (!curr_addr)
                break;
            mvEthMcastAddrSet(priv->hal_priv, curr_addr->dmi_addr, queue);
        }
     }
     else /* No Mcast addrs, not promisc or all multi - clear tables */
     {
        mvEthRxFilterModeSet(priv->hal_priv, 0);
        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
     }
}
Example #2
0
/***********************************************************
 * mv_eth_stop --                                          *
 *   stop interface with linux core. stop port activity.   *
 *   free skb's from rings.                                *
 ***********************************************************/
int mv_eth_stop(struct net_device *dev)
{
	struct eth_port *priv = MV_ETH_PRIV(dev);

	/* first make sure that the port finished its Rx polling - see tg3 */
	napi_disable(priv->napiGroup[CPU_GROUP_DEF]);

	/* stop upper layer */
	netif_carrier_off(dev);
	netif_stop_queue(dev);

	/* stop tx/rx activity, mask all interrupts, relese skb in rings,*/
	mv_eth_stop_internals(priv);

	del_timer(&priv->tx_done_timer);
	clear_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(priv->flags));
	del_timer(&priv->cleanup_timer);
	clear_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(priv->flags));

	if (dev->irq != 0)
		free_irq(dev->irq, priv);

	printk(KERN_NOTICE "%s: stopped\n", dev->name);

	return 0;
}
Example #3
0
/*********************************************************** 
 * eth_set_mac_addr --                                   *
 *   stop port activity. set new addr in device and hw.    *
 *   restart port activity.                                *
 ***********************************************************/
static int mv_eth_set_mac_addr_internals(struct net_device *dev, void *addr )
{
    mv_eth_priv *priv = MV_ETH_PRIV(dev);
    u8          *mac = &(((u8*)addr)[2]);  /* skip on first 2B (ether HW addr type) */
    int i;

    /* remove previous address table entry */
    if( mvEthMacAddrSet( priv->hal_priv, dev->dev_addr, -1) != MV_OK ) {
        printk( KERN_ERR "%s: ethSetMacAddr failed\n", dev->name );
        return -1;
    }

    /* set new addr in hw */
    if( mvEthMacAddrSet( priv->hal_priv, mac, ETH_DEF_RXQ) != MV_OK ) {
        printk( KERN_ERR "%s: ethSetMacAddr failed\n", dev->name );
    return -1;
    }

    /* set addr in the device */ 
    for( i = 0; i < 6; i++ )
        dev->dev_addr[i] = mac[i];

    printk( KERN_NOTICE "%s: mac address changed\n", dev->name );

    return 0;
}
Example #4
0
/*********************************************************** 
 * mv_eth_stop --                                       *
 *   stop interface with linux core. stop port activity.   *
 *   free skb's from rings.                                *
 ***********************************************************/
int mv_eth_stop( struct net_device *dev )
{
    unsigned long   flags;
    mv_eth_priv     *priv = MV_ETH_PRIV(dev);

    /* first make sure that the port finished its Rx polling - see tg3 */
    /* otherwise it may cause issue in SMP, one CPU is here and the other is doing the polling
    and both of it are messing with the descriptors rings!! */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    netif_poll_disable(dev);
#else
    napi_disable(&priv->napi);
#endif
    spin_lock_irqsave(priv->lock, flags);

    /* stop upper layer */
    netif_carrier_off(dev);
    netif_stop_queue(dev);
    /* stop tx/rx activity, mask all interrupts, relese skb in rings,*/
    mv_eth_stop_internals(priv);

    spin_unlock_irqrestore(priv->lock, flags);

    if( dev->irq != 0 )
    {
        free_irq(dev->irq, priv);
    }
    printk(KERN_NOTICE "%s: stopped\n", dev->name);

    return 0;
}
Example #5
0
/******************************************************************************
* mv_eth_tool_set_coalesce
* Description:
*	ethtool set RX/TX coalesce parameters
* INPUT:
*	netdev		Network device structure pointer
*	cmd		Coalesce parameters
* OUTPUT
*	None
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_set_coalesce(struct net_device *netdev,
			     struct ethtool_coalesce *cmd)
{
	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);

	if ((cmd->rx_coalesce_usecs == 0) ||
		(cmd->tx_coalesce_usecs == 0)) {
		/* coalesce usec=0 means that coalesce frames should be used,
		 * which is not permitted (unsupported) */
		return -EPERM;
	}

	if ((cmd->rx_coalesce_usecs * 166 / 64 > 0x3FFF) ||
		(cmd->tx_coalesce_usecs * 166 / 64 > 0x3FFF))
		return -EINVAL;
	
	/* Save values for mv_eth_start_internals() */
	priv->rx_coal_usec = cmd->rx_coalesce_usecs;
	priv->tx_coal_usec = cmd->tx_coalesce_usecs;
	
	mvEthRxCoalSet (priv->hal_priv, cmd->rx_coalesce_usecs);
	mvEthTxCoalSet (priv->hal_priv, cmd->tx_coalesce_usecs);

	return 0;
}
Example #6
0
/******************************************************************************
* mv_eth_tool_get_pauseparam
* Description:
*	ethtool get pause parameters
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	pause		Pause paranmeters
* RETURN:
*	None
*
*******************************************************************************/
void mv_eth_tool_get_pauseparam(struct net_device *netdev,
				struct ethtool_pauseparam *pause)
{
	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
	ETH_PORT_CTRL		*pPortCtrl = (ETH_PORT_CTRL*)(priv->hal_priv);
	MV_U32			reg;

	reg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo));
	
	pause->rx_pause = 0;
	pause->tx_pause = 0;

	if (reg & ETH_DISABLE_FC_AUTO_NEG_MASK) { /* autoneg disabled */
		pause->autoneg = AUTONEG_DISABLE;
		if (reg & ETH_SET_FLOW_CTRL_MASK)
		{
			pause->rx_pause = 1;
			pause->tx_pause = 1;
		}
	} else { /* autoneg enabled */
		pause->autoneg = AUTONEG_ENABLE;
		if (reg & ETH_ADVERTISE_SYM_FC_MASK)
		{
			pause->rx_pause = 1;
			pause->tx_pause = 1;
		}
	}
}
Example #7
0
/******************************************************************************
* mv_eth_tool_set_settings
* Description:
*	ethtool set standard port settings
* INPUT:
*	netdev		Network device structure pointer
*	cmd		command (settings)
* OUTPUT
*	None
* RETURN:
*	0 for success
*
*******************************************************************************/
int mv_eth_tool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	struct eth_port *priv = MV_ETH_PRIV(dev);
	int _speed, _duplex, _autoneg, err;

#ifdef CONFIG_MV_ETH_SWITCH
	 if (isSwitch(priv))
		 return -EPERM;
#endif /* CONFIG_MV_ETH_SWITCH */


	_duplex  = priv->duplex_cfg;
	_speed   = priv->speed_cfg;
	_autoneg = priv->autoneg_cfg;

	priv->duplex_cfg = cmd->duplex;
	priv->speed_cfg = cmd->speed;
	priv->autoneg_cfg = cmd->autoneg;
	err = mv_eth_tool_restore_settings(dev);

	if (err) {
		priv->duplex_cfg = _duplex;
		priv->speed_cfg = _speed;
		priv->autoneg_cfg = _autoneg;
	}
	return err;
}
Example #8
0
/***********************************************************
 * eth_set_multicast_list --                             *
 *   Add multicast addresses or set promiscuous mode.      *
 *   This function should have been but was not included   *
 *   by Marvell. -bbozarth                                 *
 ***********************************************************/
void mv_eth_set_multicast_list(struct net_device *dev) {

     mv_eth_priv        *priv = MV_ETH_PRIV(dev);
     int                queue = ETH_DEF_RXQ;
     int                i;

     if (dev->flags & IFF_PROMISC)
     {
        mvEthRxFilterModeSet(priv->hal_priv, 1);
     }
     else if (dev->flags & IFF_ALLMULTI)
     {
        mvEthRxFilterModeSet(priv->hal_priv, 0);
        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
        mvEthSetSpecialMcastTable(priv->port, queue);
        mvEthSetOtherMcastTable(priv->port, queue);
     }
     else if (!netdev_mc_empty(dev))
     {
		struct netdev_hw_addr *ha;

        mvEthRxFilterModeSet(priv->hal_priv, 0);
        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
		netdev_for_each_mc_addr(ha, dev)
        {
            mvEthMcastAddrSet(priv->hal_priv, ha->addr, queue);
        }
     }
Example #9
0
/******************************************************************************
* mv_eth_tool_get_pauseparam
* Description:
*	ethtool get pause parameters
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	pause		Pause paranmeters
* RETURN:
*	None
*
*******************************************************************************/
void mv_eth_tool_get_pauseparam(struct net_device *netdev,
				struct ethtool_pauseparam *pause)
{
	struct eth_port 	*priv = MV_ETH_PRIV(netdev);
	int 			port = priv->port;
	MV_ETH_PORT_STATUS	portStatus;
	MV_ETH_PORT_FC 		flowCtrl;

#ifdef CONFIG_MV_ETH_SWITCH
	if (isSwitch(priv)) {
		printk("mv_eth_tool_get_pauseparam() is not supported on a switch port\n");
		return;
	}
#endif /* CONFIG_MV_ETH_SWITCH */

	mvNetaFlowCtrlGet(port, &flowCtrl);
	if ((flowCtrl == MV_ETH_FC_AN_NO) || (flowCtrl == MV_ETH_FC_AN_SYM) || (flowCtrl == MV_ETH_FC_AN_ASYM))
		pause->autoneg = AUTONEG_ENABLE;
	else
		pause->autoneg = AUTONEG_DISABLE;

	mvNetaLinkStatus(port, &portStatus);
	if (portStatus.rxFc == MV_ETH_FC_DISABLE)
		pause->rx_pause = 0;
	else
		pause->rx_pause = 1;

	if (portStatus.txFc == MV_ETH_FC_DISABLE)
		pause->tx_pause = 0;
	else
		pause->tx_pause = 1;
}
Example #10
0
/******************************************************************************
* mv_eth_tool_get_regs
* Description:
*	ethtool get registers array
* INPUT:
*	netdev		Network device structure pointer
*	regs		registers information
* OUTPUT
*	p		registers array
* RETURN:
*	None
*
*******************************************************************************/
void mv_eth_tool_get_regs(struct net_device *netdev,
			  struct ethtool_regs *regs, void *p)
{
	struct eth_port	*priv = MV_ETH_PRIV(netdev);
	uint32_t 	*regs_buff = p;

	memset(p, 0, MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t));

	regs->version = mvCtrlModelRevGet();

	/* ETH port registers */
	regs_buff[0]  = MV_REG_READ(ETH_PORT_STATUS_REG(priv->port));
	regs_buff[1]  = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(priv->port));
	regs_buff[2]  = MV_REG_READ(ETH_PORT_CONFIG_REG(priv->port));
	regs_buff[3]  = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(priv->port));
	regs_buff[4]  = MV_REG_READ(ETH_SDMA_CONFIG_REG(priv->port));
/*	regs_buff[5]  = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(priv->port)); */
	regs_buff[6]  = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(priv->port));
	/* regs_buff[7]  = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(priv->port)); */
	regs_buff[8]  = MV_REG_READ(ETH_INTR_CAUSE_REG(priv->port));
	regs_buff[9]  = MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(priv->port));
	regs_buff[10] = MV_REG_READ(ETH_INTR_MASK_REG(priv->port));
	regs_buff[11] = MV_REG_READ(ETH_INTR_MASK_EXT_REG(priv->port));
	/* ETH Unit registers */
	regs_buff[16] = MV_REG_READ(ETH_PHY_ADDR_REG(priv->port));
	regs_buff[17] = MV_REG_READ(ETH_UNIT_INTR_CAUSE_REG(priv->port));
	regs_buff[18] = MV_REG_READ(ETH_UNIT_INTR_MASK_REG(priv->port));
	regs_buff[19] = MV_REG_READ(ETH_UNIT_ERROR_ADDR_REG(priv->port));
	regs_buff[20] = MV_REG_READ(ETH_UNIT_INT_ADDR_ERROR_REG(priv->port));

}
Example #11
0
/******************************************************************************
* mv_eth_tool_get_ethtool_stats
* Description:
*	ethtool get statistics
* INPUT:
*	netdev		Network device structure pointer
*	stats		stats parameters
* OUTPUT
*	data		output data
* RETURN:
*	None
*
*******************************************************************************/
void mv_eth_tool_get_ethtool_stats(struct net_device *netdev,
				   struct ethtool_stats *stats, uint64_t *data)
{
	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
	uint64_t	*pdest = data;
	int 		i, q;

	for (i = 0; i < MV_ETH_TOOL_GLOBAL_STATS_LEN; i++) {
		char *p = (char *)priv +
			mv_eth_tool_global_strings_stats[i].stat_offset;
		pdest[i] =  *(uint32_t *)p;
	}
	pdest += MV_ETH_TOOL_GLOBAL_STATS_LEN;
	
	for (q = 0; q < MV_ETH_RX_Q_NUM; q++) {
		for (i = 0; i < MV_ETH_TOOL_RX_QUEUE_STATS_LEN; i++) {
			char *p = (char *)priv +
				mv_eth_tool_rx_queue_strings_stats[i].stat_offset;
			pdest[i] =  *((uint32_t *)p + q);
		}
		pdest += MV_ETH_TOOL_RX_QUEUE_STATS_LEN;
	}

	for (q = 0; q < MV_ETH_TX_Q_NUM; q++) {
		for (i = 0; i < MV_ETH_TOOL_TX_QUEUE_STATS_LEN; i++) {
			char *p = (char *)priv +
				mv_eth_tool_tx_queue_strings_stats[i].stat_offset;
			pdest[i] =  *((uint32_t *)p + q);
		}
		pdest += MV_ETH_TOOL_TX_QUEUE_STATS_LEN;
	}
}
Example #12
0
/******************************************************************************
* mv_eth_tool_set_settings
* Description:
*	ethtool set standard port settings
* INPUT:
*	netdev		Network device structure pointer
*	cmd		command (settings)
* OUTPUT
*	None
* RETURN:
*	0 for success
*
*******************************************************************************/
int mv_eth_tool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	struct eth_port *priv = MV_ETH_PRIV(dev);
	int _speed, _duplex, _autoneg, _advertise, err;

	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
		printk(KERN_ERR "%s is not supported on %s\n", __func__, dev->name);
		return -EOPNOTSUPP;
	}

	_duplex  = priv->duplex_cfg;
	_speed   = priv->speed_cfg;
	_autoneg = priv->autoneg_cfg;
	_advertise = priv->advertise_cfg;

	priv->duplex_cfg = cmd->duplex;
	priv->speed_cfg = cmd->speed;
	priv->autoneg_cfg = cmd->autoneg;
	priv->advertise_cfg = cmd->advertising;
	err = mv_eth_tool_restore_settings(dev);

	if (err) {
		priv->duplex_cfg = _duplex;
		priv->speed_cfg = _speed;
		priv->autoneg_cfg = _autoneg;
		priv->advertise_cfg = _advertise;
	}
	return err;
}
Example #13
0
/******************************************************************************
* mv_eth_tool_get_pauseparam
* Description:
*	ethtool get pause parameters
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	pause		Pause paranmeters
* RETURN:
*	None
*
*******************************************************************************/
void mv_eth_tool_get_pauseparam(struct net_device *netdev,
				struct ethtool_pauseparam *pause)
{
	struct eth_port      *priv = MV_ETH_PRIV(netdev);
	int                  port = priv->port;
	MV_ETH_PORT_STATUS   portStatus;
	MV_ETH_PORT_FC       flowCtrl;

	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
		printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
		return;
	}

	mvNetaFlowCtrlGet(port, &flowCtrl);
	if ((flowCtrl == MV_ETH_FC_AN_NO) || (flowCtrl == MV_ETH_FC_AN_SYM) || (flowCtrl == MV_ETH_FC_AN_ASYM))
		pause->autoneg = AUTONEG_ENABLE;
	else
		pause->autoneg = AUTONEG_DISABLE;

	mvNetaLinkStatus(port, &portStatus);
	if (portStatus.rxFc == MV_ETH_FC_DISABLE)
		pause->rx_pause = 0;
	else
		pause->rx_pause = 1;

	if (portStatus.txFc == MV_ETH_FC_DISABLE)
		pause->tx_pause = 0;
	else
		pause->tx_pause = 1;
}
Example #14
0
/***********************************************************
 * mv_eth_start --                                         *
 *   start a network device. connect and enable interrupts *
 *   set hw defaults. fill rx buffers. restart phy link    *
 *   auto neg. set device link flags. report status.       *
 ***********************************************************/
static int mv_eth_start(struct net_device *dev)
{
	struct eth_port *priv = MV_ETH_PRIV(dev);
	int group;

	/* in default link is down */
	netif_carrier_off(dev);

	/* Stop the TX queue - it will be enabled upon PHY status change after link-up interrupt/timer */
	netif_tx_stop_all_queues(dev);

	/* fill rx buffers, start rx/tx activity, set coalescing */
	if (mv_eth_start_internals(priv, dev->mtu) != 0) {
		printk(KERN_ERR "%s: start internals failed\n", dev->name);
		goto error;
	}

	/* enable polling on the port, must be used after netif_poll_disable */
	if (priv->flags & MV_ETH_F_CONNECT_LINUX)
		for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
			napi_enable(priv->napiGroup[group]);


	if ((priv->flags & MV_ETH_F_LINK_UP) && !(priv->flags & MV_ETH_F_EXT_SWITCH)) {

		if (mv_eth_ctrl_is_tx_enabled(priv)) {
			netif_carrier_on(dev);
			netif_tx_wake_all_queues(dev);
		}
		printk(KERN_NOTICE "%s: link up\n", dev->name);
	}
#ifdef CONFIG_MV_ETH_SWITCH_LINK
	if (priv->flags & MV_ETH_F_EXT_SWITCH) {
		struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);

		dev_priv->link_map = 0;
		mv_switch_link_update_event(dev_priv->port_map, 1);
	}
#endif /* CONFIG_MV_ETH_SWITCH_LINK */

	if (priv->flags & MV_ETH_F_CONNECT_LINUX) {
		/* connect to port interrupt line */
		if (request_irq(dev->irq, mv_eth_isr, (IRQF_DISABLED|IRQF_SAMPLE_RANDOM), "mv_eth", priv)) {
			printk(KERN_ERR "cannot request irq %d for %s port %d\n", dev->irq, dev->name, priv->port);
			if (priv->flags & MV_ETH_F_CONNECT_LINUX)
				napi_disable(priv->napiGroup[CPU_GROUP_DEF]);
			goto error;
		}

		/* unmask interrupts */
		mv_eth_interrupts_unmask(priv);
		smp_call_function_many(cpu_online_mask, (smp_call_func_t)mv_eth_interrupts_unmask, (void *)priv, 1);

		printk(KERN_NOTICE "%s: started\n", dev->name);
	}
	return 0;
error:
	printk(KERN_ERR "%s: start failed\n", dev->name);
	return -1;
}
Example #15
0
/***********************************************************
 * mv_eth_stop --                                          *
 *   stop interface with linux core. stop port activity.   *
 *   free skb's from rings.                                *
 ***********************************************************/
int mv_eth_stop(struct net_device *dev)
{
	struct eth_port *priv = MV_ETH_PRIV(dev);
	struct cpu_ctrl *cpuCtrl;
	int group, cpu;

	/* first make sure that the port finished its Rx polling - see tg3 */
	for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
		napi_disable(priv->napiGroup[group]);

	/* stop upper layer */
	netif_carrier_off(dev);
	netif_tx_stop_all_queues(dev);

	/* stop tx/rx activity, mask all interrupts, relese skb in rings,*/
	mv_eth_stop_internals(priv);
	for_each_possible_cpu(cpu) {
		cpuCtrl = priv->cpu_config[cpu];
		del_timer(&cpuCtrl->tx_done_timer);
		clear_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(cpuCtrl->flags));
		del_timer(&cpuCtrl->cleanup_timer);
		clear_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(cpuCtrl->flags));
	}

	if (dev->irq != 0)
		free_irq(dev->irq, priv);

	printk(KERN_NOTICE "%s: stopped\n", dev->name);

	return 0;
}
Example #16
0
void mv_eth_set_multicast_list(struct net_device *dev)
{
	struct eth_port     *priv = MV_ETH_PRIV(dev);
	int                 rxq = CONFIG_MV_ETH_RXQ_DEF;
/*
	printk("%s - mv_eth_set_multicast_list: flags=0x%x, mc_count=%d\n",
		dev->name, dev->flags, dev->mc_count);
*/
	if (!mv_eth_pnc_ctrl_en) {
		printk(KERN_ERR "%s: PNC control is disabled\n", __func__);
		return;
	}

	if (dev->flags & IFF_PROMISC) {
		/* Accept all */
		pnc_mac_me(priv->port, NULL, rxq);
		pnc_mcast_all(priv->port, 1);
	} else {
		/* Accept Unicast to me */
		pnc_mac_me(priv->port, dev->dev_addr, rxq);

		if (dev->flags & IFF_ALLMULTI) {
			/* Accept all multicast */
			pnc_mcast_all(priv->port, 1);
		} else {
			/* Accept only initialized Multicast */
			pnc_mcast_all(priv->port, 0);
			pnc_mcast_me(priv->port, NULL);

			/* Number of entires for all ports is restricted by CONFIG_MV_ETH_PNC_MCAST_NUM */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
			if (!netdev_mc_empty(dev)) {
				struct netdev_hw_addr *ha;

				netdev_for_each_mc_addr(ha, dev) {
					if (pnc_mcast_me(priv->port, ha->addr)) {
						printk(KERN_ERR "%s: Mcast init failed\n", dev->name);
						break;
					}
				}
			}
#else
			{
				struct dev_mc_list *curr_addr = dev->mc_list;
				int                i;
				for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) {
					if (!curr_addr)
						break;
					if (pnc_mcast_me(priv->port, curr_addr->dmi_addr)) {
						printk(KERN_ERR "%s: Mcast init failed - %d of %d\n",
							dev->name, i, dev->mc_count);
						break;
					}
				}
			}
#endif /* KERNEL_VERSION >= 2.6.34 */
		}
	}
}
Example #17
0
/******************************************************************************
* mv_eth_tool_get_rx_csum
* Description:
*	ethtool get RX checksum offloading status
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	None
* RETURN:
*	RX checksum
*
*******************************************************************************/
u32 mv_eth_tool_get_rx_csum(struct net_device *netdev)
{
	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
#ifdef RX_CSUM_OFFLOAD
	return (priv->rx_csum_offload != 0);
#else
	return 0;
#endif
}
Example #18
0
/******************************************************************************
* mv_eth_tool_get_rx_csum
* Description:
*	ethtool get RX checksum offloading status
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	None
* RETURN:
*	RX checksum
*
*******************************************************************************/
u32 mv_eth_tool_get_rx_csum(struct net_device *netdev)
{
#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
	struct eth_port *priv = MV_ETH_PRIV(netdev);

	return (priv->rx_csum_offload != 0);
#else
	return 0;
#endif
}
Example #19
0
/******************************************************************************
* mv_eth_tool_nway_reset
* Description:
*	ethtool restart auto negotiation
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	None
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_nway_reset(struct net_device *netdev)
{
	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
	MV_U32		mv_phy_addr = (MV_U32)(priv->phy_id);

	if (mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK)
		return -EINVAL;

	return 0;
}
Example #20
0
/******************************************************************************
* mv_eth_tool_set_rx_csum
* Description:
*	ethtool enable/disable RX checksum offloading
* INPUT:
*	netdev		Network device structure pointer
*	data		Command data
* OUTPUT
*	None
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_set_rx_csum(struct net_device *netdev, uint32_t data)
{
	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
#ifdef RX_CSUM_OFFLOAD
	priv->rx_csum_offload = data;
	return 0;
#else
	return data ? -EINVAL : 0;
#endif
}
/******************************************************************************
* mv_eth_tool_get_settings
* Description:
*	ethtool get standard port settings
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	cmd		command (settings)
* RETURN:
*	0 for success
*
*******************************************************************************/
int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
	struct eth_port 	*priv = MV_ETH_PRIV(netdev);
	MV_U32			mv_phy_addr;
	MV_ETH_PORT_SPEED 	speed;
	MV_ETH_PORT_DUPLEX 	duplex;
	MV_ETH_PORT_STATUS      status;

	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
		printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
		return -EOPNOTSUPP;
	}

	cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
			| SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII
			| SUPPORTED_1000baseT_Full);

	mv_phy_addr = mvBoardPhyAddrGet(priv->port);

	mvNetaLinkStatus(priv->port, &status);

	switch (status.speed) {
	case MV_ETH_SPEED_1000:
		cmd->speed = SPEED_1000;
		break;
	case MV_ETH_SPEED_100:
		cmd->speed = SPEED_100;
		break;
	case MV_ETH_SPEED_10:
		cmd->speed = SPEED_10;
		break;
	default:
		return -EINVAL;
	}

	if (status.duplex == MV_ETH_DUPLEX_FULL)
		cmd->duplex = 1;
	else
		cmd->duplex = 0;

	cmd->port = PORT_MII;
	cmd->phy_address = mv_phy_addr;
	cmd->transceiver = XCVR_INTERNAL;
	/* check if speed and duplex are AN */
	mvNetaSpeedDuplexGet(priv->port, &speed, &duplex);
	if (speed == MV_ETH_SPEED_AN && duplex == MV_ETH_DUPLEX_AN) {
		/* Note: lp_advertising not available in this kernel */
		cmd->advertising = 0;
		cmd->autoneg = AUTONEG_ENABLE;
		mvEthPhyAdvertiseGet(mv_phy_addr, (MV_U16 *)&(cmd->advertising));
	} else
		cmd->autoneg = AUTONEG_DISABLE;

	return 0;
}
Example #22
0
/******************************************************************************
* mv_eth_tool_set_rx_csum
* Description:
*	ethtool enable/disable RX checksum offloading
* INPUT:
*	netdev		Network device structure pointer
*	data		Command data
* OUTPUT
*	None
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_set_rx_csum(struct net_device *netdev, uint32_t data)
{
#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
	struct eth_port *priv = MV_ETH_PRIV(netdev);

	priv->rx_csum_offload = data;
	return 0;
#else
	return -EOPNOTSUPP;
#endif
}
Example #23
0
/******************************************************************************
* mv_eth_tool_get_coalesce
* Description:
*	ethtool get RX/TX coalesce parameters
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	cmd		Coalesce parameters
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_get_coalesce(struct net_device *netdev,
			     struct ethtool_coalesce *cmd)
{
	struct eth_port *pp = MV_ETH_PRIV(netdev);
	/* get coal parameters only for rxq=0, txp=txq=0 !!!
	   notice that if you use ethtool to set coal, then all queues have the same value */
	cmd->rx_coalesce_usecs = mvNetaRxqTimeCoalGet(pp->port, 0);
	cmd->rx_max_coalesced_frames = mvNetaRxqPktsCoalGet(pp->port, 0);
	cmd->tx_max_coalesced_frames = mvNetaTxDonePktsCoalGet(pp->port, 0, 0);
	return 0;
}
Example #24
0
/******************************************************************************
* mv_eth_tool_get_link
* Description:
*	ethtool get link status
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	None
* RETURN:
*	0 if link is down, 1 if link is up
*
*******************************************************************************/
u32 mv_eth_tool_get_link(struct net_device *netdev)
{
	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
	MV_ETH_PORT_STATUS	status;

	mvEthStatusGet(priv->hal_priv, &status);
	if (status.isLinkUp == MV_TRUE)
		return 1;
	
	return 0;
}
Example #25
0
/******************************************************************************
* mv_eth_tool_get_coalesce
* Description:
*	ethtool get RX/TX coalesce parameters
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	cmd		Coalesce parameters
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_get_coalesce(struct net_device *netdev,
			     struct ethtool_coalesce *cmd)
{
	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);

	if (mvEthCoalGet(priv->hal_priv, &cmd->rx_coalesce_usecs,
	    &cmd->tx_coalesce_usecs) != MV_OK)
		return -EINVAL;
	
	return 0;
}
Example #26
0
int mv_gtw_start( struct net_device *dev )
{
    mv_eth_priv		*priv = MV_ETH_PRIV(dev);
    struct 		mv_vlan_cfg *vlan_cfg = MV_NETDEV_VLAN(dev);
    unsigned char	broadcast[6] = {0xff,0xff,0xff,0xff,0xff,0xff};

    printk("mv_gateway: starting %s\n",dev->name);

    /* start upper layer */
    netif_carrier_on(dev);
    netif_wake_queue(dev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    netif_poll_enable(dev);
#else
    if ( (priv->net_dev == dev) || !netif_running(priv->net_dev) )
    {
	napi_enable(&priv->napi);
    }
#endif

    /* Add our MAC addr to the VLAN DB at switch level to forward packets with this DA */
    /* to CPU port by using the tunneling feature. The device is always in promisc mode.      */
    mv_gtw_set_mac_addr_to_switch(dev->dev_addr, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id), (1<<SWITCH_PORT_CPU), 1);

    /* We also need to allow L2 broadcasts comming up for this interface */
    mv_gtw_set_mac_addr_to_switch(broadcast, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id), 
					vlan_cfg->ports_mask|(1<<SWITCH_PORT_CPU), 1);

    if (!(priv->flags & MV_ETH_F_TIMER))
    {
        priv->timer.expires = jiffies + ((HZ*CONFIG_MV_ETH_TIMER_PERIOD)/1000); /*ms*/
        add_timer( &(priv->timer) );
        priv->flags |= MV_ETH_F_TIMER;
    }

    if ( (priv->net_dev == dev) || !netif_running(priv->net_dev) )
    {
        priv->net_dev = dev;

	/* connect to MAC port interrupt line */
    	if ( request_irq( ETH_PORT_IRQ_NUM(priv->port), mv_eth_interrupt_handler, 
             (IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "mv_gateway", priv) ) 
	{
        	printk(KERN_ERR "failed to assign irq%d\n", ETH_PORT_IRQ_NUM(priv->port));
    	}

        /* unmask interrupts */
        mv_eth_unmask_interrupts(priv);
    }
    
    return 0;
}
Example #27
0
/******************************************************************************
* mv_eth_tool_get_settings
* Description:
*	ethtool get standard port settings
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	cmd		command (settings)
* RETURN:
*	0 for success
*
*******************************************************************************/
int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
	struct mii_if_info 	mii;
	int			retval;
	MV_ETH_PORT_STATUS 	status;
	
#ifdef CONFIG_MII	
	mii.dev			= netdev;
	mii.phy_id_mask 	= 0x1F;
	mii.reg_num_mask 	= 0x1F;
	mii.mdio_read 		= mv_eth_tool_read_mdio;
	mii.mdio_write 		= mv_eth_tool_write_mdio;
	mii.phy_id 		= priv->phy_id;
	mii.supports_gmii 	= 1;

	/* Get values from PHY */
	retval = mii_ethtool_gset(&mii, cmd);
	if (retval)
		return retval;
#endif

	/* Get some values from MAC */
	mvEthStatusGet(priv->hal_priv, &status);
	
	switch (status.speed) {
	case MV_ETH_SPEED_1000:
		cmd->speed = SPEED_1000;
		break;	
	case MV_ETH_SPEED_100:
		cmd->speed = SPEED_100;
		break;
	case MV_ETH_SPEED_10:
		cmd->speed = SPEED_10;
		break;
	default:
		return -EINVAL;
	}

	if (status.duplex == MV_ETH_DUPLEX_FULL) 
		cmd->duplex = 1;
	else
		cmd->duplex = 0;

	cmd->port = PORT_MII;
	cmd->phy_address = priv->phy_id;

	return 0;
}
Example #28
0
static struct net_device* mv_gtw_main_net_dev_get(void)
{
    int                 i;
    mv_eth_priv         *priv;
    struct net_device   *dev;

    for (i=0; i<mv_net_devs_num; i++) {
        dev = mv_net_devs[i];
        priv = MV_ETH_PRIV(dev);

        if (netif_running(dev) && priv->isGtw)
            return dev;
    }
    return NULL;
}
Example #29
0
/******************************************************************************
* mv_eth_tool_get_link
* Description:
*	ethtool get link status
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	None
* RETURN:
*	0 if link is down, 1 if link is up
*
*******************************************************************************/
u32 mv_eth_tool_get_link(struct net_device *netdev)
{
	struct eth_port     *pp = MV_ETH_PRIV(netdev);
#ifdef CONFIG_MV_ETH_SWITCH
	 if (isSwitch(pp))
		 return -EPERM;
#endif /* CONFIG_MV_ETH_SWITCH */


	if (pp) {
		if (mvNetaLinkIsUp(pp->port))
			return 1;
	}
	return 0;
}
Example #30
0
/******************************************************************************
* mv_eth_tool_nway_reset
* Description:
*	ethtool restart auto negotiation
* INPUT:
*	netdev		Network device structure pointer
* OUTPUT
*	None
* RETURN:
*	0 on success
*
*******************************************************************************/
int mv_eth_tool_nway_reset(struct net_device *netdev)
{
	struct eth_port 	*priv = MV_ETH_PRIV(netdev);
	MV_U32		mv_phy_addr = mvBoardPhyAddrGet(priv->port);
#ifdef CONFIG_MV_ETH_SWITCH
	 if (isSwitch(priv))
		 return -EPERM;
#endif /* CONFIG_MV_ETH_SWITCH */


	if (mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK)
		return -EINVAL;

	return 0;
}