return 0;
}
+static int
+e1000_ethtool_gpause(struct e1000_adapter *adapter,
+ struct ethtool_pauseparam *epause)
+{
+ struct e1000_hw *hw = &adapter->hw;
+
+ epause->autoneg =
+ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+ if(hw->fc == e1000_fc_rx_pause)
+ epause->rx_pause = 1;
+ else if(hw->fc == e1000_fc_tx_pause)
+ epause->tx_pause = 1;
+ else if(hw->fc == e1000_fc_full) {
+ epause->rx_pause = 1;
+ epause->tx_pause = 1;
+ }
+
+ return 0;
+}
+
+static int
+e1000_ethtool_spause(struct e1000_adapter *adapter,
+ struct ethtool_pauseparam *epause)
+{
+ struct e1000_hw *hw = &adapter->hw;
+
+ adapter->fc_autoneg = epause->autoneg;
+
+ if(epause->rx_pause && epause->tx_pause)
+ hw->fc = e1000_fc_full;
+ else if(epause->rx_pause && !epause->tx_pause)
+ hw->fc = e1000_fc_rx_pause;
+ else if(!epause->rx_pause && epause->tx_pause)
+ hw->fc = e1000_fc_tx_pause;
+ else if(!epause->rx_pause && !epause->tx_pause)
+ hw->fc = e1000_fc_none;
+
+ hw->original_fc = hw->fc;
+
+ if(netif_running(adapter->netdev)) {
+ e1000_down(adapter);
+ e1000_up(adapter);
+ } else
+ e1000_reset(adapter);
+
+ return 0;
+}
+
static void
e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
struct ethtool_drvinfo *drvinfo)
addr += offsetof(struct ethtool_eeprom, data);
return e1000_ethtool_seeprom(adapter, &eeprom, addr);
}
+ case ETHTOOL_GPAUSEPARAM: {
+ struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM};
+ e1000_ethtool_gpause(adapter, &epause);
+ if(copy_to_user(addr, &epause, sizeof(epause)))
+ return -EFAULT;
+ return 0;
+ }
+ case ETHTOOL_SPAUSEPARAM: {
+ struct ethtool_pauseparam epause;
+ if(copy_from_user(&epause, addr, sizeof(epause)))
+ return -EFAULT;
+ return e1000_ethtool_spause(adapter, &epause);
+ }
case ETHTOOL_GSTATS: {
struct {
struct ethtool_stats eth_stats;
static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);
static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw);
-static int32_t e1000_force_mac_fc(struct e1000_hw *hw);
static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count);
* by the PHY rather than the MAC. Software must also configure these
* bits when link is forced on a fiber connection.
*****************************************************************************/
-static int32_t
+int32_t
e1000_force_mac_fc(struct e1000_hw *hw)
{
uint32_t ctrl;
ctrl &= (~E1000_CTRL_TFCE);
E1000_WRITE_REG(hw, CTRL, ctrl);
- return 0;
+ return E1000_SUCCESS;
}
/******************************************************************************
* Valid Range: 0, 1
* - 0 - disables all checksum offload
* - 1 - enables receive IP/TCP/UDP checksum offload
- * on 82543 based NICs
+ * on 82543 and newer -based NICs
*
* Default Value: 1
*/
switch (speed + dplx) {
case 0:
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
printk(KERN_INFO
"Speed and duplex autonegotiation enabled\n");
case HALF_DUPLEX:
printk(KERN_INFO "Half Duplex specified without Speed\n");
printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
ADVERTISE_100_HALF;
break;
case FULL_DUPLEX:
printk(KERN_INFO "Full Duplex specified without Speed\n");
printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
ADVERTISE_100_FULL |
ADVERTISE_1000_FULL;
case SPEED_10:
printk(KERN_INFO "10 Mbps Speed specified without Duplex\n");
printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
ADVERTISE_10_FULL;
break;
case SPEED_10 + HALF_DUPLEX:
printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n");
- adapter->hw.autoneg = 0;
+ adapter->hw.autoneg = adapter->fc_autoneg = 0;
adapter->hw.forced_speed_duplex = e1000_10_half;
adapter->hw.autoneg_advertised = 0;
break;
case SPEED_10 + FULL_DUPLEX:
printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n");
- adapter->hw.autoneg = 0;
+ adapter->hw.autoneg = adapter->fc_autoneg = 0;
adapter->hw.forced_speed_duplex = e1000_10_full;
adapter->hw.autoneg_advertised = 0;
break;
case SPEED_100:
printk(KERN_INFO "100 Mbps Speed specified without Duplex\n");
printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
ADVERTISE_100_FULL;
break;
case SPEED_100 + HALF_DUPLEX:
printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n");
- adapter->hw.autoneg = 0;
+ adapter->hw.autoneg = adapter->fc_autoneg = 0;
adapter->hw.forced_speed_duplex = e1000_100_half;
adapter->hw.autoneg_advertised = 0;
break;
case SPEED_100 + FULL_DUPLEX:
printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n");
- adapter->hw.autoneg = 0;
+ adapter->hw.autoneg = adapter->fc_autoneg = 0;
adapter->hw.forced_speed_duplex = e1000_100_full;
adapter->hw.autoneg_advertised = 0;
break;
printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n");
printk(KERN_INFO
"Using Autonegotiation at 1000 Mbps Full Duplex only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
break;
case SPEED_1000 + HALF_DUPLEX:
printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n");
printk(KERN_INFO
"Using Autonegotiation at 1000 Mbps Full Duplex only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
break;
case SPEED_1000 + FULL_DUPLEX:
printk(KERN_INFO
"Using Autonegotiation at 1000 Mbps Full Duplex only\n");
- adapter->hw.autoneg = 1;
+ adapter->hw.autoneg = adapter->fc_autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
break;
default: