aboutsummaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/e100.c165
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c2
-rw-r--r--drivers/net/tg3.c488
-rw-r--r--drivers/net/tg3.h8
-rw-r--r--drivers/net/tulip/media.c1
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/wireless/Kconfig2
8 files changed, 520 insertions, 150 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 6202b10dbb4..e038d55e4f6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -187,7 +187,7 @@ obj-$(CONFIG_TR) += tokenring/
obj-$(CONFIG_WAN) += wan/
obj-$(CONFIG_ARCNET) += arcnet/
obj-$(CONFIG_NET_PCMCIA) += pcmcia/
-obj-$(CONFIG_NET_WIRELESS) += wireless/
+obj-$(CONFIG_NET_RADIO) += wireless/
obj-$(CONFIG_NET_TULIP) += tulip/
obj-$(CONFIG_HAMRADIO) += hamradio/
obj-$(CONFIG_IRDA) += irda/
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 1b68dd5a49b..4a47df5a9ff 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -155,9 +155,9 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.3.6-k2"DRV_EXT
+#define DRV_VERSION "3.4.8-k2"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
-#define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation"
+#define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation"
#define PFX DRV_NAME ": "
#define E100_WATCHDOG_PERIOD (2 * HZ)
@@ -210,11 +210,17 @@ 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(0x1091, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1092, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
INTEL_8255X_ETHERNET_DEVICE(0x2459, 2),
INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
+ INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7),
{ 0, }
};
MODULE_DEVICE_TABLE(pci, e100_id_table);
@@ -269,6 +275,12 @@ enum scb_status {
rus_mask = 0x3C,
};
+enum ru_state {
+ RU_SUSPENDED = 0,
+ RU_RUNNING = 1,
+ RU_UNINITIALIZED = -1,
+};
+
enum scb_stat_ack {
stat_ack_not_ours = 0x00,
stat_ack_sw_gen = 0x04,
@@ -510,7 +522,7 @@ struct nic {
struct rx *rx_to_use;
struct rx *rx_to_clean;
struct rfd blank_rfd;
- int ru_running;
+ enum ru_state ru_running;
spinlock_t cb_lock ____cacheline_aligned;
spinlock_t cmd_lock;
@@ -539,6 +551,7 @@ struct nic {
struct timer_list watchdog;
struct timer_list blink_timer;
struct mii_if_info mii;
+ struct work_struct tx_timeout_task;
enum loopback loopback;
struct mem *mem;
@@ -770,7 +783,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
return 0;
}
-#define E100_WAIT_SCB_TIMEOUT 40
+#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
unsigned long flags;
@@ -840,6 +853,10 @@ static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
* because the controller is too busy, so
* let's just queue the command and try again
* when another command is scheduled. */
+ if(err == -ENOSPC) {
+ //request a reset
+ schedule_work(&nic->tx_timeout_task);
+ }
break;
} else {
nic->cuc_cmd = cuc_resume;
@@ -884,7 +901,7 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
static void e100_get_defaults(struct nic *nic)
{
- struct param_range rfds = { .min = 64, .max = 256, .count = 64 };
+ struct param_range rfds = { .min = 16, .max = 256, .count = 64 };
struct param_range cbs = { .min = 64, .max = 256, .count = 64 };
pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
@@ -899,8 +916,9 @@ static void e100_get_defaults(struct nic *nic)
/* Quadwords to DMA into FIFO before starting frame transmit */
nic->tx_threshold = 0xE0;
- nic->tx_command = cpu_to_le16(cb_tx | cb_i | cb_tx_sf |
- ((nic->mac >= mac_82558_D101_A4) ? cb_cid : 0));
+ /* no interrupt for every tx completion, delay = 256us if not 557*/
+ nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
+ ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
/* Template for a freshly allocated RFD */
nic->blank_rfd.command = cpu_to_le16(cb_el);
@@ -964,7 +982,8 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
if(nic->flags & multicast_all)
config->multicast_all = 0x1; /* 1=accept, 0=no */
- if(!(nic->flags & wol_magic))
+ /* disable WoL when up */
+ if(netif_running(nic->netdev) || !(nic->flags & wol_magic))
config->magic_packet_disable = 0x1; /* 1=off, 0=on */
if(nic->mac >= mac_82558_D101_A4) {
@@ -1203,7 +1222,9 @@ static void e100_update_stats(struct nic *nic)
}
}
- e100_exec_cmd(nic, cuc_dump_reset, 0);
+
+ if(e100_exec_cmd(nic, cuc_dump_reset, 0))
+ DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}
static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
@@ -1279,12 +1300,15 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
cb->command = nic->tx_command;
+ /* interrupt every 16 packets regardless of delay */
+ if((nic->cbs_avail & ~15) == nic->cbs_avail) cb->command |= cb_i;
cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
cb->u.tcb.tcb_byte_count = 0;
cb->u.tcb.threshold = nic->tx_threshold;
cb->u.tcb.tbd_count = 1;
cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
+ // check for mapping failure?
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
}
@@ -1297,7 +1321,8 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
Issue a NOP command followed by a 1us delay before
issuing the Tx command. */
- e100_exec_cmd(nic, cuc_nop, 0);
+ if(e100_exec_cmd(nic, cuc_nop, 0))
+ DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n");
udelay(1);
}
@@ -1415,12 +1440,18 @@ static int e100_alloc_cbs(struct nic *nic)
return 0;
}
-static inline void e100_start_receiver(struct nic *nic)
+static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
{
+ if(!nic->rxs) return;
+ if(RU_SUSPENDED != nic->ru_running) return;
+
+ /* handle init time starts */
+ if(!rx) rx = nic->rxs;
+
/* (Re)start RU if suspended or idle and RFA is non-NULL */
- if(!nic->ru_running && nic->rx_to_clean->skb) {
- e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
- nic->ru_running = 1;
+ if(rx->skb) {
+ e100_exec_cmd(nic, ruc_start, rx->dma_addr);
+ nic->ru_running = RU_RUNNING;
}
}
@@ -1437,6 +1468,13 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
+ if(pci_dma_mapping_error(rx->dma_addr)) {
+ dev_kfree_skb_any(rx->skb);
+ rx->skb = 0;
+ rx->dma_addr = 0;
+ return -ENOMEM;
+ }
+
/* Link the RFD to end of RFA by linking previous RFD to
* this one, and clearing EL bit of previous. */
if(rx->prev->skb) {
@@ -1471,7 +1509,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
/* If data isn't ready, nothing to indicate */
if(unlikely(!(rfd_status & cb_complete)))
- return -EAGAIN;
+ return -ENODATA;
/* Get actual data size */
actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
@@ -1482,6 +1520,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
pci_unmap_single(nic->pdev, rx->dma_addr,
RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ /* this allows for a fast restart without re-enabling interrupts */
+ if(le16_to_cpu(rfd->command) & cb_el)
+ nic->ru_running = RU_SUSPENDED;
+
/* Pull off the RFD and put the actual data (minus eth hdr) */
skb_reserve(skb, sizeof(struct rfd));
skb_put(skb, actual_size);
@@ -1514,20 +1556,45 @@ static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
unsigned int work_to_do)
{
struct rx *rx;
+ int restart_required = 0;
+ struct rx *rx_to_start = NULL;
+
+ /* are we already rnr? then pay attention!!! this ensures that
+ * the state machine progression never allows a start with a
+ * partially cleaned list, avoiding a race between hardware
+ * and rx_to_clean when in NAPI mode */
+ if(RU_SUSPENDED == nic->ru_running)
+ restart_required = 1;
/* Indicate newly arrived packets */
for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
- if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+ int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
+ if(-EAGAIN == err) {
+ /* hit quota so have more work to do, restart once
+ * cleanup is complete */
+ restart_required = 0;
+ break;
+ } else if(-ENODATA == err)
break; /* No more to clean */
}
+ /* save our starting point as the place we'll restart the receiver */
+ if(restart_required)
+ rx_to_start = nic->rx_to_clean;
+
/* Alloc new skbs to refill list */
for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
if(unlikely(e100_rx_alloc_skb(nic, rx)))
break; /* Better luck next time (see watchdog) */
}
- e100_start_receiver(nic);
+ if(restart_required) {
+ // ack the rnr?
+ writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
+ e100_start_receiver(nic, rx_to_start);
+ if(work_done)
+ (*work_done)++;
+ }
}
static void e100_rx_clean_list(struct nic *nic)
@@ -1535,6 +1602,8 @@ static void e100_rx_clean_list(struct nic *nic)
struct rx *rx;
unsigned int i, count = nic->params.rfds.count;
+ nic->ru_running = RU_UNINITIALIZED;
+
if(nic->rxs) {
for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
if(rx->skb) {
@@ -1548,7 +1617,6 @@ static void e100_rx_clean_list(struct nic *nic)
}
nic->rx_to_use = nic->rx_to_clean = NULL;
- nic->ru_running = 0;
}
static int e100_rx_alloc_list(struct nic *nic)
@@ -1557,6 +1625,7 @@ static int e100_rx_alloc_list(struct nic *nic)
unsigned int i, count = nic->params.rfds.count;
nic->rx_to_use = nic->rx_to_clean = NULL;
+ nic->ru_running = RU_UNINITIALIZED;
if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC)))
return -ENOMEM;
@@ -1572,6 +1641,7 @@ static int e100_rx_alloc_list(struct nic *nic)
}
nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+ nic->ru_running = RU_SUSPENDED;
return 0;
}
@@ -1593,7 +1663,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
/* We hit Receive No Resource (RNR); restart RU after cleaning */
if(stat_ack & stat_ack_rnr)
- nic->ru_running = 0;
+ nic->ru_running = RU_SUSPENDED;
e100_disable_irq(nic);
netif_rx_schedule(netdev);
@@ -1663,6 +1733,7 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}
+#ifdef CONFIG_PM
static int e100_asf(struct nic *nic)
{
/* ASF can be enabled from eeprom */
@@ -1671,6 +1742,7 @@ static int e100_asf(struct nic *nic)
!(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
}
+#endif
static int e100_up(struct nic *nic)
{
@@ -1683,13 +1755,16 @@ static int e100_up(struct nic *nic)
if((err = e100_hw_init(nic)))
goto err_clean_cbs;
e100_set_multicast_list(nic->netdev);
- e100_start_receiver(nic);
+ e100_start_receiver(nic, 0);
mod_timer(&nic->watchdog, jiffies);
if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ,
nic->netdev->name, nic->netdev)))
goto err_no_irq;
- e100_enable_irq(nic);
netif_wake_queue(nic->netdev);
+ netif_poll_enable(nic->netdev);
+ /* enable ints _after_ enabling poll, preventing a race between
+ * disable ints+schedule */
+ e100_enable_irq(nic);
return 0;
err_no_irq:
@@ -1703,11 +1778,13 @@ err_rx_clean_list:
static void e100_down(struct nic *nic)
{
+ /* wait here for poll to complete */
+ netif_poll_disable(nic->netdev);
+ netif_stop_queue(nic->netdev);
e100_hw_reset(nic);
free_irq(nic->pdev->irq, nic->netdev);
del_timer_sync(&nic->watchdog);
netif_carrier_off(nic->netdev);
- netif_stop_queue(nic->netdev);
e100_clean_cbs(nic);
e100_rx_clean_list(nic);
}
@@ -1716,6 +1793,15 @@ static void e100_tx_timeout(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
+ /* Reset outside of interrupt context, to avoid request_irq
+ * in interrupt context */
+ schedule_work(&nic->tx_timeout_task);
+}
+
+static void e100_tx_timeout_task(struct net_device *netdev)
+{
+ struct nic *nic = netdev_priv(netdev);
+
DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
readb(&nic->csr->scb.status));
e100_down(netdev_priv(netdev));
@@ -1749,7 +1835,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
BMCR_LOOPBACK);
- e100_start_receiver(nic);
+ e100_start_receiver(nic, 0);
if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) {
err = -ENOMEM;
@@ -1869,7 +1955,6 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
else
nic->flags &= ~wol_magic;
- pci_enable_wake(nic->pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
e100_exec_cb(nic, NULL, e100_configure);
return 0;
@@ -2223,6 +2308,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
e100_get_defaults(nic);
+ /* locks must be initialized before calling hw_reset */
spin_lock_init(&nic->cb_lock);
spin_lock_init(&nic->cmd_lock);
@@ -2240,6 +2326,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->blink_timer.function = e100_blink_led;
nic->blink_timer.data = (unsigned long)nic;
+ INIT_WORK(&nic->tx_timeout_task,
+ (void (*)(void *))e100_tx_timeout_task, netdev);
+
if((err = e100_alloc(nic))) {
DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
goto err_out_iounmap;
@@ -2263,7 +2352,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
(nic->eeprom[eeprom_id] & eeprom_id_wol))
nic->flags |= wol_magic;
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+ /* ack any pending wake events, disable PME */
+ pci_enable_wake(pdev, 0, 0);
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
@@ -2335,7 +2425,10 @@ static int e100_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- e100_hw_init(nic);
+ /* ack any pending wake events, disable PME */
+ pci_enable_wake(pdev, 0, 0);
+ if(e100_hw_init(nic))
+ DPRINTK(HW, ERR, "e100_hw_init failed\n");
netif_device_attach(netdev);
if(netif_running(netdev))
@@ -2345,6 +2438,21 @@ static int e100_resume(struct pci_dev *pdev)
}
#endif
+
+static void e100_shutdown(struct device *dev)
+{
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct nic *nic = netdev_priv(netdev);
+
+#ifdef CONFIG_PM
+ pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+#else
+ pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
+#endif
+}
+
+
static struct pci_driver e100_driver = {
.name = DRV_NAME,
.id_table = e100_id_table,
@@ -2354,6 +2462,11 @@ static struct pci_driver e100_driver = {
.suspend = e100_suspend,
.resume = e100_resume,
#endif
+
+ .driver = {
+ .shutdown = e100_shutdown,
+ }
+
};
static int __init e100_init_module(void)
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index ab44358ddbf..6482d994d48 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1595,7 +1595,7 @@ static struct ethtool_ops emac_ethtool_ops = {
static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct ocp_enet_private *fep = dev->priv;
- uint *data = (uint *) & rq->ifr_ifru;
+ uint16_t *data = (uint16_t *) & rq->ifr_ifru;
switch (cmd) {
case SIOCGMIIPHY:
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index f79b02e80e7..f10dd74988c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -61,8 +61,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.27"
-#define DRV_MODULE_RELDATE "May 5, 2005"
+#define DRV_MODULE_VERSION "3.29"
+#define DRV_MODULE_RELDATE "May 23, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -206,6 +206,8 @@ static struct pci_device_id tg3_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M,
@@ -420,7 +422,8 @@ static void tg3_enable_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ (tp->last_tag << 24));
tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
tg3_cond_int(tp);
@@ -455,10 +458,16 @@ static void tg3_restart_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ tp->last_tag << 24);
mmiowb();
- if (tg3_has_work(tp))
+ /* When doing tagged status, this work check is unnecessary.
+ * The last_tag we write above tells the chip which piece of
+ * work we've completed.
+ */
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+ tg3_has_work(tp))
tw32(HOSTCC_MODE, tp->coalesce_mode |
(HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
}
@@ -2500,7 +2509,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
if (netif_carrier_ok(tp->dev)) {
tw32(HOSTCC_STAT_COAL_TICKS,
- DEFAULT_STAT_COAL_TICKS);
+ tp->coal.stats_block_coalesce_usecs);
} else {
tw32(HOSTCC_STAT_COAL_TICKS, 0);
}
@@ -2886,7 +2895,6 @@ static int tg3_poll(struct net_device *netdev, int *budget)
* All RX "locking" is done by ensuring outside
* code synchronizes with dev->poll()
*/
- done = 1;
if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
int orig_budget = *budget;
int work_done;
@@ -2898,12 +2906,14 @@ static int tg3_poll(struct net_device *netdev, int *budget)
*budget -= work_done;
netdev->quota -= work_done;
-
- if (work_done >= orig_budget)
- done = 0;
}
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ tp->last_tag = sblk->status_tag;
+ rmb();
+
/* if no more work, tell net stack and NIC we're done */
+ done = !tg3_has_work(tp);
if (done) {
spin_lock_irqsave(&tp->lock, flags);
__netif_rx_complete(netdev);
@@ -2928,22 +2938,21 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
spin_lock_irqsave(&tp->lock, flags);
/*
- * writing any value to intr-mbox-0 clears PCI INTA# and
+ * Writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events.
- * writing non-zero to intr-mbox-0 additional tells the
+ * Writing non-zero to intr-mbox-0 additional tells the
* NIC to stop sending us irqs, engaging "in-intr-handler"
* event coalescing.
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ tp->last_tag = sblk->status_tag;
sblk->status &= ~SD_STATUS_UPDATED;
-
if (likely(tg3_has_work(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */
else {
- /* no work, re-enable interrupts
- */
+ /* No work, re-enable interrupts. */
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
+ tp->last_tag << 24);
}
spin_unlock_irqrestore(&tp->lock, flags);
@@ -2969,21 +2978,62 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if ((sblk->status & SD_STATUS_UPDATED) ||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
/*
- * writing any value to intr-mbox-0 clears PCI INTA# and
+ * Writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events.
- * writing non-zero to intr-mbox-0 additional tells the
+ * Writing non-zero to intr-mbox-0 additional tells the
* NIC to stop sending us irqs, engaging "in-intr-handler"
* event coalescing.
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001);
+ sblk->status &= ~SD_STATUS_UPDATED;
+ if (likely(tg3_has_work(tp)))
+ netif_rx_schedule(dev); /* schedule NAPI poll */
+ else {
+ /* No work, shared interrupt perhaps? re-enable
+ * interrupts, and flush that PCI write
+ */
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000000);
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ }
+ } else { /* shared interrupt */
+ handled = 0;
+ }
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+
+ return IRQ_RETVAL(handled);
+}
+
+static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct tg3 *tp = netdev_priv(dev);
+ struct tg3_hw_status *sblk = tp->hw_status;
+ unsigned long flags;
+ unsigned int handled = 1;
+
+ spin_lock_irqsave(&tp->lock, flags);
+
+ /* In INTx mode, it is possible for the interrupt to arrive at
+ * the CPU before the status block posted prior to the interrupt.
+ * Reading the PCI State register will confirm whether the
+ * interrupt is ours and will flush the status block.
+ */
+ if ((sblk->status & SD_STATUS_UPDATED) ||
+ !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
/*
- * Flush PCI write. This also guarantees that our
- * status block has been flushed to host memory.
+ * writing any value to intr-mbox-0 clears PCI INTA# and
+ * chip-internal interrupt pending events.
+ * writing non-zero to intr-mbox-0 additional tells the
+ * NIC to stop sending us irqs, engaging "in-intr-handler"
+ * event coalescing.
*/
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000001);
+ tp->last_tag = sblk->status_tag;
sblk->status &= ~SD_STATUS_UPDATED;
-
if (likely(tg3_has_work(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */
else {
@@ -2991,7 +3041,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* interrupts, and flush that PCI write
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
+ tp->last_tag << 24);
tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
} else { /* shared interrupt */
@@ -5044,6 +5094,27 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
}
static void __tg3_set_rx_mode(struct net_device *);
+static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
+{
+ tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
+ tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
+ tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
+ tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+ tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
+ tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+ }
+ tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
+ tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+ u32 val = ec->stats_block_coalesce_usecs;
+
+ if (!netif_carrier_ok(tp->dev))
+ val = 0;
+
+ tw32(HOSTCC_STAT_COAL_TICKS, val);
+ }
+}
/* tp->lock is held. */
static int tg3_reset_hw(struct tg3 *tp)
@@ -5366,16 +5437,7 @@ static int tg3_reset_hw(struct tg3 *tp)
udelay(10);
}
- tw32(HOSTCC_RXCOL_TICKS, 0);
- tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
- tw32(HOSTCC_RXMAX_FRAMES, 1);
- tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
- if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
- tw32(HOSTCC_RXCOAL_TICK_INT, 0);
- tw32(HOSTCC_TXCOAL_TICK_INT, 0);
- }
- tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
- tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+ tg3_set_coalesce(tp, &tp->coal);
/* set status block DMA address */
tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
@@ -5388,8 +5450,6 @@ static int tg3_reset_hw(struct tg3 *tp)
* the tg3_periodic_fetch_stats call there, and
* tg3_get_stats to see how this works for 5705/5750 chips.
*/
- tw32(HOSTCC_STAT_COAL_TICKS,
- DEFAULT_STAT_COAL_TICKS);
tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
((u64) tp->stats_mapping >> 32));
tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
@@ -5445,7 +5505,8 @@ static int tg3_reset_hw(struct tg3 *tp)
udelay(100);
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
- tr32(MAILBOX_INTERRUPT_0);
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tp->last_tag = 0;
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
@@ -5723,31 +5784,33 @@ static void tg3_timer(unsigned long __opaque)
spin_lock_irqsave(&tp->lock, flags);
spin_lock(&tp->tx_lock);
- /* All of this garbage is because when using non-tagged
- * IRQ status the mailbox/status_block protocol the chip
- * uses with the cpu is race prone.
- */
- if (tp->hw_status->status & SD_STATUS_UPDATED) {
- tw32(GRC_LOCAL_CTRL,
- tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
- } else {
- tw32(HOSTCC_MODE, tp->coalesce_mode |
- (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
- }
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
+ /* All of this garbage is because when using non-tagged
+ * IRQ status the mailbox/status_block protocol the chip
+ * uses with the cpu is race prone.
+ */
+ if (tp->hw_status->status & SD_STATUS_UPDATED) {
+ tw32(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ } else {
+ tw32(HOSTCC_MODE, tp->coalesce_mode |
+ (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+ }
- if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
- tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
- spin_unlock(&tp->tx_lock);
- spin_unlock_irqrestore(&tp->lock, flags);
- schedule_work(&tp->reset_task);
- return;
+ if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+ tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
+ spin_unlock(&tp->tx_lock);
+ spin_unlock_irqrestore(&tp->lock, flags);
+ schedule_work(&tp->reset_task);
+ return;
+ }
}
- if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
- tg3_periodic_fetch_stats(tp);
-
/* This part only runs once per second. */
if (!--tp->timer_counter) {
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+ tg3_periodic_fetch_stats(tp);
+
if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
u32 mac_stat;
int phy_event;
@@ -5846,9 +5909,13 @@ static int tg3_test_interrupt(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
err = request_irq(tp->pdev->irq, tg3_msi,
SA_SAMPLE_RANDOM, dev->name, dev);
- else
- err = request_irq(tp->pdev->irq, tg3_interrupt,
+ else {
+ irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ fn = tg3_interrupt_tagged;
+ err = request_irq(tp->pdev->irq, fn,
SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ }
if (err)
return err;
@@ -5900,9 +5967,14 @@ static int tg3_test_msi(struct tg3 *tp)
tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
- err = request_irq(tp->pdev->irq, tg3_interrupt,
- SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ {
+ irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ fn = tg3_interrupt_tagged;
+ err = request_irq(tp->pdev->irq, fn,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ }
if (err)
return err;
@@ -5948,7 +6020,13 @@ static int tg3_open(struct net_device *dev)
if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
(GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
(GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) {
- if (pci_enable_msi(tp->pdev) == 0) {
+ /* All MSI supporting chips should support tagged
+ * status. Assert that this is the case.
+ */
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
+ printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
+ "Not using MSI.\n", tp->dev->name);
+ } else if (pci_enable_msi(tp->pdev) == 0) {
u32 msi_mode;
msi_mode = tr32(MSGINT_MODE);
@@ -5959,9 +6037,14 @@ static int tg3_open(struct net_device *dev)
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
err = request_irq(tp->pdev->irq, tg3_msi,
SA_SAMPLE_RANDOM, dev->name, dev);
- else
- err = request_irq(tp->pdev->irq, tg3_interrupt,
+ else {
+ irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ fn = tg3_interrupt_tagged;
+
+ err = request_irq(tp->pdev->irq, fn,
SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ }
if (err) {
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -5980,9 +6063,16 @@ static int tg3_open(struct net_device *dev)
tg3_halt(tp, 1);
tg3_free_rings(tp);
} else {
- tp->timer_offset = HZ / 10;
- tp->timer_counter = tp->timer_multiplier = 10;
- tp->asf_counter = tp->asf_multiplier = (10 * 120);
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ tp->timer_offset = HZ;
+ else
+ tp->timer_offset = HZ / 10;
+
+ BUG_ON(tp->timer_offset > HZ);
+ tp->timer_counter = tp->timer_multiplier =
+ (HZ / tp->timer_offset);
+ tp->asf_counter = tp->asf_multiplier =
+ ((HZ / tp->timer_offset) * 120);
init_timer(&tp->timer);
tp->timer.expires = jiffies + tp->timer_offset;
@@ -6005,6 +6095,7 @@ static int tg3_open(struct net_device *dev)
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
err = tg3_test_msi(tp);
+
if (err) {
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
@@ -7203,6 +7294,14 @@ static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
}
#endif
+static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ memcpy(ec, &tp->coal, sizeof(*ec));
+ return 0;
+}
+
static struct ethtool_ops tg3_ethtool_ops = {
.get_settings = tg3_get_settings,
.set_settings = tg3_set_settings,
@@ -7235,6 +7334,7 @@ static struct ethtool_ops tg3_ethtool_ops = {
.get_strings = tg3_get_strings,
.get_stats_count = tg3_get_stats_count,
.get_ethtool_stats = tg3_get_ethtool_stats,
+ .get_coalesce = tg3_get_coalesce,
};
static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -8422,15 +8522,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
- /* Only 5701 and later support tagged irq status mode.
- * Also, 5788 chips cannot use tagged irq status.
- *
- * However, since we are using NAPI avoid tagged irq status
- * because the interrupt condition is more difficult to
- * fully clear in that mode.
- */
tp->coalesce_mode = 0;
-
if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
@@ -8494,6 +8586,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
tp->tg3_flags2 |= TG3_FLG2_IS_5788;
+ if (!(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700))
+ tp->tg3_flags |= TG3_FLAG_TAGGED_STATUS;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+ tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD);
+
+ tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+ }
+
/* these are limited to 10/100 only */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
(grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
@@ -8671,6 +8775,146 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
return 0;
}
+#define BOUNDARY_SINGLE_CACHELINE 1
+#define BOUNDARY_MULTI_CACHELINE 2
+
+static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+{
+ int cacheline_size;
+ u8 byte;
+ int goal;
+
+ pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
+ if (byte == 0)
+ cacheline_size = 1024;
+ else
+ cacheline_size = (int) byte * 4;
+
+ /* On 5703 and later chips, the boundary bits have no
+ * effect.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+ !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+ goto out;
+
+#if defined(CONFIG_PPC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC)
+ goal = BOUNDARY_MULTI_CACHELINE;
+#else
+#if defined(CONFIG_SPARC64) || defined(CONFIG_ALPHA)
+ goal = BOUNDARY_SINGLE_CACHELINE;
+#else
+ goal = 0;
+#endif
+#endif
+
+ if (!goal)
+ goto out;
+
+ /* PCI controllers on most RISC systems tend to disconnect
+ * when a device tries to burst across a cache-line boundary.
+ * Therefore, letting tg3 do so just wastes PCI bandwidth.
+ *
+ * Unfortunately, for PCI-E there are only limited
+ * write-side controls for this, and thus for reads
+ * we will still get the disconnects. We'll also waste
+ * these PCI cycles for both read and write for chips
+ * other than 5700 and 5701 which do not implement the
+ * boundary bits.
+ */
+ if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+ !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+ switch (cacheline_size) {
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_128_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_128_PCIX);
+ } else {
+ val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
+ }
+ break;
+
+ case 256:
+ val |= (DMA_RWCTRL_READ_BNDRY_256_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_256_PCIX);
+ break;
+
+ default:
+ val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
+ break;
+ };
+ } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ switch (cacheline_size) {
+ case 16:
+ case 32:
+ case 64:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
+ val |= DMA_RWCTRL_WRITE_BNDRY_64_PCIE;
+ break;
+ }
+ /* fallthrough */
+ case 128:
+ default:
+ val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
+ val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
+ break;
+ };
+ } else {
+ switch (cacheline_size) {
+ case 16:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_16 |
+ DMA_RWCTRL_WRITE_BNDRY_16);
+ break;
+ }
+ /* fallthrough */
+ case 32:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_32 |
+ DMA_RWCTRL_WRITE_BNDRY_32);
+ break;
+ }
+ /* fallthrough */
+ case 64:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_64 |
+ DMA_RWCTRL_WRITE_BNDRY_64);
+ break;
+ }
+ /* fallthrough */
+ case 128:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_128 |
+ DMA_RWCTRL_WRITE_BNDRY_128);
+ break;
+ }
+ /* fallthrough */
+ case 256:
+ val |= (DMA_RWCTRL_READ_BNDRY_256 |
+ DMA_RWCTRL_WRITE_BNDRY_256);
+ break;
+ case 512:
+ val |= (DMA_RWCTRL_READ_BNDRY_512 |
+ DMA_RWCTRL_WRITE_BNDRY_512);
+ break;
+ case 1024:
+ default:
+ val |= (DMA_RWCTRL_READ_BNDRY_1024 |
+ DMA_RWCTRL_WRITE_BNDRY_1024);
+ break;
+ };
+ }
+
+out:
+ return val;
+}
+
static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
{
struct tg3_internal_buffer_desc test_desc;
@@ -8752,12 +8996,12 @@ static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dm
return ret;
}
-#define TEST_BUFFER_SIZE 0x400
+#define TEST_BUFFER_SIZE 0x2000
static int __devinit tg3_test_dma(struct tg3 *tp)
{
dma_addr_t buf_dma;
- u32 *buf;
+ u32 *buf, saved_dma_rwctrl;
int ret;
buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma);
@@ -8769,46 +9013,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
(0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
-#ifndef CONFIG_X86
- {
- u8 byte;
- int cacheline_size;
- pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
-
- if (byte == 0)
- cacheline_size = 1024;
- else
- cacheline_size = (int) byte * 4;
-
- switch (cacheline_size) {
- case 16:
- case 32:
- case 64:
- case 128:
- if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
- !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_384_PCIX;
- break;
- } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
- tp->dma_rwctrl &=
- ~(DMA_RWCTRL_PCI_WRITE_CMD);
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
- break;
- }
- /* fallthrough */
- case 256:
- if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
- !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_256;
- else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_256_PCIX;
- };
- }
-#endif
+ tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
/* DMA read watermark not used on PCIE */
@@ -8827,7 +9032,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
if (ccval == 0x6 || ccval == 0x7)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
- /* Set bit 23 to renable PCIX hw bug fix */
+ /* Set bit 23 to enable PCIX hw bug fix */
tp->dma_rwctrl |= 0x009f0000;
} else {
tp->dma_rwctrl |= 0x001b000f;
@@ -8868,6 +9073,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
goto out;
+ /* It is best to perform DMA test with maximum write burst size
+ * to expose the 5700/5701 write DMA bug.
+ */
+ saved_dma_rwctrl = tp->dma_rwctrl;
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
while (1) {
u32 *p = buf, i;
@@ -8906,8 +9118,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
if (p[i] == i)
continue;
- if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) ==
- DMA_RWCTRL_WRITE_BNDRY_DISAB) {
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
break;
@@ -8924,6 +9137,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
break;
}
}
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ /* DMA test passed without adjusting DMA boundary,
+ * just restore the calculated DMA boundary
+ */
+ tp->dma_rwctrl = saved_dma_rwctrl;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
out:
pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma);
@@ -9011,6 +9232,31 @@ static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
return peer;
}
+static void __devinit tg3_init_coal(struct tg3 *tp)
+{
+ struct ethtool_coalesce *ec = &tp->coal;
+
+ memset(ec, 0, sizeof(*ec));
+ ec->cmd = ETHTOOL_GCOALESCE;
+ ec->rx_coalesce_usecs = LOW_RXCOL_TICKS;
+ ec->tx_coalesce_usecs = LOW_TXCOL_TICKS;
+ ec->rx_max_coalesced_frames = LOW_RXMAX_FRAMES;
+ ec->tx_max_coalesced_frames = LOW_TXMAX_FRAMES;
+ ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT;
+ ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT;
+ ec->rx_max_coalesced_frames_irq = DEFAULT_RXCOAL_MAXF_INT;
+ ec->tx_max_coalesced_frames_irq = DEFAULT_TXCOAL_MAXF_INT;
+ ec->stats_block_coalesce_usecs = DEFAULT_STAT_COAL_TICKS;
+
+ if (tp->coalesce_mode & (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD)) {
+ ec->rx_coalesce_usecs = LOW_RXCOL_TICKS_CLRTCKS;
+ ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT_CLRTCKS;
+ ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS;
+ ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS;
+ }
+}
+
static int __devinit tg3_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -9256,6 +9502,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
/* flow control autonegotiation is default behavior */
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+ tg3_init_coal(tp);
+
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
@@ -9298,6 +9546,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
+ printk(KERN_INFO "%s: dma_rwctrl[%08x]\n",
+ dev->name, tp->dma_rwctrl);
return 0;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 8de6f21037b..993f84c93dc 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -876,10 +876,12 @@
#define HOSTCC_STATUS_ERROR_ATTN 0x00000004
#define HOSTCC_RXCOL_TICKS 0x00003c08
#define LOW_RXCOL_TICKS 0x00000032
+#define LOW_RXCOL_TICKS_CLRTCKS 0x00000014
#define DEFAULT_RXCOL_TICKS 0x00000048
#define HIGH_RXCOL_TICKS 0x00000096
#define HOSTCC_TXCOL_TICKS 0x00003c0c
#define LOW_TXCOL_TICKS 0x00000096
+#define LOW_TXCOL_TICKS_CLRTCKS 0x00000048
#define DEFAULT_TXCOL_TICKS 0x0000012c
#define HIGH_TXCOL_TICKS 0x00000145
#define HOSTCC_RXMAX_FRAMES 0x00003c10
@@ -892,8 +894,10 @@
#define HIGH_TXMAX_FRAMES 0x00000052
#define HOSTCC_RXCOAL_TICK_INT 0x00003c18
#define DEFAULT_RXCOAL_TICK_INT 0x00000019
+#define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014
#define HOSTCC_TXCOAL_TICK_INT 0x00003c1c
#define DEFAULT_TXCOAL_TICK_INT 0x00000019
+#define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014
#define HOSTCC_RXCOAL_MAXF_INT 0x00003c20
#define DEFAULT_RXCOAL_MAXF_INT 0x00000005
#define HOSTCC_TXCOAL_MAXF_INT 0x00003c24
@@ -2023,6 +2027,7 @@ struct tg3 {
struct tg3_hw_status *hw_status;
dma_addr_t status_mapping;
+ u32 last_tag;
u32 msg_enable;
@@ -2068,6 +2073,7 @@ struct tg3 {
u32 rx_offset;
u32 tg3_flags;
+#define TG3_FLAG_TAGGED_STATUS 0x00000001
#define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002
#define TG3_FLAG_RX_CHECKSUMS 0x00000004
#define TG3_FLAG_USE_LINKCHG_REG 0x00000008
@@ -2225,7 +2231,7 @@ struct tg3 {
#define SST_25VF0X0_PAGE_SIZE 4098
-
+ struct ethtool_coalesce coal;
};
#endif /* !(_T3_H) */
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index edae09a4b02..919c40cd635 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -174,6 +174,7 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
break;
}
spin_unlock_irqrestore(&tp->mii_lock, flags);
+ return;
}
/* Establish sync by sending 32 logic ones. */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index d098b3ba353..e0ae3ed6e57 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1104,7 +1104,7 @@ static void set_rx_mode(struct net_device *dev)
if (entry != 0) {
/* Avoid a chip errata by prefixing a dummy entry. Don't do
this on the ULI526X as it triggers a different problem */
- if (!(tp->chip_id == ULI526X && (tp->revision = 0x40 || tp->revision == 0x50))) {
+ if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
tp->tx_buffers[entry].skb = NULL;
tp->tx_buffers[entry].mapping = 0;
tp->tx_ring[entry].length =
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 0aaa12c0c09..1d3231cc471 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -323,7 +323,7 @@ config PRISM54
For a complete list of supported cards visit <http://prism54.org>.
Here is the latest confirmed list of supported cards:
- 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+ 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1)
Allnet ALL0271 PCI Card
Compex WL54G Cardbus Card
Corega CG-WLCB54GT Cardbus Card