Ejemplo n.º 1
0
static int e1000_set_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;

	/*
	 * When SoL/IDER sessions are active, autoneg/speed/duplex
	 * cannot be changed
	 */
	if (e1000_check_reset_block(hw)) {
		e_err("Cannot change link characteristics when SoL/IDER is "
		      "active.\n");
		return -EINVAL;
	}

	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
		msleep(1);

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		hw->mac.autoneg = 1;
		if (hw->phy.media_type == e1000_media_type_fiber)
			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
						     ADVERTISED_FIBRE |
						     ADVERTISED_Autoneg;
		else
			hw->phy.autoneg_advertised = ecmd->advertising |
						     ADVERTISED_TP |
						     ADVERTISED_Autoneg;
		ecmd->advertising = hw->phy.autoneg_advertised;
		if (adapter->fc_autoneg)
			hw->fc.requested_mode = e1000_fc_default;
	} else {
		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
			clear_bit(__E1000_RESETTING, &adapter->state);
			return -EINVAL;
		}
	}

	/* reset the link */

	if (netif_running(adapter->netdev)) {
		e1000e_down(adapter);
		e1000e_up(adapter);
	} else {
		e1000e_reset(adapter);
	}

	clear_bit(__E1000_RESETTING, &adapter->state);
	return 0;
}
Ejemplo n.º 2
0
static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);

	if (data)
		adapter->flags |= FLAG_RX_CSUM_ENABLED;
	else
		adapter->flags &= ~FLAG_RX_CSUM_ENABLED;

	if (netif_running(netdev))
		e1000e_reinit_locked(adapter);
	else
		e1000e_reset(adapter);
	return 0;
}
Ejemplo n.º 3
0
Archivo: ethtool.c Proyecto: A-K/linux
static int e1000_set_pauseparam(struct net_device *netdev,
				struct ethtool_pauseparam *pause)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;
	int retval = 0;

	adapter->fc_autoneg = pause->autoneg;

	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
		usleep_range(1000, 2000);

	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
		hw->fc.requested_mode = e1000_fc_default;
		if (netif_running(adapter->netdev)) {
			e1000e_down(adapter);
			e1000e_up(adapter);
		} else {
			e1000e_reset(adapter);
		}
	} else {
		if (pause->rx_pause && pause->tx_pause)
			hw->fc.requested_mode = e1000_fc_full;
		else if (pause->rx_pause && !pause->tx_pause)
			hw->fc.requested_mode = e1000_fc_rx_pause;
		else if (!pause->rx_pause && pause->tx_pause)
			hw->fc.requested_mode = e1000_fc_tx_pause;
		else if (!pause->rx_pause && !pause->tx_pause)
			hw->fc.requested_mode = e1000_fc_none;

		hw->fc.current_mode = hw->fc.requested_mode;

		if (hw->phy.media_type == e1000_media_type_fiber) {
			retval = hw->mac.ops.setup_link(hw);
			/* implicit goto out */
		} else {
			retval = e1000e_force_mac_fc(hw);
			if (retval)
				goto out;
			e1000e_set_fc_watermarks(hw);
		}
	}

out:
	clear_bit(__E1000_RESETTING, &adapter->state);
	return retval;
}
Ejemplo n.º 4
0
/**
 * e1000e_remove - Device Removal Routine
 *
 * @v pdev PCI device information struct
 *
 **/
void e1000e_remove ( struct pci_device *pdev )
{
	struct net_device *netdev = pci_get_drvdata ( pdev );
	struct e1000_adapter *adapter = netdev_priv ( netdev );

	DBGP ( "e1000e_remove\n" );

	if ( adapter->hw.flash_address )
		iounmap ( adapter->hw.flash_address );
	if  ( adapter->hw.hw_addr )
		iounmap ( adapter->hw.hw_addr );

	unregister_netdev ( netdev );
	e1000e_reset  ( adapter );
	netdev_nullify ( netdev );
	netdev_put ( netdev );
}
Ejemplo n.º 5
0
/**
 * e1000e_open - Called when a network interface is made active
 *
 * @v netdev	network interface device structure
 * @ret rc	Return status code, 0 on success, negative value on failure
 *
 **/
static int e1000e_open ( struct net_device *netdev )
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	int err;

	DBGP ( "e1000e_open\n" );

	/* allocate transmit descriptors */
	err = e1000e_setup_tx_resources ( adapter );
	if ( err ) {
		DBG ( "Error setting up TX resources!\n" );
		goto err_setup_tx;
	}

	/* allocate receive descriptors */
	err = e1000e_setup_rx_resources ( adapter );
	if ( err ) {
		DBG ( "Error setting up RX resources!\n" );
		goto err_setup_rx;
	}

	e1000e_configure_tx ( adapter );

	e1000e_configure_rx ( adapter );

	DBG ( "E1000_RXDCTL(0): %#08x\n",  E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) );

	return 0;

err_setup_rx:
        DBG ( "err_setup_rx\n" );
	e1000e_free_tx_resources ( adapter );
err_setup_tx:
        DBG ( "err_setup_tx\n" );
	e1000e_reset ( adapter );

	return err;
}
Ejemplo n.º 6
0
/**
 * e1000_close - Disables a network interface
 *
 * @v netdev	network interface device structure
 *
 **/
static void e1000e_close ( struct net_device *netdev )
{
	struct e1000_adapter *adapter = netdev_priv ( netdev );
	struct e1000_hw *hw = &adapter->hw;
	uint32_t rctl;
	uint32_t icr;

	DBGP ( "e1000_close\n" );

	/* Acknowledge interrupts */
	icr = E1000_READ_REG ( hw, E1000_ICR );

	e1000e_irq_disable ( adapter );

	/* disable receives */
	rctl = E1000_READ_REG ( hw, E1000_RCTL );
	E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN );
	e1e_flush();

	e1000e_reset ( adapter );

	e1000e_free_tx_resources ( adapter );
	e1000e_free_rx_resources ( adapter );
}
Ejemplo n.º 7
0
Archivo: ethtool.c Proyecto: A-K/linux
static int e1000_set_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;

	/*
	 * When SoL/IDER sessions are active, autoneg/speed/duplex
	 * cannot be changed
	 */
	if (hw->phy.ops.check_reset_block &&
	    hw->phy.ops.check_reset_block(hw)) {
		e_err("Cannot change link characteristics when SoL/IDER is active.\n");
		return -EINVAL;
	}

	/*
	 * MDI setting is only allowed when autoneg enabled because
	 * some hardware doesn't allow MDI setting when speed or
	 * duplex is forced.
	 */
	if (ecmd->eth_tp_mdix_ctrl) {
		if (hw->phy.media_type != e1000_media_type_copper)
			return -EOPNOTSUPP;

		if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
		    (ecmd->autoneg != AUTONEG_ENABLE)) {
			e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
			return -EINVAL;
		}
	}

	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
		usleep_range(1000, 2000);

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		hw->mac.autoneg = 1;
		if (hw->phy.media_type == e1000_media_type_fiber)
			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
						     ADVERTISED_FIBRE |
						     ADVERTISED_Autoneg;
		else
			hw->phy.autoneg_advertised = ecmd->advertising |
						     ADVERTISED_TP |
						     ADVERTISED_Autoneg;
		ecmd->advertising = hw->phy.autoneg_advertised;
		if (adapter->fc_autoneg)
			hw->fc.requested_mode = e1000_fc_default;
	} else {
		u32 speed = ethtool_cmd_speed(ecmd);
		/* calling this overrides forced MDI setting */
		if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
			clear_bit(__E1000_RESETTING, &adapter->state);
			return -EINVAL;
		}
	}

	/* MDI-X => 2; MDI => 1; Auto => 3 */
	if (ecmd->eth_tp_mdix_ctrl) {
		/*
		 * fix up the value for auto (3 => 0) as zero is mapped
		 * internally to auto
		 */
		if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
			hw->phy.mdix = AUTO_ALL_MODES;
		else
			hw->phy.mdix = ecmd->eth_tp_mdix_ctrl;
	}

	/* reset the link */

	if (netif_running(adapter->netdev)) {
		e1000e_down(adapter);
		e1000e_up(adapter);
	} else
		e1000e_reset(adapter);

	clear_bit(__E1000_RESETTING, &adapter->state);
	return 0;
}
Ejemplo n.º 8
0
/**
 * e1000_probe - Initial configuration of e1000 NIC
 *
 * @v pci	PCI device
 * @v id	PCI IDs
 *
 * @ret rc	Return status code
 **/
int e1000e_probe ( struct pci_device *pdev,
	      const struct pci_device_id *ent)
{
	int i, err;
	struct net_device *netdev;
	struct e1000_adapter *adapter;
	unsigned long mmio_start, mmio_len;
	unsigned long flash_start, flash_len;
	struct e1000_hw *hw;
	const struct e1000_info *ei = e1000_info_tbl[ent->driver_data];

	DBGP ( "e1000_probe\n" );

	err = -ENOMEM;

	/* Allocate net device ( also allocates memory for netdev->priv
	   and makes netdev-priv point to it ) */
	netdev = alloc_etherdev ( sizeof ( struct e1000_adapter ) );
	if ( ! netdev ) {
                DBG ( "err_alloc_etherdev\n" );
		goto err_alloc_etherdev;
        }

	/* Associate e1000-specific network operations operations with
	 * generic network device layer */
	netdev_init ( netdev, &e1000e_operations );

	/* Associate this network device with given PCI device */
	pci_set_drvdata ( pdev, netdev );
	netdev->dev = &pdev->dev;

	/* Initialize driver private storage */
	adapter = netdev_priv ( netdev );
	memset ( adapter, 0, ( sizeof ( *adapter ) ) );

	adapter->pdev	    = pdev;

	adapter->ioaddr	    = pdev->ioaddr;
	adapter->hw.io_base = pdev->ioaddr;

	hw		    = &adapter->hw;
	hw->device_id	    = pdev->device;

	adapter->irqno	    = pdev->irq;
	adapter->netdev	    = netdev;
	adapter->hw.back    = adapter;

	adapter->ei	    = ei;
	adapter->pba	    = ei->pba;
	adapter->flags	    = ei->flags;
	adapter->flags2	    = ei->flags2;

	adapter->hw.adapter  = adapter;
	adapter->hw.mac.type = ei->mac;
	adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;

	adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC;
	adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC;

	/* Fix up PCI device */
	adjust_pci_device ( pdev );

	err = -EIO;

	mmio_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_0 );
	mmio_len   = pci_bar_size  ( pdev, PCI_BASE_ADDRESS_0 );

	DBG ( "mmio_start: %#08lx\n", mmio_start );
	DBG ( "mmio_len: %#08lx\n", mmio_len );

	adapter->hw.hw_addr = ioremap ( mmio_start, mmio_len );
	DBG ( "adapter->hw.hw_addr: %p\n", adapter->hw.hw_addr );

	if ( ! adapter->hw.hw_addr ) {
                DBG ( "err_ioremap\n" );
		goto err_ioremap;
        }

	/* Flash BAR mapping depends on mac_type */
	if ( ( adapter->flags & FLAG_HAS_FLASH) && ( pdev->ioaddr ) ) {
		flash_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_1 );
		flash_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_1 );
		adapter->hw.flash_address = ioremap ( flash_start, flash_len );
		if ( ! adapter->hw.flash_address ) {
                        DBG ( "err_flashmap\n" );
			goto err_flashmap;
		}
	}

	/* setup adapter struct */
	err = e1000e_sw_init ( adapter );
	if (err) {
                DBG ( "err_sw_init\n" );
		goto err_sw_init;
        }

	if (ei->get_variants) {
		err = ei->get_variants(adapter);
		if (err) {
                        DBG ( "err_hw_initr\n" );
			goto err_hw_init;
                }
	}

	/* Copper options */
	if (adapter->hw.phy.media_type == e1000_media_type_copper) {
		adapter->hw.phy.mdix = AUTO_ALL_MODES;
		adapter->hw.phy.disable_polarity_correction = 0;
		adapter->hw.phy.ms_type = e1000_ms_hw_default;
	}

	DBG ( "adapter->hw.mac.type: %#08x\n", adapter->hw.mac.type );

	/* Force auto-negotiation */
	adapter->hw.mac.autoneg = 1;
	adapter->fc_autoneg = 1;
	adapter->hw.phy.autoneg_wait_to_complete = true;
	adapter->hw.mac.adaptive_ifs = true;
	adapter->hw.fc.requested_mode = e1000_fc_default;
	adapter->hw.fc.current_mode = e1000_fc_default;

	/*
	 * before reading the NVM, reset the controller to
	 * put the device in a known good starting state
	 */
	adapter->hw.mac.ops.reset_hw(&adapter->hw);

	/*
	 * systems with ASPM and others may see the checksum fail on the first
	 * attempt. Let's give it a few tries
	 */
	for (i = 0;; i++) {
		if (e1000e_validate_nvm_checksum(&adapter->hw) >= 0)
			break;
		if (i == 2) {
			DBG("The NVM Checksum Is Not Valid\n");
			err = -EIO;
			goto err_eeprom;
		}
	}

	/* copy the MAC address out of the EEPROM */
	if ( e1000e_read_mac_addr ( &adapter->hw ) )
		DBG ( "EEPROM Read Error\n" );

	memcpy ( netdev->hw_addr, adapter->hw.mac.perm_addr, ETH_ALEN );

	/* reset the hardware with the new settings */
	e1000e_reset ( adapter );

	/* Mark as link up; we don't yet handle link state */
	netdev_link_up ( netdev );

	if ( ( err = register_netdev ( netdev ) ) != 0) {
                DBG ( "err_register\n" );
		goto err_register;
        }

	for (i = 0; i < 6; i++)
		DBG ("%02x%s", netdev->ll_addr[i], i == 5 ? "\n" : ":");

	DBG ( "e1000e_probe succeeded!\n" );

	/* No errors, return success */
	return 0;

/* Error return paths */
err_register:
err_hw_init:
err_eeprom:
err_flashmap:
	if (!e1000e_check_reset_block(&adapter->hw))
		e1000e_phy_hw_reset(&adapter->hw);
	if (adapter->hw.flash_address)
		iounmap(adapter->hw.flash_address);
err_sw_init:
	iounmap ( adapter->hw.hw_addr );
err_ioremap:
	netdev_put ( netdev );
err_alloc_etherdev:
	return err;
}