summaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000/e1000_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-rw-r--r--drivers/net/e1000/e1000_main.c111
1 files changed, 68 insertions, 43 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 137226d..cb7f051 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -29,6 +29,8 @@
#include "e1000.h"
/* Change Log
+ * 6.0.58 4/20/05
+ * o Accepted ethtool cleanup patch from Stephen Hemminger
* 6.0.44+ 2/15/05
* o applied Anton's patch to resolve tx hang in hardware
* o Applied Andrew Mortons patch - e1000 stops working after resume
@@ -41,9 +43,9 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.0.54-k2"DRIVERNAPI
+#define DRV_VERSION "6.0.60-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
-char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
+char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
*
@@ -517,7 +519,7 @@ e1000_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
- adapter = netdev->priv;
+ adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->hw.back = adapter;
@@ -738,7 +740,7 @@ static void __devexit
e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t manc, swsm;
flush_scheduled_work();
@@ -871,7 +873,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
static int
e1000_open(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
int err;
/* allocate transmit descriptors */
@@ -919,7 +921,7 @@ err_setup_tx:
static int
e1000_close(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_down(adapter);
@@ -1599,7 +1601,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
static int
e1000_set_mac(struct net_device *netdev, void *p)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
if(!is_valid_ether_addr(addr->sa_data))
@@ -1634,7 +1636,7 @@ e1000_set_mac(struct net_device *netdev, void *p)
static void
e1000_set_multi(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
unsigned long flags;
@@ -2213,7 +2215,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
unsigned int tx_flags = 0;
@@ -2344,7 +2346,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
static void
e1000_tx_timeout(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task);
@@ -2353,7 +2355,7 @@ e1000_tx_timeout(struct net_device *netdev)
static void
e1000_tx_timeout_task(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_down(adapter);
e1000_up(adapter);
@@ -2370,7 +2372,7 @@ e1000_tx_timeout_task(struct net_device *netdev)
static struct net_device_stats *
e1000_get_stats(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_update_stats(adapter);
return &adapter->net_stats;
@@ -2387,7 +2389,7 @@ e1000_get_stats(struct net_device *netdev)
static int
e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
@@ -2598,7 +2600,7 @@ static irqreturn_t
e1000_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = data;
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
uint32_t icr = E1000_READ_REG(hw, ICR);
#ifndef CONFIG_E1000_NAPI
@@ -2661,7 +2663,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
static int
e1000_clean(struct net_device *netdev, int *budget)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
int work_to_do = min(*budget, netdev->quota);
int tx_cleaned;
int work_done = 0;
@@ -2672,8 +2674,8 @@ e1000_clean(struct net_device *netdev, int *budget)
*budget -= work_done;
netdev->quota -= work_done;
- /* If no Tx and no Rx work done, exit the polling mode */
if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
+ /* If no Tx and not enough Rx work done, exit the polling mode */
netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
@@ -2769,13 +2771,13 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
i = tx_ring->next_to_clean;
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
- DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n"
+ DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
" TDH <%x>\n"
" TDT <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%llx>\n"
+ " dma <%zx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
@@ -2994,7 +2996,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- staterr = rx_desc->wb.middle.status_error;
+ staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
while(staterr & E1000_RXD_STAT_DD) {
buffer_info = &rx_ring->buffer_info[i];
@@ -3065,16 +3067,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan &
- E1000_RXD_SPC_VLAN_MASK));
+ le16_to_cpu(rx_desc->wb.middle.vlan) &
+ E1000_RXD_SPC_VLAN_MASK);
} else {
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan &
- E1000_RXD_SPC_VLAN_MASK));
+ le16_to_cpu(rx_desc->wb.middle.vlan) &
+ E1000_RXD_SPC_VLAN_MASK);
} else {
netif_rx(skb);
}
@@ -3087,7 +3089,7 @@ next_desc:
if(unlikely(++i == rx_ring->count)) i = 0;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- staterr = rx_desc->wb.middle.status_error;
+ staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
adapter->alloc_rx_buf(adapter);
@@ -3371,11 +3373,12 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
static int
e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
struct mii_ioctl_data *data = if_mii(ifr);
int retval;
uint16_t mii_reg;
uint16_t spddplx;
+ unsigned long flags;
if(adapter->hw.media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
@@ -3385,22 +3388,29 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
data->phy_id = adapter->hw.phy_addr;
break;
case SIOCGMIIREG:
- if (!capable(CAP_NET_ADMIN))
+ if(!capable(CAP_NET_ADMIN))
return -EPERM;
- if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
- &data->val_out))
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ &data->val_out)) {
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
+ }
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
+ if(!capable(CAP_NET_ADMIN))
return -EPERM;
- if (data->reg_num & ~(0x1F))
+ if(data->reg_num & ~(0x1F))
return -EFAULT;
mii_reg = data->val_in;
- if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
- mii_reg))
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ if(e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ mii_reg)) {
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
- if (adapter->hw.phy_type == e1000_phy_m88) {
+ }
+ if(adapter->hw.phy_type == e1000_phy_m88) {
switch (data->reg_num) {
case PHY_CTRL:
if(mii_reg & MII_CR_POWER_DOWN)
@@ -3420,8 +3430,12 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
HALF_DUPLEX;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if(retval)
+ if(retval) {
+ spin_unlock_irqrestore(
+ &adapter->stats_lock,
+ flags);
return retval;
+ }
}
if(netif_running(adapter->netdev)) {
e1000_down(adapter);
@@ -3431,8 +3445,11 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if (e1000_phy_reset(&adapter->hw))
+ if(e1000_phy_reset(&adapter->hw)) {
+ spin_unlock_irqrestore(
+ &adapter->stats_lock, flags);
return -EIO;
+ }
break;
}
} else {
@@ -3448,6 +3465,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
}
}
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
default:
return -EOPNOTSUPP;
@@ -3504,7 +3522,7 @@ e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
static void
e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t ctrl, rctl;
e1000_irq_disable(adapter);
@@ -3544,7 +3562,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
static void
e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
if((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
@@ -3560,7 +3578,7 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
static void
e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
e1000_irq_disable(adapter);
@@ -3601,6 +3619,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
{
adapter->hw.autoneg = 0;
+ /* Fiber NICs only allow 1000 gbps Full duplex */
+ if((adapter->hw.media_type == e1000_media_type_fiber) &&
+ spddplx != (SPEED_1000 + DUPLEX_FULL)) {
+ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
+ return -EINVAL;
+ }
+
switch(spddplx) {
case SPEED_10 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_10_half;
@@ -3647,7 +3672,7 @@ static int
e1000_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
uint32_t wufc = adapter->wol;
@@ -3740,12 +3765,12 @@ static int
e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev->priv;
- uint32_t manc, ret, swsm;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ uint32_t manc, ret_val, swsm;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
- ret = pci_enable_device(pdev);
+ ret_val = pci_enable_device(pdev);
pci_set_master(pdev);
pci_enable_wake(pdev, 3, 0);
@@ -3788,7 +3813,7 @@ e1000_resume(struct pci_dev *pdev)
static void
e1000_netpoll(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
enable_irq(adapter->pdev->irq);
OpenPOWER on IntegriCloud