* cb_to_use is the next CB to use for queuing a command; cb_to_clean
* is the next CB to check for completion; cb_to_send is the first
* CB to start on in case of a previous failure to resume. CB clean
- * up happens in interrupt context in response to a CU interrupt, or
- * in dev->poll in the case where NAPI is enabled. cbs_avail keeps
- * track of number of free CB resources available.
+ * up happens in interrupt context in response to a CU interrupt.
+ * cbs_avail keeps track of number of free CB resources available.
*
* Hardware padding of short packets to minimum packet size is
* enabled. 82557 pads with 7Eh, while the later controllers pad
* replacement RFDs cannot be allocated, or the RU goes non-active,
* the RU must be restarted. Frame arrival generates an interrupt,
* and Rx indication and re-allocation happen in the same context,
- * therefore no locking is required. If NAPI is enabled, this work
- * happens in dev->poll. A software-generated interrupt is gen-
- * erated from the watchdog to recover from a failed allocation
+ * therefore no locking is required. A software-generated interrupt
+ * is generated from the watchdog to recover from a failed allocation
* senario where all Rx resources have been indicated and none re-
* placed.
*
* supported. Tx Scatter/Gather is not supported. Jumbo Frames is
* not supported (hardware limitation).
*
- * NAPI support is enabled with CONFIG_E100_NAPI.
- *
* MagicPacket(tm) WoL support is enabled/disabled via ethtool.
*
* Thanks to JC (jchapman@katalix.com) for helping with
#define DRV_NAME "e100"
-#define DRV_VERSION "3.0.18"
+#define DRV_EXT "-NAPI"
+#define DRV_VERSION "3.0.27-k2"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation"
#define PFX DRV_NAME ": "
INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
+ INTEL_8255X_ETHERNET_DEVICE(0x1056, 5),
+ INTEL_8255X_ETHERNET_DEVICE(0x1057, 5),
INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
phy_nsc_tx = 0x5C002000,
phy_82562_et = 0x033002A8,
phy_82562_em = 0x032002A8,
+ phy_82562_ek = 0x031002A8,
phy_82562_eh = 0x017002A8,
phy_unknown = 0xFFFFFFFF,
};
};
enum eeprom_offsets {
+ eeprom_cnfg_mdix = 0x03,
eeprom_id = 0x0A,
eeprom_config_asf = 0x0D,
eeprom_smbus_addr = 0x90,
};
+enum eeprom_cnfg_mdix {
+ eeprom_mdix_enabled = 0x0080,
+};
+
enum eeprom_id {
eeprom_id_wol = 0x0020,
};
};
enum cb_command {
+ cb_nop = 0x0000,
cb_iaaddr = 0x0001,
cb_config = 0x0002,
cb_multi = 0x0003,
cb_tx = 0x0004,
+ cb_ucode = 0x0005,
cb_dump = 0x0006,
cb_tx_sf = 0x0008,
cb_cid = 0x1f00,
};
/* Important: keep total struct u32-aligned */
+#define UCODE_SIZE 134
struct cb {
u16 status;
u16 command;
u32 link;
union {
u8 iaaddr[ETH_ALEN];
+ u32 ucode[UCODE_SIZE];
struct config config;
struct multi multi;
struct {
u32 rx_fc_pause;
u32 rx_fc_unsupported;
u32 rx_tco_frames;
+ u32 rx_over_length_errors;
u8 rev_id;
u16 leds;
c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
}
+static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+ int i;
+ static const u32 ucode[UCODE_SIZE] = {
+ /* NFS packets are misinterpreted as TCO packets and
+ * incorrectly routed to the BMC over SMBus. This
+ * microcode patch checks the fragmented IP bit in the
+ * NFS/UDP header to distinguish between NFS and TCO. */
+ 0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
+ 0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
+ 0x00906EFD, 0x00900EFD, 0x00E00EF8,
+ };
+
+ if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
+ for(i = 0; i < UCODE_SIZE; i++)
+ cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+ cb->command = cpu_to_le16(cb_ucode);
+ } else
+ cb->command = cpu_to_le16(cb_nop);
+}
+
static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
}
- if(nic->mac >= mac_82550_D102)
+ if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
+ (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
+ (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)))
/* enable/disable MDI/MDI-X auto-switching */
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
return err;
if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
return err;
+ if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+ return err;
if((err = e100_exec_cb(nic, NULL, e100_configure)))
return err;
if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
le32_to_cpu(s->tx_lost_crs);
ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
- ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors);
+ ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
+ nic->rx_over_length_errors;
ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
+ ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
le32_to_cpu(s->rx_alignment_errors) +
dev_kfree_skb_any(skb);
} else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
- nic->net_stats.rx_over_errors++;
+ nic->rx_over_length_errors++;
nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else {
nic->net_stats.rx_packets++;
nic->net_stats.rx_bytes += actual_size;
nic->netdev->last_rx = jiffies;
-#ifdef CONFIG_E100_NAPI
netif_receive_skb(skb);
-#else
- netif_rx(skb);
-#endif
if(work_done)
(*work_done)++;
}
if(stat_ack & stat_ack_rnr)
nic->ru_running = 0;
-#ifdef CONFIG_E100_NAPI
e100_disable_irq(nic);
netif_rx_schedule(netdev);
-#else
- if(stat_ack & stat_ack_rx)
- e100_rx_clean(nic, NULL, 0);
- if(stat_ack & stat_ack_tx)
- e100_tx_clean(nic);
-#endif
return IRQ_HANDLED;
}
-#ifdef CONFIG_E100_NAPI
static int e100_poll(struct net_device *netdev, int *budget)
{
struct nic *nic = netdev_priv(netdev);
return 1;
}
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
static void e100_netpoll(struct net_device *netdev)
static int e100_asf(struct nic *nic)
{
/* ASF can be enabled from eeprom */
- return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) &&
+ return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
(nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
!(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
static void e100_diag_test(struct net_device *netdev,
struct ethtool_test *test, u64 *data)
{
+ struct ethtool_cmd cmd;
struct nic *nic = netdev_priv(netdev);
- int i;
+ int i, err;
memset(data, 0, E100_TEST_LEN * sizeof(u64));
data[0] = !mii_link_ok(&nic->mii);
data[1] = e100_eeprom_load(nic);
if(test->flags & ETH_TEST_FL_OFFLINE) {
+
+ /* save speed, duplex & autoneg settings */
+ err = mii_ethtool_gset(&nic->mii, &cmd);
+
if(netif_running(netdev))
e100_down(nic);
data[2] = e100_self_test(nic);
data[3] = e100_loopback_test(nic, lb_mac);
data[4] = e100_loopback_test(nic, lb_phy);
+
+ /* restore speed, duplex & autoneg settings */
+ err = mii_ethtool_sset(&nic->mii, &cmd);
+
if(netif_running(netdev))
e100_up(nic);
}
SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
netdev->tx_timeout = e100_tx_timeout;
netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
-#ifdef CONFIG_E100_NAPI
netdev->poll = e100_poll;
netdev->weight = E100_NAPI_WEIGHT;
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = e100_netpoll;
#endif