aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-08 01:09:19 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-08 01:09:19 -0800
commitc994ae1766652f0c65dcd2e763355c80c3b793d0 (patch)
tree56c605a2328d8702cf32924ed54bcc43f110dd06 /drivers
parent4827352550499ffaa6ae026f93167e1b46205e69 (diff)
parent7667f5e43d00ee7d15e9f781c27815af0ae06a26 (diff)
downloadhistory-c994ae1766652f0c65dcd2e763355c80c3b793d0.tar.gz
Merge bk://gkernel.bkbits.net/net-drivers-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/3c509.c19
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/e100.c19
-rw-r--r--drivers/net/e1000/e1000_ethtool.c68
-rw-r--r--drivers/net/e1000/e1000_hw.c125
-rw-r--r--drivers/net/e1000/e1000_hw.h8
-rw-r--r--drivers/net/e1000/e1000_main.c220
-rw-r--r--drivers/net/e1000/e1000_osdep.h9
-rw-r--r--drivers/net/e1000/e1000_param.c8
-rw-r--r--drivers/net/forcedeth.c305
-rw-r--r--drivers/net/r8169.c100
-rw-r--r--drivers/net/s2io.h2
-rw-r--r--drivers/net/tulip/media.c37
-rw-r--r--drivers/net/tulip/timer.c1
-rw-r--r--drivers/net/tulip/tulip.h8
-rw-r--r--drivers/net/tulip/tulip_core.c40
-rw-r--r--drivers/net/tulip/xircom_tulip_cb.c19
-rw-r--r--drivers/net/tun.c151
-rw-r--r--drivers/net/via-rhine.c2
-rw-r--r--drivers/net/via-velocity.c6
20 files changed, 862 insertions, 287 deletions
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index b346be77486d54..d474ba62382625 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -209,6 +209,9 @@ static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data);
#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
static int el3_device_remove (struct device *device);
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void el3_poll_controller(struct net_device *dev);
+#endif
#ifdef CONFIG_EISA
struct eisa_device_id el3_eisa_ids[] = {
@@ -321,6 +324,9 @@ static int __init el3_common_init(struct net_device *dev)
dev->set_multicast_list = &set_multicast_list;
dev->tx_timeout = el3_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = el3_poll_controller;
+#endif
SET_ETHTOOL_OPS(dev, &ethtool_ops);
err = register_netdev(dev);
@@ -999,6 +1005,19 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void el3_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ el3_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
static struct net_device_stats *
el3_get_stats(struct net_device *dev)
{
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index a71423c751e2f9..80ebac6d2c9e87 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -398,6 +398,8 @@ static void cp_clean_rings (struct cp_private *cp);
static struct pci_device_id cp_pci_tbl[] = {
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+ { PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{ },
};
MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 17eecc72d791e7..d9574c63900a80 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -155,7 +155,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.2.3-k2"DRV_EXT
+#define DRV_VERSION "3.3.6-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 ": "
@@ -201,6 +201,7 @@ static struct pci_device_id e100_id_table[] = {
INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
INTEL_8255X_ETHERNET_DEVICE(0x1056, 5),
INTEL_8255X_ETHERNET_DEVICE(0x1057, 5),
+ INTEL_8255X_ETHERNET_DEVICE(0x1059, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
@@ -209,7 +210,6 @@ static struct pci_device_id e100_id_table[] = {
INTEL_8255X_ETHERNET_DEVICE(0x1069, 6),
INTEL_8255X_ETHERNET_DEVICE(0x106A, 6),
INTEL_8255X_ETHERNET_DEVICE(0x106B, 6),
- INTEL_8255X_ETHERNET_DEVICE(0x1059, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
@@ -621,8 +621,7 @@ static int e100_self_test(struct nic *nic)
writel(selftest | dma_addr, &nic->csr->port);
e100_write_flush(nic);
/* Wait 10 msec for self-test to complete */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 100 + 1);
+ msleep(10);
/* Interrupts are enabled after self-test */
e100_disable_irq(nic);
@@ -670,8 +669,7 @@ static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data)
e100_write_flush(nic); udelay(4);
}
/* Wait 10 msec for cmd to complete */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 100 + 1);
+ msleep(10);
/* Chip deselect */
writeb(0, &nic->csr->eeprom_ctrl_lo);
@@ -1760,8 +1758,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
memset(skb->data, 0xFF, ETH_DATA_LEN);
e100_xmit_frame(skb, nic->netdev);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 100 + 1);
+ msleep(10);
if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
skb->data, ETH_DATA_LEN))
@@ -1847,8 +1844,7 @@ static void e100_get_regs(struct net_device *netdev,
mdio_read(netdev, nic->mii.phy_id, i);
memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
e100_exec_cb(nic, NULL, e100_dump);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 100 + 1);
+ msleep(10);
memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
sizeof(nic->mem->dump_buf));
}
@@ -2027,8 +2023,7 @@ static int e100_phys_id(struct net_device *netdev, u32 data)
if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
mod_timer(&nic->blink_timer, jiffies);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(data * HZ);
+ msleep_interruptible(data * 1000);
del_timer_sync(&nic->blink_timer);
mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0);
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index cc50e4d5d46325..9b40cf1c2c9c89 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -776,7 +776,7 @@ static int
e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
{
struct net_device *netdev = adapter->netdev;
- uint32_t icr, mask, i=0, shared_int = TRUE;
+ uint32_t mask, i=0, shared_int = TRUE;
uint32_t irq = adapter->pdev->irq;
*data = 0;
@@ -784,7 +784,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
/* Hook up test interrupt handler just for this test */
if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
shared_int = FALSE;
- } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)){
+ } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+ netdev->name, netdev)){
*data = 1;
return -1;
}
@@ -793,21 +794,6 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
msec_delay(10);
- /* Interrupts are disabled, so read interrupt cause
- * register (icr) twice to verify that there are no interrupts
- * pending. icr is clear on read.
- */
- icr = E1000_READ_REG(&adapter->hw, ICR);
- icr = E1000_READ_REG(&adapter->hw, ICR);
-
- if(icr != 0) {
- /* if icr is non-zero, there is no point
- * running other interrupt tests.
- */
- *data = 2;
- i = 10;
- }
-
/* Test each interrupt */
for(; i < 10; i++) {
@@ -856,8 +842,10 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
- E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
+ E1000_WRITE_REG(&adapter->hw, IMC,
+ (~mask & 0x00007FFF));
+ E1000_WRITE_REG(&adapter->hw, ICS,
+ (~mask & 0x00007FFF));
msec_delay(10);
if(adapter->test_icr) {
@@ -1336,10 +1324,17 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
msec_delay(200);
- pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[0].dma,
- rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);
+ i = 0;
+ do {
+ pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[i].dma,
+ rxdr->buffer_info[i].length,
+ PCI_DMA_FROMDEVICE);
+
+ if (!e1000_check_lbtest_frame(rxdr->buffer_info[i++].skb, 1024))
+ return 0;
+ } while (i < 64);
- return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024);
+ return 13;
}
static int
@@ -1358,10 +1353,27 @@ static int
e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
{
*data = 0;
- e1000_check_for_link(&adapter->hw);
- if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
- *data = 1;
+ if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ int i = 0;
+ adapter->hw.serdes_link_down = TRUE;
+
+ /* on some blade server designs link establishment */
+ /* could take as long as 2-3 minutes. */
+ do {
+ e1000_check_for_link(&adapter->hw);
+ if (adapter->hw.serdes_link_down == FALSE)
+ return *data;
+ msec_delay(20);
+ } while (i++ < 3750);
+
+ *data = 1;
+ } else {
+ e1000_check_for_link(&adapter->hw);
+
+ if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ *data = 1;
+ }
}
return *data;
}
@@ -1490,6 +1502,8 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82543GC_COPPER:
case E1000_DEV_ID_82544EI_FIBER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
+ case E1000_DEV_ID_82545EM_FIBER:
+ case E1000_DEV_ID_82545EM_COPPER:
return wol->wolopts ? -EOPNOTSUPP : 0;
case E1000_DEV_ID_82546EB_FIBER:
@@ -1554,9 +1568,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
e1000_setup_led(&adapter->hw);
mod_timer(&adapter->blink_timer, jiffies);
- set_current_state(TASK_INTERRUPTIBLE);
-
- schedule_timeout(data * HZ);
+ msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
e1000_led_off(&adapter->hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 0c7d458fdfe63e..f140e2c7eab0eb 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -123,16 +123,31 @@ e1000_set_phy_type(struct e1000_hw *hw)
static void
e1000_phy_init_script(struct e1000_hw *hw)
{
+ uint32_t ret_val;
+ uint16_t phy_saved_data;
+
DEBUGFUNC("e1000_phy_init_script");
+
if(hw->phy_init_script) {
msec_delay(20);
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of this routine. */
+ ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ /* Disabled the PHY transmitter */
+ e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ msec_delay(20);
+
e1000_write_phy_reg(hw,0x0000,0x0140);
msec_delay(5);
- if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) {
+ switch(hw->mac_type) {
+ case e1000_82541:
+ case e1000_82547:
e1000_write_phy_reg(hw, 0x1F95, 0x0001);
e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
@@ -150,12 +165,23 @@ e1000_phy_init_script(struct e1000_hw *hw)
e1000_write_phy_reg(hw, 0x1F96, 0x003F);
e1000_write_phy_reg(hw, 0x2010, 0x0008);
- } else {
+ break;
+
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
e1000_write_phy_reg(hw, 0x1F73, 0x0099);
+ break;
+ default:
+ break;
}
e1000_write_phy_reg(hw, 0x0000, 0x3300);
+ msec_delay(20);
+
+ /* Now enable the transmitter */
+ e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
if(hw->mac_type == e1000_82547) {
uint16_t fused, fine, coarse;
@@ -244,6 +270,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546GB_COPPER:
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
+ case E1000_DEV_ID_82546GB_PCIE:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -967,7 +994,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
hw->dsp_config_state = e1000_dsp_config_disabled;
- /* Force MDI for IGP B-0 PHY */
+ /* Force MDI for earlier revs of the IGP PHY */
phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
IGP01E1000_PSCR_FORCE_MDI_MDIX);
hw->mdix = 1;
@@ -2111,7 +2138,7 @@ e1000_check_for_link(struct e1000_hw *hw)
* at gigabit speed, then TBI compatibility is not needed. If we are
* at gigabit speed, we turn on TBI compatibility.
*/
- if(hw->tbi_compatibility_en) {
+ if(hw->tbi_compatibility_en) {
uint16_t speed, duplex;
e1000_get_speed_and_duplex(hw, &speed, &duplex);
if(speed != SPEED_1000) {
@@ -2466,12 +2493,14 @@ e1000_read_phy_reg(struct e1000_hw *hw,
DEBUGFUNC("e1000_read_phy_reg");
+
if(hw->phy_type == e1000_phy_igp &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
- if(ret_val)
+ if(ret_val) {
return ret_val;
+ }
}
ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
@@ -2570,12 +2599,14 @@ e1000_write_phy_reg(struct e1000_hw *hw,
DEBUGFUNC("e1000_write_phy_reg");
+
if(hw->phy_type == e1000_phy_igp &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
- if(ret_val)
+ if(ret_val) {
return ret_val;
+ }
}
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
@@ -3478,7 +3509,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
/* A check for invalid values: offset too large, too many words, and not
* enough words.
*/
- if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
+ if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
(words == 0)) {
DEBUGOUT("\"words\" parameter out of bounds\n");
return -E1000_ERR_EEPROM;
@@ -3626,7 +3657,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
/* A check for invalid values: offset too large, too many words, and not
* enough words.
*/
- if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
+ if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
(words == 0)) {
DEBUGOUT("\"words\" parameter out of bounds\n");
return -E1000_ERR_EEPROM;
@@ -4918,7 +4949,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
boolean_t link_up)
{
int32_t ret_val;
- uint16_t phy_data, speed, duplex, i;
+ uint16_t phy_data, phy_saved_data, speed, duplex, i;
uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
{IGP01E1000_PHY_AGC_PARAM_A,
IGP01E1000_PHY_AGC_PARAM_B,
@@ -4999,6 +5030,21 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
}
} else {
if(hw->dsp_config_state == e1000_dsp_config_activated) {
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of the routines. */
+ ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
+ /* Disable the PHY transmitter */
+ ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ if(ret_val)
+ return ret_val;
+
+ msec_delay(20);
+
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
if(ret_val)
@@ -5021,10 +5067,33 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
if(ret_val)
return ret_val;
+ msec_delay(20);
+
+ /* Now enable the transmitter */
+ ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
hw->dsp_config_state = e1000_dsp_config_enabled;
}
if(hw->ffe_config_state == e1000_ffe_config_active) {
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of the routines. */
+ ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
+ /* Disable the PHY transmitter */
+ ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ if(ret_val)
+ return ret_val;
+
+ msec_delay(20);
+
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
if(ret_val)
@@ -5038,6 +5107,15 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
IGP01E1000_IEEE_RESTART_AUTONEG);
if(ret_val)
return ret_val;
+
+ msec_delay(20);
+
+ /* Now enable the transmitter */
+ ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if(ret_val)
+ return ret_val;
+
hw->ffe_config_state = e1000_ffe_config_enabled;
}
}
@@ -5126,14 +5204,29 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
* Dx states where the power conservation is most important. During
* driver activity we should enable SmartSpeed, so performance is
* maintained. */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
- if(ret_val)
- return ret_val;
+ if (hw->smart_speed == e1000_smart_speed_on) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if(ret_val)
+ return ret_val;
- phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
- if(ret_val)
- return ret_val;
+ phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->smart_speed == e1000_smart_speed_off) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ }
} else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
(hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index b1054cf14980a1..756727eb434abc 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -168,6 +168,12 @@ typedef enum {
} e1000_downshift;
typedef enum {
+ e1000_smart_speed_default = 0,
+ e1000_smart_speed_on,
+ e1000_smart_speed_off
+} e1000_smart_speed;
+
+typedef enum {
e1000_polarity_reversal_enabled = 0,
e1000_polarity_reversal_disabled,
e1000_polarity_reversal_undefined = 0xFF
@@ -361,6 +367,7 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
#define E1000_DEV_ID_82546GB_COPPER 0x1079
#define E1000_DEV_ID_82546GB_FIBER 0x107A
#define E1000_DEV_ID_82546GB_SERDES 0x107B
+#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -1026,6 +1033,7 @@ struct e1000_hw {
uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
boolean_t disable_polarity_correction;
boolean_t speed_downgraded;
+ e1000_smart_speed smart_speed;
e1000_dsp_config dsp_config_state;
boolean_t get_link_status;
boolean_t serdes_link_down;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 92ecad3117ba59..216a5b6eb76a39 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -35,10 +35,19 @@
* - More errlogging support from Jon Mason <jonmason@us.ibm.com>
* - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com>
*
- * 5.3.11 6/4/04
- * - ethtool register dump reads MANC register conditionally.
- *
- * 5.3.10 6/1/04
+ * 5.6.5 11/01/04
+ * - Enabling NETIF_F_SG without checksum offload is illegal -
+ John Mason <jdmason@us.ibm.com>
+ * 5.6.3 10/26/04
+ * - Remove redundant initialization - Jamal Hadi
+ * - Reset buffer_info->dma in tx resource cleanup logic
+ * 5.6.2 10/12/04
+ * - Avoid filling tx_ring completely - shemminger@osdl.org
+ * - Replace schedule_timeout() with msleep()/msleep_interruptible() -
+ * nacc@us.ibm.com
+ * - Sparse cleanup - shemminger@osdl.org
+ * - Fix tx resource cleanup logic
+ * - LLTX support - ak@suse.de and hadi@cyberus.ca
*/
char e1000_driver_name[] = "e1000";
@@ -48,7 +57,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-char e1000_driver_version[] = "5.5.4-k2"DRIVERNAPI;
+char e1000_driver_version[] = "5.6.10.1-k2"DRIVERNAPI;
char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
@@ -90,6 +99,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x107A),
INTEL_E1000_ETHERNET_DEVICE(0x107B),
INTEL_E1000_ETHERNET_DEVICE(0x107C),
+ INTEL_E1000_ETHERNET_DEVICE(0x108A),
/* required last entry */
{0,}
};
@@ -128,8 +138,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
-static void e1000_irq_disable(struct e1000_adapter *adapter);
-static void e1000_irq_enable(struct e1000_adapter *adapter);
static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
#ifdef CONFIG_E1000_NAPI
@@ -146,9 +154,6 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
void set_ethtool_ops(struct net_device *netdev);
static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
-static void e1000_rx_checksum(struct e1000_adapter *adapter,
- struct e1000_rx_desc *rx_desc,
- struct sk_buff *skb);
static void e1000_tx_timeout(struct net_device *dev);
static void e1000_tx_timeout_task(struct net_device *dev);
static void e1000_smartspeed(struct e1000_adapter *adapter);
@@ -242,6 +247,33 @@ e1000_exit_module(void)
module_exit(e1000_exit_module);
+/**
+ * e1000_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+static inline void
+e1000_irq_disable(struct e1000_adapter *adapter)
+{
+ atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ E1000_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+}
+
+/**
+ * e1000_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+
+static inline void
+e1000_irq_enable(struct e1000_adapter *adapter)
+{
+ if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
+ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
+ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+}
int
e1000_up(struct e1000_adapter *adapter)
@@ -475,8 +507,6 @@ e1000_probe(struct pci_dev *pdev,
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- } else {
- netdev->features = NETIF_F_SG;
}
#ifdef NETIF_F_TSO
@@ -1061,6 +1091,24 @@ e1000_free_tx_resources(struct e1000_adapter *adapter)
adapter->tx_ring.desc = NULL;
}
+static inline void
+e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
+ struct e1000_buffer *buffer_info)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ if(buffer_info->dma) {
+ pci_unmap_page(pdev,
+ buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+ if(buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+}
+
/**
* e1000_clean_tx_ring - Free Tx Buffers
* @adapter: board private structure
@@ -1071,7 +1119,6 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
- struct pci_dev *pdev = adapter->pdev;
unsigned long size;
unsigned int i;
@@ -1079,17 +1126,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
for(i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
- if(buffer_info->skb) {
-
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_TODEVICE);
-
- dev_kfree_skb(buffer_info->skb);
-
- buffer_info->skb = NULL;
- }
+ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
}
size = sizeof(struct e1000_buffer) * tx_ring->count;
@@ -1762,7 +1799,6 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int mss = 0;
int count = 0;
unsigned int f;
- nr_frags = skb_shinfo(skb)->nr_frags;
len -= skb->data_len;
if(unlikely(skb->len <= 0)) {
@@ -1811,7 +1847,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
- if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) {
+ if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2)) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_BUSY;
@@ -1844,6 +1880,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies;
+ /* Make sure there is space in the ring for the next send. */
+ if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < MAX_SKB_FRAGS + 2))
+ netif_stop_queue(netdev);
+
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_OK;
}
@@ -1904,9 +1944,9 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
- return -EINVAL;
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
+ return -EINVAL;
}
if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) {
@@ -2074,34 +2114,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
}
/**
- * e1000_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-
-static void
-e1000_irq_disable(struct e1000_adapter *adapter)
-{
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(&adapter->hw, IMC, ~0);
- E1000_WRITE_FLUSH(&adapter->hw);
- synchronize_irq(adapter->pdev->irq);
-}
-
-/**
- * e1000_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-
-static void
-e1000_irq_enable(struct e1000_adapter *adapter)
-{
- if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
- E1000_WRITE_FLUSH(&adapter->hw);
- }
-}
-
-/**
* e1000_intr - Interrupt Handler
* @irq: interrupt number
* @data: pointer to a network interface device structure
@@ -2162,6 +2174,9 @@ e1000_clean(struct net_device *netdev, int *budget)
int tx_cleaned;
int work_done = 0;
+ if (!netif_carrier_ok(netdev))
+ goto quit_polling;
+
tx_cleaned = e1000_clean_tx_irq(adapter);
e1000_clean_rx_irq(adapter, &work_done, work_to_do);
@@ -2171,7 +2186,7 @@ e1000_clean(struct net_device *netdev, int *budget)
/* if no Rx and Tx cleanup work was done, exit the polling mode */
if(!tx_cleaned || (work_done < work_to_do) ||
!netif_running(netdev)) {
- netif_rx_complete(netdev);
+quit_polling: netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
}
@@ -2190,7 +2205,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
unsigned int i, eop;
@@ -2205,19 +2219,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
- if(likely(buffer_info->dma)) {
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
- }
-
- if(buffer_info->skb) {
- dev_kfree_skb_any(buffer_info->skb);
- buffer_info->skb = NULL;
- }
-
+ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->buffer_addr = 0;
tx_desc->lower.data = 0;
tx_desc->upper.data = 0;
@@ -2244,6 +2246,41 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
}
/**
+ * e1000_rx_checksum - Receive Checksum Offload for 82543
+ * @adapter: board private structure
+ * @rx_desc: receive descriptor
+ * @sk_buff: socket buffer with received data
+ **/
+
+static inline void
+e1000_rx_checksum(struct e1000_adapter *adapter,
+ struct e1000_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ /* 82543 or newer only */
+ if(unlikely((adapter->hw.mac_type < e1000_82543) ||
+ /* Ignore Checksum bit is set */
+ (rx_desc->status & E1000_RXD_STAT_IXSM) ||
+ /* TCP Checksum has not been calculated */
+ (!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) {
+ skb->ip_summed = CHECKSUM_NONE;
+ return;
+ }
+
+ /* At this point we know the hardware did the TCP checksum */
+ /* now look at the TCP checksum error bit */
+ if(rx_desc->errors & E1000_RXD_ERR_TCPE) {
+ /* let the stack verify checksum errors */
+ skb->ip_summed = CHECKSUM_NONE;
+ adapter->hw_csum_err++;
+ } else {
+ /* TCP checksum is good */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ adapter->hw_csum_good++;
+ }
+}
+
+/**
* e1000_clean_rx_irq - Send received data up the network stack
* @adapter: board private structure
**/
@@ -2291,7 +2328,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
/* All receives must fit into a single buffer */
E1000_DBG("%s: Receive packet consumed multiple"
- " buffers\n", netdev->name);
+ " buffers\n", netdev->name);
dev_kfree_skb_irq(skb);
goto next_desc;
}
@@ -2376,8 +2413,8 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
buffer_info = &rx_ring->buffer_info[i];
while(!buffer_info->skb) {
-
skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+
if(unlikely(!skb)) {
/* Better luck next round */
break;
@@ -2587,41 +2624,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return E1000_SUCCESS;
}
-/**
- * e1000_rx_checksum - Receive Checksum Offload for 82543
- * @adapter: board private structure
- * @rx_desc: receive descriptor
- * @sk_buff: socket buffer with received data
- **/
-
-static void
-e1000_rx_checksum(struct e1000_adapter *adapter,
- struct e1000_rx_desc *rx_desc,
- struct sk_buff *skb)
-{
- /* 82543 or newer only */
- if(unlikely((adapter->hw.mac_type < e1000_82543) ||
- /* Ignore Checksum bit is set */
- (rx_desc->status & E1000_RXD_STAT_IXSM) ||
- /* TCP Checksum has not been calculated */
- (!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) {
- skb->ip_summed = CHECKSUM_NONE;
- return;
- }
-
- /* At this point we know the hardware did the TCP checksum */
- /* now look at the TCP checksum error bit */
- if(rx_desc->errors & E1000_RXD_ERR_TCPE) {
- /* let the stack verify checksum errors */
- skb->ip_summed = CHECKSUM_NONE;
- adapter->hw_csum_err++;
- } else {
- /* TCP checksum is good */
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- adapter->hw_csum_good++;
- }
-}
-
void
e1000_pci_set_mwi(struct e1000_hw *hw)
{
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 630beaf27e09c8..970c656a517c19 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -42,13 +42,8 @@
#include <linux/sched.h>
#ifndef msec_delay
-#define msec_delay(x) do { if(in_interrupt()) { \
- /* Don't mdelay in interrupt context! */ \
- BUG(); \
- } else { \
- set_current_state(TASK_UNINTERRUPTIBLE); \
- schedule_timeout((x * HZ)/1000 + 2); \
- } } while(0)
+#define msec_delay(x) msleep(x)
+
/* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
* but cannot process phy register reads/writes faster than millisecond
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 038d55958d9408..e914d09fe6f936 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -47,7 +47,7 @@
#define E1000_PARAM(X, desc) \
static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
static int num_##X = 0; \
- module_param_array(X, int, &num_##X, 0); \
+ module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
/* Transmit Descriptor Count
@@ -470,9 +470,6 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
switch(adapter->itr) {
- case -1:
- adapter->itr = 1;
- break;
case 0:
DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
@@ -481,13 +478,14 @@ e1000_check_options(struct e1000_adapter *adapter)
DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
opt.name);
break;
+ case -1:
default:
e1000_validate_option(&adapter->itr, &opt,
adapter);
break;
}
} else {
- adapter->itr = 1;
+ adapter->itr = opt.def;
}
}
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index cb40c184f30307..cda48c5d72a91f 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -79,6 +79,8 @@
* 0.30: 25 Sep 2004: rx checksum support for nf 250 Gb. Add rx reset
* into nv_close, otherwise reenabling for wol can
* cause DMA to kfree'd memory.
+ * 0.31: 14 Nov 2004: ethtool support for getting/setting link
+ * capabilities.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -90,7 +92,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.30"
+#define FORCEDETH_VERSION "0.31"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -210,6 +212,7 @@ enum {
#define NVREG_LINKSPEED_10 1000
#define NVREG_LINKSPEED_100 100
#define NVREG_LINKSPEED_1000 50
+#define NVREG_LINKSPEED_MASK (0xFFF)
NvRegUnknownSetupReg5 = 0x130,
#define NVREG_UNKSETUP5_BIT31 (1<<31)
NvRegUnknownSetupReg3 = 0x13c,
@@ -441,6 +444,8 @@ struct fe_priv {
int in_shutdown;
u32 linkspeed;
int duplex;
+ int autoneg;
+ int fixed_mode;
int phyaddr;
int wolenabled;
unsigned int phy_oui;
@@ -765,50 +770,6 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
return &np->stats;
}
-static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- struct fe_priv *np = get_nvpriv(dev);
- strcpy(info->driver, "forcedeth");
- strcpy(info->version, FORCEDETH_VERSION);
- strcpy(info->bus_info, pci_name(np->pci_dev));
-}
-
-static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
-{
- struct fe_priv *np = get_nvpriv(dev);
- wolinfo->supported = WAKE_MAGIC;
-
- spin_lock_irq(&np->lock);
- if (np->wolenabled)
- wolinfo->wolopts = WAKE_MAGIC;
- spin_unlock_irq(&np->lock);
-}
-
-static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
-{
- struct fe_priv *np = get_nvpriv(dev);
- u8 __iomem *base = get_hwbase(dev);
-
- spin_lock_irq(&np->lock);
- if (wolinfo->wolopts == 0) {
- writel(0, base + NvRegWakeUpFlags);
- np->wolenabled = 0;
- }
- if (wolinfo->wolopts & WAKE_MAGIC) {
- writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
- np->wolenabled = 1;
- }
- spin_unlock_irq(&np->lock);
- return 0;
-}
-
-static struct ethtool_ops ops = {
- .get_drvinfo = nv_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_wol = nv_get_wol,
- .set_wol = nv_set_wol,
-};
-
/*
* nv_alloc_rx: fill rx ring entries.
* Return 1 if the allocations for the skbs failed and the
@@ -1286,6 +1247,25 @@ static int nv_update_linkspeed(struct net_device *dev)
goto set_speed;
}
+ if (np->autoneg == 0) {
+ dprintk(KERN_DEBUG "%s: nv_update_linkspeed: autoneg off, PHY set to 0x%04x.\n",
+ dev->name, np->fixed_mode);
+ if (np->fixed_mode & LPA_100FULL) {
+ newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
+ newdup = 1;
+ } else if (np->fixed_mode & LPA_100HALF) {
+ newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
+ newdup = 0;
+ } else if (np->fixed_mode & LPA_10FULL) {
+ newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+ newdup = 1;
+ } else {
+ newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+ newdup = 0;
+ }
+ retval = 1;
+ goto set_speed;
+ }
/* check auto negotiation is complete */
if (!(mii_status & BMSR_ANEGCOMPLETE)) {
/* still in autonegotiation - configure nic for 10 MBit HD and wait. */
@@ -1303,7 +1283,7 @@ static int nv_update_linkspeed(struct net_device *dev)
if ((control_1000 & ADVERTISE_1000FULL) &&
(status_1000 & LPA_1000FULL)) {
- dprintk(KERN_DEBUG "%s: nv_update_linkspeed: GBit ethernet detected.\n",
+ dprintk(KERN_DEBUG "%s: nv_update_linkspeed: GBit ethernet detected.\n",
dev->name);
newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_1000;
newdup = 1;
@@ -1362,9 +1342,9 @@ set_speed:
phyreg &= ~(PHY_HALF|PHY_100|PHY_1000);
if (np->duplex == 0)
phyreg |= PHY_HALF;
- if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
+ if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_100)
phyreg |= PHY_100;
- else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
+ else if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000)
phyreg |= PHY_1000;
writel(phyreg, base + NvRegPhyInterface);
@@ -1500,6 +1480,227 @@ static void nv_do_nic_poll(unsigned long data)
enable_irq(dev->irq);
}
+static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ strcpy(info->driver, "forcedeth");
+ strcpy(info->version, FORCEDETH_VERSION);
+ strcpy(info->bus_info, pci_name(np->pci_dev));
+}
+
+static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ wolinfo->supported = WAKE_MAGIC;
+
+ spin_lock_irq(&np->lock);
+ if (np->wolenabled)
+ wolinfo->wolopts = WAKE_MAGIC;
+ spin_unlock_irq(&np->lock);
+}
+
+static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+ spin_lock_irq(&np->lock);
+ if (wolinfo->wolopts == 0) {
+ writel(0, base + NvRegWakeUpFlags);
+ np->wolenabled = 0;
+ }
+ if (wolinfo->wolopts & WAKE_MAGIC) {
+ writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
+ np->wolenabled = 1;
+ }
+ spin_unlock_irq(&np->lock);
+ return 0;
+}
+
+static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ int adv;
+
+ spin_lock_irq(&np->lock);
+ ecmd->port = PORT_MII;
+ if (!netif_running(dev)) {
+ /* We do not track link speed / duplex setting if the
+ * interface is disabled. Force a link check */
+ nv_update_linkspeed(dev);
+ }
+ switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
+ case NVREG_LINKSPEED_10:
+ ecmd->speed = SPEED_10;
+ break;
+ case NVREG_LINKSPEED_100:
+ ecmd->speed = SPEED_100;
+ break;
+ case NVREG_LINKSPEED_1000:
+ ecmd->speed = SPEED_1000;
+ break;
+ }
+ ecmd->duplex = DUPLEX_HALF;
+ if (np->duplex)
+ ecmd->duplex = DUPLEX_FULL;
+
+ ecmd->autoneg = np->autoneg;
+
+ ecmd->advertising = ADVERTISED_MII;
+ if (np->autoneg) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+ } else {
+ adv = np->fixed_mode;
+ }
+ if (adv & ADVERTISE_10HALF)
+ ecmd->advertising |= ADVERTISED_10baseT_Half;
+ if (adv & ADVERTISE_10FULL)
+ ecmd->advertising |= ADVERTISED_10baseT_Full;
+ if (adv & ADVERTISE_100HALF)
+ ecmd->advertising |= ADVERTISED_100baseT_Half;
+ if (adv & ADVERTISE_100FULL)
+ ecmd->advertising |= ADVERTISED_100baseT_Full;
+ if (np->autoneg && np->gigabit == PHY_GIGABIT) {
+ adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+ if (adv & ADVERTISE_1000FULL)
+ ecmd->advertising |= ADVERTISED_1000baseT_Full;
+ }
+
+ ecmd->supported = (SUPPORTED_Autoneg |
+ SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_MII);
+ if (np->gigabit == PHY_GIGABIT)
+ ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+ ecmd->phy_address = np->phyaddr;
+ ecmd->transceiver = XCVR_EXTERNAL;
+
+ /* ignore maxtxpkt, maxrxpkt for now */
+ spin_unlock_irq(&np->lock);
+ return 0;
+}
+
+static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct fe_priv *np = netdev_priv(dev);
+
+ if (ecmd->port != PORT_MII)
+ return -EINVAL;
+ if (ecmd->transceiver != XCVR_EXTERNAL)
+ return -EINVAL;
+ if (ecmd->phy_address != np->phyaddr) {
+ /* TODO: support switching between multiple phys. Should be
+ * trivial, but not enabled due to lack of test hardware. */
+ return -EINVAL;
+ }
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ u32 mask;
+
+ mask = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+ if (np->gigabit == PHY_GIGABIT)
+ mask |= ADVERTISED_1000baseT_Full;
+
+ if ((ecmd->advertising & mask) == 0)
+ return -EINVAL;
+
+ } else if (ecmd->autoneg == AUTONEG_DISABLE) {
+ /* Note: autonegotiation disable, speed 1000 intentionally
+ * forbidden - noone should need that. */
+
+ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+ return -EINVAL;
+ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ spin_lock_irq(&np->lock);
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ int adv, bmcr;
+
+ np->autoneg = 1;
+
+ /* advertise only what has been requested */
+ adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (ecmd->advertising & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (ecmd->advertising & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (ecmd->advertising & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (ecmd->advertising & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
+
+ if (np->gigabit == PHY_GIGABIT) {
+ adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+ adv &= ~ADVERTISE_1000FULL;
+ if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+ adv |= ADVERTISE_1000FULL;
+ mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+ }
+
+ bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+
+ } else {
+ int adv, bmcr;
+
+ np->autoneg = 0;
+
+ adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF)
+ adv |= ADVERTISE_10HALF;
+ if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL)
+ adv |= ADVERTISE_10FULL;
+ if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF)
+ adv |= ADVERTISE_100HALF;
+ if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)
+ adv |= ADVERTISE_100FULL;
+ mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
+ np->fixed_mode = adv;
+
+ if (np->gigabit == PHY_GIGABIT) {
+ adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+ adv &= ~ADVERTISE_1000FULL;
+ mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+ }
+
+ bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+ bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX);
+ if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL))
+ bmcr |= BMCR_FULLDPLX;
+ if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL))
+ bmcr |= BMCR_SPEED100;
+ mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+
+ if (netif_running(dev)) {
+ /* Wait a bit and then reconfigure the nic. */
+ udelay(10);
+ nv_linkchange(dev);
+ }
+ }
+ spin_unlock_irq(&np->lock);
+
+ return 0;
+}
+
+static struct ethtool_ops ops = {
+ .get_drvinfo = nv_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_wol = nv_get_wol,
+ .set_wol = nv_set_wol,
+ .get_settings = nv_get_settings,
+ .set_settings = nv_set_settings,
+};
+
static int nv_open(struct net_device *dev)
{
struct fe_priv *np = get_nvpriv(dev);
@@ -1550,9 +1751,6 @@ static int nv_open(struct net_device *dev)
base + NvRegRingSizes);
/* 5) continue setup */
- np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
- np->duplex = 0;
-
writel(np->linkspeed, base + NvRegLinkSpeed);
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
writel(np->desc_ver, base + NvRegTxRxControl);
@@ -1866,6 +2064,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
phy_init(dev);
}
+ /* set default link speed settings */
+ np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
+ np->duplex = 0;
+ np->autoneg = 1;
+
err = register_netdev(dev);
if (err) {
printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index d8a5b70f69c3cd..4923ad730efb35 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -63,7 +63,6 @@ VERSION 1.6LK <2004/04/14>
#define RTL8169_VERSION "1.6LK"
#define MODULENAME "r8169"
-#define RTL8169_DRIVER_NAME MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION
#define PFX MODULENAME ": "
#ifdef RTL8169_DEBUG
@@ -112,7 +111,8 @@ static int multicast_filter_limit = 32;
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
-#define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */
+#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */
+#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
#define R8169_REGS_SIZE 256
@@ -427,6 +427,9 @@ static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
void __iomem *);
+static int rtl8169_change_mtu(struct net_device *netdev, int new_mtu);
+static void rtl8169_down(struct net_device *dev);
+
#ifdef CONFIG_R8169_NAPI
static int rtl8169_poll(struct net_device *dev, int *budget);
#endif
@@ -560,8 +563,8 @@ static void rtl8169_get_drvinfo(struct net_device *dev,
{
struct rtl8169_private *tp = netdev_priv(dev);
- strcpy(info->driver, RTL8169_DRIVER_NAME);
- strcpy(info->version, RTL8169_VERSION );
+ strcpy(info->driver, MODULENAME);
+ strcpy(info->version, RTL8169_VERSION);
strcpy(info->bus_info, pci_name(tp->pci_dev));
}
@@ -1238,8 +1241,6 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
}
tp->chipset = i;
- tp->rx_buf_sz = RX_BUF_SIZE;
-
*ioaddr_out = ioaddr;
*dev_out = dev;
out:
@@ -1280,7 +1281,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
board_idx++;
if (!printed_version) {
- printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n");
+ printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
+ MODULENAME, RTL8169_VERSION);
printed_version = 1;
}
@@ -1321,6 +1323,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
+ dev->change_mtu = rtl8169_change_mtu;
#ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
@@ -1449,13 +1452,22 @@ static int rtl8169_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
-static int
-rtl8169_open(struct net_device *dev)
+static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
+ struct net_device *dev)
+{
+ unsigned int mtu = dev->mtu;
+
+ tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
+}
+
+static int rtl8169_open(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
struct pci_dev *pdev = tp->pci_dev;
int retval;
+ rtl8169_set_rxbufsize(tp, dev);
+
retval =
request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);
if (retval < 0)
@@ -1535,8 +1547,8 @@ rtl8169_hw_start(struct net_device *dev)
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
RTL_W8(EarlyTxThres, EarlyTxThld);
- // For gigabit rtl8169
- RTL_W16(RxMaxSize, RxPacketMaxSize);
+ // For gigabit rtl8169, MTU + header + CRC + VLAN
+ RTL_W16(RxMaxSize, tp->rx_buf_sz);
// Set Rx Config register
i = rtl8169_rx_config |
@@ -1577,6 +1589,37 @@ rtl8169_hw_start(struct net_device *dev)
netif_start_queue(dev);
}
+static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int ret = 0;
+
+ if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+
+ if (!netif_running(dev))
+ goto out;
+
+ rtl8169_down(dev);
+
+ rtl8169_set_rxbufsize(tp, dev);
+
+ ret = rtl8169_init_ring(dev);
+ if (ret < 0)
+ goto out;
+
+ rtl8169_hw_start(dev);
+
+ netif_poll_enable(dev);
+
+ rtl8169_request_timer(dev);
+
+out:
+ return ret;
+}
+
static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
{
desc->addr = 0x0badbadbadbadbadull;
@@ -1743,10 +1786,19 @@ static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *))
static void rtl8169_wait_for_quiescence(struct net_device *dev)
{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
synchronize_irq(dev->irq);
/* Wait for any pending NAPI task to complete */
netif_poll_disable(dev);
+
+ RTL_W16(IntrMask, 0x0000);
+
+ RTL_W16(IntrStatus, 0xffff);
+
+ netif_poll_enable(dev);
}
static void rtl8169_reinit_task(void *_data)
@@ -1970,7 +2022,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
/* The infamous DAC f*ckup only happens at boot time */
- if ((tp->cp_cmd & PCIDAC) && (tp->dirty_rx == tp->cur_rx == 0)) {
+ if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
printk(KERN_INFO PFX "%s: disabling PCI DAC.\n", dev->name);
tp->cp_cmd &= ~PCIDAC;
RTL_W16(CPlusCmd, tp->cp_cmd);
@@ -2256,19 +2308,17 @@ static int rtl8169_poll(struct net_device *dev, int *budget)
}
#endif
-static int
-rtl8169_close(struct net_device *dev)
+static void rtl8169_down(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
- struct pci_dev *pdev = tp->pci_dev;
void __iomem *ioaddr = tp->mmio_addr;
+ rtl8169_delete_timer(dev);
+
netif_stop_queue(dev);
flush_scheduled_work();
- rtl8169_delete_timer(dev);
-
spin_lock_irq(&tp->lock);
/* Stop the chip's Tx and Rx DMA processes. */
@@ -2283,13 +2333,27 @@ rtl8169_close(struct net_device *dev)
spin_unlock_irq(&tp->lock);
- free_irq(dev->irq, dev);
+ synchronize_irq(dev->irq);
netif_poll_disable(dev);
+ /* Give a racing hard_start_xmit a few cycles to complete. */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+
rtl8169_tx_clear(tp);
rtl8169_rx_clear(tp);
+}
+
+static int rtl8169_close(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+
+ rtl8169_down(dev);
+
+ free_irq(dev->irq, dev);
pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
tp->RxPhyAddr);
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 70cdd866dd8a53..d2deaaf5d98bab 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -61,7 +61,7 @@ typedef enum xena_max_outstanding_splits {
#define INTR_DBG 4
/* Global variable that defines the present debug level of the driver. */
-int debug_level = ERR_DBG; /* Default level. */
+static int debug_level = ERR_DBG; /* Default level. */
/* DEBUG message print. */
#define DBG_PRINT(dbg_level, args...) if(!(debug_level<dbg_level)) printk(args)
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index 0b914b46b9a439..091a0e07a5865e 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -81,6 +81,25 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
return retval & 0xffff;
}
+ if(tp->chip_id == ULI526X && tp->revision >= 0x40) {
+ int value;
+ int i = 1000;
+
+ value = ioread32(ioaddr + CSR9);
+ iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
+
+ value = (phy_id << 21) | (location << 16) | 0x80000000;
+ iowrite32(value, ioaddr + CSR10);
+
+ while(--i > 0) {
+ mdio_delay();
+ if(ioread32(ioaddr + CSR10) & 0x10000000)
+ break;
+ }
+ retval = ioread32(ioaddr + CSR10);
+ spin_unlock_irqrestore(&tp->mii_lock, flags);
+ return retval & 0xFFFF;
+ }
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -140,7 +159,23 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
spin_unlock_irqrestore(&tp->mii_lock, flags);
return;
}
-
+ if (tp->chip_id == ULI526X && tp->revision >= 0x40) {
+ int value;
+ int i = 1000;
+
+ value = ioread32(ioaddr + CSR9);
+ iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
+
+ value = (phy_id << 21) | (location << 16) | 0x40000000 | (val & 0xFFFF);
+ iowrite32(value, ioaddr + CSR10);
+
+ while(--i > 0) {
+ if (ioread32(ioaddr + CSR10) & 0x10000000)
+ break;
+ }
+ spin_unlock_irqrestore(&tp->mii_lock, flags);
+ }
+
/* Establish sync by sending 32 logic ones. */
for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c
index e058a9fbfe8844..691568283553b4 100644
--- a/drivers/net/tulip/timer.c
+++ b/drivers/net/tulip/timer.c
@@ -39,6 +39,7 @@ void tulip_timer(unsigned long data)
case MX98713:
case COMPEX9881:
case DM910X:
+ case ULI526X:
default: {
struct medialeaf *mleaf;
unsigned char *p;
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 6cce2834d6c70c..063a1f05a3d8fa 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -88,6 +88,7 @@ enum chips {
I21145,
DM910X,
CONEXANT,
+ ULI526X
};
@@ -481,8 +482,11 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp)
static inline void tulip_restart_rxtx(struct tulip_private *tp)
{
- tulip_stop_rxtx(tp);
- udelay(5);
+ if(!(tp->chip_id == ULI526X &&
+ (tp->revision == 0x40 || tp->revision == 0x50))) {
+ tulip_stop_rxtx(tp);
+ udelay(5);
+ }
tulip_start_rxtx(tp);
}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 9549c41d4dcf9e..87f580093687eb 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -88,9 +88,9 @@ static int rx_copybreak = 100;
ToDo: Non-Intel setting could be better.
*/
-#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__ia64__)
static int csr0 = 0x01A00000 | 0xE000;
-#elif defined(__i386__) || defined(__powerpc__)
+#elif defined(__i386__) || defined(__powerpc__) || defined(__x86_64__)
static int csr0 = 0x01A00000 | 0x8000;
#elif defined(__sparc__) || defined(__hppa__)
/* The UltraSparc PCI controllers will disconnect at every 64-byte
@@ -198,6 +198,10 @@ struct tulip_chip_table tulip_tbl[] = {
/* RS7112 */
{ "Conexant LANfinity", 256, 0x0001ebef,
HAS_MII | HAS_ACPI, tulip_timer },
+
+ /* ULi526X */
+ { "ULi M5261/M5263", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, tulip_timer },
};
@@ -229,12 +233,14 @@ static struct pci_device_id tulip_pci_tbl[] = {
{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1186, 0x1591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
{ 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
- { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, /* ALi 1563 integrated ethernet */
+ { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
+ { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
{ } /* terminate list */
};
@@ -515,7 +521,7 @@ static void tulip_tx_timeout(struct net_device *dev)
dev->name);
} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
|| tp->chip_id == MX98713 || tp->chip_id == COMPEX9881
- || tp->chip_id == DM910X) {
+ || tp->chip_id == DM910X || tp->chip_id == ULI526X) {
printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
"SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
@@ -1216,6 +1222,22 @@ out:
}
#endif
+/*
+ * Chips that have the MRM/reserved bit quirk and the burst quirk. That
+ * is the DM910X and the on chip ULi devices
+ */
+
+static int tulip_uli_dm_quirk(struct pci_dev *pdev)
+{
+ if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
+ return 1;
+ if (pdev->vendor == 0x10b9 && pdev->device == 0x5261)
+ return 1;
+ if (pdev->vendor == 0x10b9 && pdev->device == 0x5263)
+ return 1;
+ return 0;
+}
+
static int __devinit tulip_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1304,17 +1326,12 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
/* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */
- if ((pdev->vendor == 0x1282 && pdev->device == 0x9102)
- || (pdev->vendor == 0x10b9 && pdev->device == 0x5261))
+ if (tulip_uli_dm_quirk(pdev)) {
csr0 &= ~0x01f100ff;
-
#if defined(__sparc__)
- /* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */
- if ((pdev->vendor == 0x1282 && pdev->device == 0x9102)
- || (pdev->vendor == 0x10b9 && pdev->device == 0x5261))
csr0 = (csr0 & ~0xff00) | 0xe000;
#endif
-
+ }
/*
* And back to business
*/
@@ -1659,6 +1676,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
switch (chip_idx) {
case DC21140:
case DM910X:
+ case ULI526X:
default:
if (tp->mtable)
iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index 5b0647c2f44c56..32ccb26890c3ce 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -33,6 +33,13 @@
/* A few user-configurable values. */
+#define xircom_debug debug
+#ifdef XIRCOM_DEBUG
+static int xircom_debug = XIRCOM_DEBUG;
+#else
+static int xircom_debug = 1;
+#endif
+
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 25;
@@ -124,19 +131,11 @@ module_param(max_interrupt_work, int, 0);
module_param(rx_copybreak, int, 0);
module_param(csr0, int, 0);
-static int num_units;
-module_param_array(options, num_units, int, 0);
-module_param_array(full_duplex, num_units, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
#define RUN_AT(x) (jiffies + (x))
-#define xircom_debug debug
-#ifdef XIRCOM_DEBUG
-static int xircom_debug = XIRCOM_DEBUG;
-#else
-static int xircom_debug = 1;
-#endif
-
/*
Theory of Operation
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d0fe0f656ea68b..87a4e0008d4207 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -41,6 +41,7 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>
+#include <linux/crc32.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -104,11 +105,42 @@ drop:
return 0;
}
-static void tun_net_mclist(struct net_device *dev)
+/** Add the specified Ethernet address to this multicast filter. */
+static void
+add_multi(u32* filter, const u8* addr)
{
- /* Nothing to do for multicast filters.
- * We always accept all frames. */
- return;
+ int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
+ filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+}
+
+/** Remove the specified Ethernet addres from this multicast filter. */
+static void
+del_multi(u32* filter, const u8* addr)
+{
+ int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
+ filter[bit_nr >> 5] &= ~(1 << (bit_nr & 31));
+}
+
+/** Update the list of multicast groups to which the network device belongs.
+ * This list is used to filter packets being sent from the character device to
+ * the network device. */
+static void
+tun_net_mclist(struct net_device *dev)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ const struct dev_mc_list *mclist;
+ int i;
+ DBG(KERN_DEBUG "%s: tun_net_mclist: mc_count %d\n",
+ dev->name, dev->mc_count);
+ memset(tun->chr_filter, 0, sizeof tun->chr_filter);
+ for (i = 0, mclist = dev->mc_list; i < dev->mc_count && mclist != NULL;
+ i++, mclist = mclist->next) {
+ add_multi(tun->net_filter, mclist->dmi_addr);
+ DBG(KERN_DEBUG "%s: tun_net_mclist: %x:%x:%x:%x:%x:%x\n",
+ dev->name,
+ mclist->dmi_addr[0], mclist->dmi_addr[1], mclist->dmi_addr[2],
+ mclist->dmi_addr[3], mclist->dmi_addr[4], mclist->dmi_addr[5]);
+ }
}
static struct net_device_stats *tun_net_stats(struct net_device *dev)
@@ -301,6 +333,10 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
add_wait_queue(&tun->read_wait, &wait);
while (len) {
+ const u8 ones[ ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ u8 addr[ ETH_ALEN];
+ int bit_nr;
+
current->state = TASK_INTERRUPTIBLE;
/* Read frames from the queue */
@@ -320,10 +356,37 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
}
netif_start_queue(tun->dev);
- ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
-
- kfree_skb(skb);
- break;
+ /** Decide whether to accept this packet. This code is designed to
+ * behave identically to an Ethernet interface. Accept the packet if
+ * - we are promiscuous.
+ * - the packet is addressed to us.
+ * - the packet is broadcast.
+ * - the packet is multicast and
+ * - we are multicast promiscous.
+ * - we belong to the multicast group.
+ */
+ memcpy(addr, skb->data, min(sizeof addr, skb->len));
+ bit_nr = ether_crc(sizeof addr, addr) >> 26;
+ if ((tun->if_flags & IFF_PROMISC) ||
+ memcmp(addr, tun->dev_addr, sizeof addr) == 0 ||
+ memcmp(addr, ones, sizeof addr) == 0 ||
+ (((addr[0] == 1 && addr[1] == 0 && addr[2] == 0x5e) ||
+ (addr[0] == 0x33 && addr[1] == 0x33)) &&
+ ((tun->if_flags & IFF_ALLMULTI) ||
+ (tun->chr_filter[bit_nr >> 5] & (1 << (bit_nr & 31)))))) {
+ DBG(KERN_DEBUG "%s: tun_chr_readv: accepted: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name, addr[0], addr[1], addr[2],
+ addr[3], addr[4], addr[5]);
+ ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
+ kfree_skb(skb);
+ break;
+ } else {
+ DBG(KERN_DEBUG "%s: tun_chr_readv: rejected: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name, addr[0], addr[1], addr[2],
+ addr[3], addr[4], addr[5]);
+ kfree_skb(skb);
+ continue;
+ }
}
current->state = TASK_RUNNING;
@@ -417,6 +480,12 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
tun = netdev_priv(dev);
tun->dev = dev;
tun->flags = flags;
+ /* Be promiscuous by default to maintain previous behaviour. */
+ tun->if_flags = IFF_PROMISC;
+ /* Generate random Ethernet address. */
+ *(u16 *)tun->dev_addr = htons(0x00FF);
+ get_random_bytes(tun->dev_addr + sizeof(u16), 4);
+ memset(tun->chr_filter, 0, sizeof tun->chr_filter);
tun_net_init(dev);
@@ -457,13 +526,16 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct tun_struct *tun = file->private_data;
+ void __user* argp = (void __user*)arg;
+ struct ifreq ifr;
+
+ if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
+ if (copy_from_user(&ifr, argp, sizeof ifr))
+ return -EFAULT;
if (cmd == TUNSETIFF && !tun) {
- struct ifreq ifr;
int err;
- if (copy_from_user(&ifr, (void __user *)arg, sizeof(ifr)))
- return -EFAULT;
ifr.ifr_name[IFNAMSIZ-1] = '\0';
rtnl_lock();
@@ -473,7 +545,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
if (err)
return err;
- if (copy_to_user((void __user *)arg, &ifr, sizeof(ifr)))
+ if (copy_to_user(argp, &ifr, sizeof(ifr)))
return -EFAULT;
return 0;
}
@@ -519,6 +591,61 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
break;
#endif
+ case SIOCGIFFLAGS:
+ ifr.ifr_flags = tun->if_flags;
+ if (copy_to_user( argp, &ifr, sizeof ifr))
+ return -EFAULT;
+ return 0;
+
+ case SIOCSIFFLAGS:
+ /** Set the character device's interface flags. Currently only
+ * IFF_PROMISC and IFF_ALLMULTI are used. */
+ tun->if_flags = ifr.ifr_flags;
+ DBG(KERN_INFO "%s: interface flags 0x%lx\n",
+ tun->dev->name, tun->if_flags);
+ return 0;
+
+ case SIOCGIFHWADDR:
+ memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr,
+ min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
+ if (copy_to_user( argp, &ifr, sizeof ifr))
+ return -EFAULT;
+ return 0;
+
+ case SIOCSIFHWADDR:
+ /** Set the character device's hardware address. This is used when
+ * filtering packets being sent from the network device to the character
+ * device. */
+ memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
+ min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
+ DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name,
+ tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
+ tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
+ return 0;
+
+ case SIOCADDMULTI:
+ /** Add the specified group to the character device's multicast filter
+ * list. */
+ add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
+ DBG(KERN_DEBUG "%s: add multi: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name,
+ (u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
+ (u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
+ (u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
+ return 0;
+
+ case SIOCDELMULTI:
+ /** Remove the specified group from the character device's multicast
+ * filter list. */
+ del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
+ DBG(KERN_DEBUG "%s: del multi: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name,
+ (u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
+ (u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
+ (u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
+ return 0;
+
default:
return -EINVAL;
};
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 4c33ad4e5dab0d..04eced2181c7d0 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -859,7 +859,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
#ifdef USE_MMIO
memaddr
#else
- ioaddr
+ (long)ioaddr
#endif
);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 1886fe6b982e85..c889078c315f57 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -100,8 +100,8 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver");
#define VELOCITY_PARAM(N,D) \
- static const int N[MAX_UNITS]=OPTION_DEFAULT;\
- MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\
+ static int N[MAX_UNITS]=OPTION_DEFAULT;\
+ module_param_array(N, int, NULL, 0); \
MODULE_PARM_DESC(N, D);
#define RX_DESC_MIN 64
@@ -229,7 +229,7 @@ VELOCITY_PARAM(wol_opts, "Wake On Lan options");
VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
static int rx_copybreak = 200;
-MODULE_PARM(rx_copybreak, "i");
+module_param(rx_copybreak, int, 0644);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);