patch-2.4.20 linux-2.4.20/drivers/net/tg3.c
Next file: linux-2.4.20/drivers/net/tg3.h
Previous file: linux-2.4.20/drivers/net/sunhme.c
Back to the patch index
Back to the overall index
- Lines: 3276
- Date:
Thu Nov 28 15:53:14 2002
- Orig file:
linux-2.4.19/drivers/net/tg3.c
- Orig date:
Fri Aug 2 17:39:44 2002
diff -urN linux-2.4.19/drivers/net/tg3.c linux-2.4.20/drivers/net/tg3.c
@@ -48,12 +48,19 @@
#define TG3_VLAN_TAG_USED 0
#endif
+#ifdef NETIF_F_TSO
+/* XXX some bug in tso firmware hangs tx cpu, disabled until fixed */
+#define TG3_DO_TSO 0
+#else
+#define TG3_DO_TSO 0
+#endif
+
#include "tg3.h"
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "0.99"
-#define DRV_MODULE_RELDATE "Jun 11, 2002"
+#define DRV_MODULE_VERSION "1.2"
+#define DRV_MODULE_RELDATE "Nov 14, 2002"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -142,6 +149,8 @@
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X,
@@ -212,6 +221,7 @@
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
static void tg3_enable_ints(struct tg3 *tp)
@@ -220,9 +230,44 @@
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
- if (tp->hw_status->status & SD_STATUS_UPDATED)
+ if (tp->hw_status->status & SD_STATUS_UPDATED) {
+ tw32(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ }
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+}
+
+static inline void tg3_mask_ints(struct tg3 *tp)
+{
+ tw32(TG3PCI_MISC_HOST_CTRL,
+ (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
+}
+
+static inline void tg3_unmask_ints(struct tg3 *tp)
+{
+ tw32(TG3PCI_MISC_HOST_CTRL,
+ (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
+ if (tp->hw_status->status & SD_STATUS_UPDATED) {
tw32(GRC_LOCAL_CTRL,
tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ }
+}
+
+static void tg3_switch_clocks(struct tg3 *tp)
+{
+ if (tr32(TG3PCI_CLOCK_CTRL) & CLOCK_CTRL_44MHZ_CORE) {
+ tw32(TG3PCI_CLOCK_CTRL,
+ (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
+ tw32(TG3PCI_CLOCK_CTRL,
+ (CLOCK_CTRL_ALTCLK));
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
+ }
+ tw32(TG3PCI_CLOCK_CTRL, 0);
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
}
#define PHY_BUSY_LOOPS 5000
@@ -235,6 +280,7 @@
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32(MAC_MI_MODE,
(tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ tr32(MAC_MI_MODE);
udelay(40);
}
@@ -247,9 +293,11 @@
frame_val |= (MI_COM_CMD_READ | MI_COM_START);
tw32(MAC_MI_COM, frame_val);
+ tr32(MAC_MI_COM);
loops = PHY_BUSY_LOOPS;
while (loops-- > 0) {
+ udelay(10);
frame_val = tr32(MAC_MI_COM);
if ((frame_val & MI_COM_BUSY) == 0) {
@@ -257,7 +305,6 @@
frame_val = tr32(MAC_MI_COM);
break;
}
- udelay(10);
}
ret = -EBUSY;
@@ -268,6 +315,7 @@
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32(MAC_MI_MODE, tp->mi_mode);
+ tr32(MAC_MI_MODE);
udelay(40);
}
@@ -282,6 +330,7 @@
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32(MAC_MI_MODE,
(tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ tr32(MAC_MI_MODE);
udelay(40);
}
@@ -293,16 +342,17 @@
frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
tw32(MAC_MI_COM, frame_val);
+ tr32(MAC_MI_COM);
loops = PHY_BUSY_LOOPS;
while (loops-- > 0) {
+ udelay(10);
frame_val = tr32(MAC_MI_COM);
if ((frame_val & MI_COM_BUSY) == 0) {
udelay(5);
frame_val = tr32(MAC_MI_COM);
break;
}
- udelay(10);
}
ret = -EBUSY;
@@ -311,6 +361,7 @@
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32(MAC_MI_MODE, tp->mi_mode);
+ tr32(MAC_MI_MODE);
udelay(40);
}
@@ -388,7 +439,9 @@
pm + PCI_PM_CTRL,
power_control);
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
+ tr32(GRC_LOCAL_CTRL);
+ udelay(100);
+
return 0;
case 1:
@@ -404,7 +457,8 @@
break;
default:
- printk(KERN_WARNING "%s: Invalid power state (%d) requested.\n",
+ printk(KERN_WARNING PFX "%s: Invalid power state (%d) "
+ "requested.\n",
tp->dev->name, state);
return -EINVAL;
};
@@ -422,9 +476,12 @@
tp->link_config.orig_autoneg = tp->link_config.autoneg;
}
- tp->link_config.speed = SPEED_10;
- tp->link_config.autoneg = AUTONEG_ENABLE;
- tg3_setup_phy(tp);
+ if (tp->phy_id != PHY_ID_SERDES) {
+ tp->link_config.speed = SPEED_10;
+ tp->link_config.duplex = DUPLEX_HALF;
+ tp->link_config.autoneg = AUTONEG_ENABLE;
+ tg3_setup_phy(tp);
+ }
tg3_halt(tp);
@@ -433,52 +490,114 @@
if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
u32 mac_mode;
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
+ if (tp->phy_id != PHY_ID_SERDES) {
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
+ udelay(40);
+
+ mac_mode = MAC_MODE_PORT_MODE_MII;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
+ !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
+ mac_mode |= MAC_MODE_LINK_POLARITY;
+ } else {
+ mac_mode = MAC_MODE_PORT_MODE_TBI;
+ }
- mac_mode = MAC_MODE_PORT_MODE_MII |
- MAC_MODE_LINK_POLARITY;
if (((power_caps & PCI_PM_CAP_PME_D3cold) &&
(tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
tw32(MAC_MODE, mac_mode);
+ tr32(MAC_MODE);
+ udelay(100);
+
tw32(MAC_RX_MODE, RX_MODE_ENABLE);
+ tr32(MAC_RX_MODE);
+ udelay(10);
}
if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) {
- tw32(TG3PCI_CLOCK_CTRL,
- (CLOCK_CTRL_RXCLK_DISABLE |
- CLOCK_CTRL_TXCLK_DISABLE |
- CLOCK_CTRL_ALTCLK));
- tw32(TG3PCI_CLOCK_CTRL,
- (CLOCK_CTRL_RXCLK_DISABLE |
- CLOCK_CTRL_TXCLK_DISABLE |
- CLOCK_CTRL_44MHZ_CORE));
- tw32(TG3PCI_CLOCK_CTRL,
- (CLOCK_CTRL_RXCLK_DISABLE |
- CLOCK_CTRL_TXCLK_DISABLE |
- CLOCK_CTRL_ALTCLK |
- CLOCK_CTRL_44MHZ_CORE));
+ u32 base_val;
+
+ base_val = 0;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+ base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
+ CLOCK_CTRL_TXCLK_DISABLE);
+
+ tw32(TG3PCI_CLOCK_CTRL, base_val |
+ CLOCK_CTRL_ALTCLK);
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
+
+ tw32(TG3PCI_CLOCK_CTRL, base_val |
+ CLOCK_CTRL_ALTCLK |
+ CLOCK_CTRL_44MHZ_CORE);
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
+
+ tw32(TG3PCI_CLOCK_CTRL, base_val |
+ CLOCK_CTRL_44MHZ_CORE);
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
} else {
- tw32(TG3PCI_CLOCK_CTRL,
- (CLOCK_CTRL_RXCLK_DISABLE |
- CLOCK_CTRL_TXCLK_DISABLE |
- CLOCK_CTRL_ALTCLK |
- CLOCK_CTRL_PWRDOWN_PLL133));
- }
+ u32 base_val;
- udelay(40);
+ base_val = 0;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+ base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
+ CLOCK_CTRL_TXCLK_DISABLE);
+
+ tw32(TG3PCI_CLOCK_CTRL, base_val |
+ CLOCK_CTRL_ALTCLK |
+ CLOCK_CTRL_PWRDOWN_PLL133);
+ tr32(TG3PCI_CLOCK_CTRL);
+ udelay(40);
+ }
- if ((power_caps & PCI_PM_CAP_PME_D3cold) &&
+ if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) &&
(tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) {
- /* Move to auxilliary power. */
- tw32(GRC_LOCAL_CTRL,
- (GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1));
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ tw32(GRC_LOCAL_CTRL,
+ (GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1));
+ tr32(GRC_LOCAL_CTRL);
+ udelay(100);
+ } else {
+ tw32(GRC_LOCAL_CTRL,
+ (GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 |
+ GRC_LCLCTRL_GPIO_OUTPUT2));
+ tr32(GRC_LOCAL_CTRL);
+ udelay(100);
+
+ tw32(GRC_LOCAL_CTRL,
+ (GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 |
+ GRC_LCLCTRL_GPIO_OUTPUT2));
+ tr32(GRC_LOCAL_CTRL);
+ udelay(100);
+
+ tw32(GRC_LOCAL_CTRL,
+ (GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 |
+ GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1));
+ tr32(GRC_LOCAL_CTRL);
+ udelay(100);
+ }
}
/* Finally, set the new power state. */
@@ -490,9 +609,9 @@
static void tg3_link_report(struct tg3 *tp)
{
if (!netif_carrier_ok(tp->dev)) {
- printk("%s: Link is down.\n", tp->dev->name);
+ printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name);
} else {
- printk("%s: Link is up at %d Mbps, %s duplex.\n",
+ printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
tp->dev->name,
(tp->link_config.active_speed == SPEED_1000 ?
1000 :
@@ -501,7 +620,8 @@
(tp->link_config.active_duplex == DUPLEX_FULL ?
"full" : "half"));
- printk("%s: Flow control is %s for TX and %s for RX.\n",
+ printk(KERN_INFO PFX "%s: Flow control is %s for TX and "
+ "%s for RX.\n",
tp->dev->name,
(tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "on" : "off",
(tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "on" : "off");
@@ -634,8 +754,9 @@
new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
if (tp->link_config.advertising & ADVERTISED_1000baseT_Full)
new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
- if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+ if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) &&
+ (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0))
new_adv |= (MII_TG3_CTRL_AS_MASTER |
MII_TG3_CTRL_ENABLE_AS_MASTER);
tg3_writephy(tp, MII_TG3_CTRL, new_adv);
@@ -785,11 +906,16 @@
tw32(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
+ tr32(MAC_STATUS);
+ udelay(40);
tp->mi_mode = MAC_MI_MODE_BASE;
tw32(MAC_MI_MODE, tp->mi_mode);
+ tr32(MAC_MI_MODE);
udelay(40);
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
+
if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
tg3_readphy(tp, MII_BMSR, &bmsr);
tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -947,16 +1073,15 @@
tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
- if (current_link_up == 1)
- tp->mac_mode |= MAC_MODE_LINK_POLARITY;
- tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1);
- } else {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
if ((tp->led_mode == led_mode_link10) ||
(current_link_up == 1 &&
tp->link_config.active_speed == SPEED_10))
tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ } else {
+ if (current_link_up == 1)
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1);
}
/* ??? Without this setting Netgear GA302T PHY does not
@@ -966,10 +1091,13 @@
tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
tw32(MAC_MI_MODE, tp->mi_mode);
+ tr32(MAC_MI_MODE);
udelay(40);
}
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
if (tp->tg3_flags &
(TG3_FLAG_USE_LINKCHG_REG |
@@ -979,6 +1107,8 @@
} else {
tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
}
+ tr32(MAC_EVENT);
+ udelay(40);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
current_link_up == 1 &&
@@ -989,6 +1119,8 @@
tw32(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
+ tr32(MAC_STATUS);
+ udelay(40);
tg3_write_mem(tp,
NIC_SRAM_FIRMWARE_MBOX,
NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
@@ -1150,6 +1282,9 @@
tw32(MAC_TX_AUTO_NEG, 0);
tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
+
ret = ANEG_TIMER_ENAB;
ap->state = ANEG_STATE_RESTART;
@@ -1173,6 +1308,8 @@
tw32(MAC_TX_AUTO_NEG, ap->txconfig);
tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
ap->state = ANEG_STATE_ABILITY_DETECT;
break;
@@ -1188,6 +1325,8 @@
tw32(MAC_TX_AUTO_NEG, ap->txconfig);
tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
ap->state = ANEG_STATE_ACK_DETECT;
@@ -1273,6 +1412,8 @@
ap->link_time = ap->cur_time;
tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
ap->state = ANEG_STATE_IDLE_DETECT;
ret = ANEG_TIMER_ENAB;
@@ -1329,6 +1470,7 @@
tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
udelay(40);
/* Reset when initting first time or we have a link. */
@@ -1379,6 +1521,8 @@
tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
else
tw32(MAC_EVENT, 0);
+ tr32(MAC_EVENT);
+ udelay(40);
current_link_up = 0;
if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
@@ -1396,9 +1540,12 @@
tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
tw32(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
- udelay(20);
+ tr32(MAC_MODE);
+ udelay(40);
tw32(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+ tr32(MAC_MODE);
+ udelay(40);
aninfo.state = ANEG_STATE_UNKNOWN;
aninfo.cur_time = 0;
@@ -1414,6 +1561,8 @@
tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
if (status == ANEG_DONE &&
(aninfo.flags &
@@ -1439,8 +1588,8 @@
tw32(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
-
- udelay(20);
+ tr32(MAC_STATUS);
+ udelay(40);
if ((tr32(MAC_STATUS) &
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED)) == 0)
@@ -1458,6 +1607,8 @@
tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
tp->hw_status->status =
(SD_STATUS_UPDATED |
@@ -1468,8 +1619,8 @@
tw32(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
-
- udelay(20);
+ tr32(MAC_STATUS);
+ udelay(40);
if ((tr32(MAC_STATUS) &
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED)) == 0)
@@ -1505,9 +1656,12 @@
if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
tw32(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
+ tr32(MAC_MODE);
+ udelay(40);
if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
- udelay(1);
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
}
}
@@ -1549,7 +1703,7 @@
u32 sw_idx = tp->tx_cons;
while (sw_idx != hw_idx) {
- struct ring_info *ri = &tp->tx_buffers[sw_idx];
+ struct tx_ring_info *ri = &tp->tx_buffers[sw_idx];
struct sk_buff *skb = ri->skb;
int i;
@@ -1725,7 +1879,7 @@
#if TG3_VLAN_TAG_USED
static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag)
{
- return vlan_hwaccel_rx(skb, tp->vlgrp, vlan_tag);
+ return vlan_hwaccel_receive_skb(skb, tp->vlgrp, vlan_tag);
}
#endif
@@ -1753,16 +1907,18 @@
* If both the host and chip were to write into the same ring, cache line
* eviction could occur since both entities want it in an exclusive state.
*/
-static void tg3_rx(struct tg3 *tp)
+static int tg3_rx(struct tg3 *tp, int budget)
{
u32 work_mask;
u32 rx_rcb_ptr = tp->rx_rcb_ptr;
u16 hw_idx, sw_idx;
+ int received;
hw_idx = tp->hw_status->idx[0].rx_producer;
sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE;
work_mask = 0;
- while (sw_idx != hw_idx) {
+ received = 0;
+ while (sw_idx != hw_idx && budget > 0) {
struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx];
unsigned int len;
struct sk_buff *skb;
@@ -1860,9 +2016,11 @@
desc->err_vlan & RXD_VLAN_MASK);
} else
#endif
- netif_rx(skb);
+ netif_receive_skb(skb);
tp->dev->last_rx = jiffies;
+ received++;
+ budget--;
next_pkt:
(*post_ptr)++;
@@ -1875,129 +2033,44 @@
tp->rx_rcb_ptr = rx_rcb_ptr;
tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
(rx_rcb_ptr % TG3_RX_RCB_RING_SIZE));
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
/* Refill RX ring(s). */
if (work_mask & RXD_OPAQUE_RING_STD) {
sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE;
tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
sw_idx);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
}
if (work_mask & RXD_OPAQUE_RING_JUMBO) {
sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE;
tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
sw_idx);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
}
#if TG3_MINI_RING_WORKS
if (work_mask & RXD_OPAQUE_RING_MINI) {
sw_idx = tp->rx_mini_ptr % TG3_RX_MINI_RING_SIZE;
tw32_mailbox(MAILBOX_RCV_MINI_PROD_IDX + TG3_64BIT_REG_LOW,
sw_idx);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCV_MINI_PROD_IDX + TG3_64BIT_REG_LOW);
}
#endif
-}
-
-#define PKT_RATE_LOW 22000
-#define PKT_RATE_HIGH 61000
-
-static void tg3_rate_sample(struct tg3 *tp, unsigned long ticks)
-{
- u32 delta, rx_now, tx_now;
- int new_vals, do_tx, do_rx;
- rx_now = tp->hw_stats->rx_ucast_packets.low;
- tx_now = tp->hw_stats->COS_out_packets[0].low;
-
- delta = (rx_now - tp->last_rx_count);
- delta += (tx_now - tp->last_tx_count);
- delta /= (ticks / tp->coalesce_config.rate_sample_jiffies);
-
- tp->last_rx_count = rx_now;
- tp->last_tx_count = tx_now;
-
- new_vals = 0;
- do_tx = (tp->tg3_flags & TG3_FLAG_ADAPTIVE_TX) != 0;
- do_rx = (tp->tg3_flags & TG3_FLAG_ADAPTIVE_RX) != 0;
- if (delta < tp->coalesce_config.pkt_rate_low) {
- if (do_rx &&
- tp->coalesce_config.rx_max_coalesced_frames !=
- tp->coalesce_config.rx_max_coalesced_frames_low) {
- tp->coalesce_config.rx_max_coalesced_frames =
- LOW_RXMAX_FRAMES;
- tp->coalesce_config.rx_coalesce_ticks =
- LOW_RXCOL_TICKS;
- new_vals = 1;
- }
- if (do_tx &&
- tp->coalesce_config.tx_max_coalesced_frames !=
- tp->coalesce_config.tx_max_coalesced_frames_low) {
- tp->coalesce_config.tx_max_coalesced_frames =
- tp->coalesce_config.tx_max_coalesced_frames_low;
- tp->coalesce_config.tx_coalesce_ticks =
- tp->coalesce_config.tx_coalesce_ticks_low;
- new_vals = 1;
- }
- } else if (delta < tp->coalesce_config.pkt_rate_high) {
- if (do_rx &&
- tp->coalesce_config.rx_max_coalesced_frames !=
- tp->coalesce_config.rx_max_coalesced_frames_def) {
- tp->coalesce_config.rx_max_coalesced_frames =
- tp->coalesce_config.rx_max_coalesced_frames_def;
- tp->coalesce_config.rx_coalesce_ticks =
- tp->coalesce_config.rx_coalesce_ticks_def;
- new_vals = 1;
- }
- if (do_tx &&
- tp->coalesce_config.tx_max_coalesced_frames !=
- tp->coalesce_config.tx_max_coalesced_frames_def) {
- tp->coalesce_config.tx_max_coalesced_frames =
- tp->coalesce_config.tx_max_coalesced_frames_def;
- tp->coalesce_config.tx_coalesce_ticks =
- tp->coalesce_config.tx_coalesce_ticks_def;
- new_vals = 1;
- }
- } else {
- if (do_rx &&
- tp->coalesce_config.rx_max_coalesced_frames !=
- tp->coalesce_config.rx_max_coalesced_frames_high) {
- tp->coalesce_config.rx_max_coalesced_frames =
- tp->coalesce_config.rx_max_coalesced_frames_high;
- tp->coalesce_config.rx_coalesce_ticks =
- tp->coalesce_config.rx_coalesce_ticks_high;
- new_vals = 1;
- }
- if (do_tx &&
- tp->coalesce_config.tx_max_coalesced_frames !=
- tp->coalesce_config.tx_max_coalesced_frames_high) {
- tp->coalesce_config.tx_max_coalesced_frames =
- tp->coalesce_config.tx_max_coalesced_frames_high;
- tp->coalesce_config.tx_coalesce_ticks =
- tp->coalesce_config.tx_coalesce_ticks_high;
- new_vals = 1;
- }
- }
-
- if (new_vals) {
- if (do_rx) {
- tw32(HOSTCC_RXCOL_TICKS,
- tp->coalesce_config.rx_coalesce_ticks);
- tw32(HOSTCC_RXMAX_FRAMES,
- tp->coalesce_config.rx_max_coalesced_frames);
- }
- if (do_tx) {
- tw32(HOSTCC_TXCOL_TICKS,
- tp->coalesce_config.tx_coalesce_ticks);
- tw32(HOSTCC_TXMAX_FRAMES,
- tp->coalesce_config.tx_max_coalesced_frames);
- }
- }
-
- tp->last_rate_sample = jiffies;
+ return received;
}
-static void tg3_interrupt_main_work(struct tg3 *tp)
+static int tg3_poll(struct net_device *netdev, int *budget)
{
+ struct tg3 *tp = netdev->priv;
struct tg3_hw_status *sblk = tp->hw_status;
- int did_pkts;
+ int done;
+
+ spin_lock_irq(&tp->lock);
if (!(tp->tg3_flags &
(TG3_FLAG_USE_LINKCHG_REG |
@@ -2009,84 +2082,91 @@
}
}
- did_pkts = 0;
- if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
- tg3_rx(tp);
- did_pkts = 1;
- }
-
if (sblk->idx[0].tx_consumer != tp->tx_cons) {
+ spin_lock(&tp->tx_lock);
tg3_tx(tp);
- did_pkts = 1;
+ spin_unlock(&tp->tx_lock);
}
- if (did_pkts &&
- (tp->tg3_flags & (TG3_FLAG_ADAPTIVE_RX | TG3_FLAG_ADAPTIVE_TX))) {
- unsigned long ticks = jiffies - tp->last_rate_sample;
+ done = 1;
+ if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
+ int orig_budget = *budget;
+ int work_done;
+
+ if (orig_budget > netdev->quota)
+ orig_budget = netdev->quota;
+
+ work_done = tg3_rx(tp, orig_budget);
- if (ticks >= tp->coalesce_config.rate_sample_jiffies)
- tg3_rate_sample(tp, ticks);
+ *budget -= work_done;
+ netdev->quota -= work_done;
+
+ if (work_done >= orig_budget)
+ done = 0;
}
+
+ if (done) {
+ netif_rx_complete(netdev);
+ tg3_unmask_ints(tp);
+ }
+
+ spin_unlock_irq(&tp->lock);
+
+ return (done ? 0 : 1);
}
-static void tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static __inline__ void tg3_interrupt_main_work(struct net_device *dev, struct tg3 *tp)
{
- struct net_device *dev = dev_id;
- struct tg3 *tp = dev->priv;
struct tg3_hw_status *sblk = tp->hw_status;
+ int work_exists = 0;
- spin_lock(&tp->lock);
-
- while (sblk->status & SD_STATUS_UPDATED) {
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000001);
- sblk->status &= ~SD_STATUS_UPDATED;
+ if (!(tp->tg3_flags &
+ (TG3_FLAG_USE_LINKCHG_REG |
+ TG3_FLAG_POLL_SERDES))) {
+ if (sblk->status & SD_STATUS_LINK_CHG)
+ work_exists = 1;
+ }
+ if (sblk->idx[0].tx_consumer != tp->tx_cons ||
+ sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
+ work_exists = 1;
- tg3_interrupt_main_work(tp);
+ if (!work_exists)
+ return;
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ if (netif_rx_schedule_prep(dev)) {
+ /* NOTE: These writes are posted by the readback of
+ * the mailbox register done by our caller.
+ */
+ tg3_mask_ints(tp);
+ __netif_rx_schedule(dev);
+ } else {
+ printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
+ dev->name);
}
-
- spin_unlock(&tp->lock);
}
-static void tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs)
+static void tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct tg3 *tp = dev->priv;
struct tg3_hw_status *sblk = tp->hw_status;
+ unsigned long flags;
- spin_lock(&tp->lock);
+ spin_lock_irqsave(&tp->lock, flags);
if (sblk->status & SD_STATUS_UPDATED) {
- u32 oldtag;
-
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001);
- oldtag = sblk->status_tag;
-
- while (1) {
- u32 newtag;
-
- sblk->status &= ~SD_STATUS_UPDATED;
- barrier();
+ sblk->status &= ~SD_STATUS_UPDATED;
- tg3_interrupt_main_work(tp);
+ tg3_interrupt_main_work(dev, tp);
- newtag = sblk->status_tag;
- if (newtag == oldtag) {
- tw32_mailbox(MAILBOX_INTERRUPT_0 +
- TG3_64BIT_REG_LOW,
- newtag << 24);
- break;
- }
- oldtag = newtag;
- }
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000000);
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
- spin_unlock(&tp->lock);
+ spin_unlock_irqrestore(&tp->lock, flags);
}
static void tg3_init_rings(struct tg3 *);
@@ -2096,15 +2176,17 @@
{
struct tg3 *tp = dev->priv;
- printk(KERN_ERR "%s: transmit timed out, resetting\n",
+ printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
dev->name);
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_halt(tp);
tg3_init_rings(tp);
tg3_init_hw(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_wake_queue(dev);
@@ -2136,11 +2218,11 @@
}
#endif
-static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, int);
+static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
u32 guilty_entry, int guilty_len,
- u32 last_plus_one, u32 *start)
+ u32 last_plus_one, u32 *start, u32 mss)
{
dma_addr_t new_addr;
u32 entry = *start;
@@ -2193,7 +2275,7 @@
PCI_DMA_TODEVICE);
tg3_set_txd(tp, entry, new_addr, new_skb->len,
(skb->ip_summed == CHECKSUM_HW) ?
- TXD_FLAG_TCPUDP_CSUM : 0, 1);
+ TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
*start = NEXT_TX(entry);
/* Now clean up the sw ring entries. */
@@ -2225,30 +2307,28 @@
static void tg3_set_txd(struct tg3 *tp, int entry,
dma_addr_t mapping, int len, u32 flags,
- int is_end)
+ u32 mss_and_is_end)
{
-#if TG3_VLAN_TAG_USED
- u16 vlan_tag = 0;
-#endif
+ int is_end = (mss_and_is_end & 0x1);
+ u32 mss = (mss_and_is_end >> 1);
+ u32 vlan_tag = 0;
if (is_end)
flags |= TXD_FLAG_END;
-#if TG3_VLAN_TAG_USED
if (flags & TXD_FLAG_VLAN) {
vlan_tag = flags >> 16;
flags &= 0xffff;
}
-#endif
+ vlan_tag |= (mss << TXD_MSS_SHIFT);
if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
txd->addr_hi = ((u64) mapping >> 32);
txd->addr_lo = ((u64) mapping & 0xffffffff);
txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-#if TG3_VLAN_TAG_USED
txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
-#endif
} else {
+ struct tx_ring_info *txr = &tp->tx_buffers[entry];
unsigned long txd;
txd = (tp->regs +
@@ -2264,9 +2344,10 @@
writel(((u64) mapping & 0xffffffff),
txd + TXD_ADDR + TG3_64BIT_REG_LOW);
writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS);
-#if TG3_VLAN_TAG_USED
- writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
-#endif
+ if (txr->prev_vlan_tag != vlan_tag) {
+ writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
+ txr->prev_vlan_tag = vlan_tag;
+ }
}
}
@@ -2284,17 +2365,37 @@
struct tg3 *tp = dev->priv;
dma_addr_t mapping;
unsigned int i;
- u32 len, entry, base_flags;
+ u32 len, entry, base_flags, mss;
int would_hit_hwbug;
+ unsigned long flags;
len = (skb->len - skb->data_len);
- spin_lock_irq(&tp->lock);
+ /* No BH disabling for tx_lock here. We are running in BH disabled
+ * context and TX reclaim runs via tp->poll inside of a software
+ * interrupt. Rejoice!
+ *
+ * Actually, things are not so simple. If we are to take a hw
+ * IRQ here, we can deadlock, consider:
+ *
+ * CPU1 CPU2
+ * tg3_start_xmit
+ * take tp->tx_lock
+ * tg3_timer
+ * take tp->lock
+ * tg3_interrupt
+ * spin on tp->lock
+ * spin on tp->tx_lock
+ *
+ * So we really do need to disable interrupts when taking
+ * tx_lock here.
+ */
+ spin_lock_irqsave(&tp->tx_lock, flags);
/* This is a hard error, log it. */
if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
netif_stop_queue(dev);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
return 1;
@@ -2304,6 +2405,13 @@
base_flags = 0;
if (skb->ip_summed == CHECKSUM_HW)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
+#if TG3_DO_TSO != 0
+ if ((mss = skb_shinfo(skb)->tso_size) != 0)
+ base_flags |= (TXD_FLAG_CPU_PRE_DMA |
+ TXD_FLAG_CPU_POST_DMA);
+#else
+ mss = 0;
+#endif
#if TG3_VLAN_TAG_USED
if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
@@ -2322,7 +2430,7 @@
would_hit_hwbug = entry + 1;
tg3_set_txd(tp, entry, mapping, len, base_flags,
- (skb_shinfo(skb)->nr_frags == 0));
+ (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
entry = NEXT_TX(entry);
@@ -2351,7 +2459,7 @@
}
tg3_set_txd(tp, entry, mapping, len,
- base_flags, (i == last));
+ base_flags, (i == last) | (mss << 1));
entry = NEXT_TX(entry);
}
@@ -2387,7 +2495,7 @@
if (tigon3_4gb_hwbug_workaround(tp, skb,
entry, len,
last_plus_one,
- &start))
+ &start, mss))
goto out_unlock;
entry = start;
@@ -2400,12 +2508,27 @@
if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
TG3_64BIT_REG_LOW), entry);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
+ TG3_64BIT_REG_LOW);
} else {
+ /* First, make sure tg3 sees last descriptor fully
+ * in SRAM.
+ */
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
+ TG3_64BIT_REG_LOW);
+
tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
TG3_64BIT_REG_LOW), entry);
if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
TG3_64BIT_REG_LOW), entry);
+
+ /* Now post the mailbox write itself. */
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
+ TG3_64BIT_REG_LOW);
}
tp->tx_prod = entry;
@@ -2413,7 +2536,7 @@
netif_stop_queue(dev);
out_unlock:
- spin_unlock_irq(&tp->lock);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
dev->trans_start = jiffies;
@@ -2424,16 +2547,36 @@
{
struct tg3 *tp = dev->priv;
dma_addr_t mapping;
- u32 len, entry, base_flags;
+ u32 len, entry, base_flags, mss;
+ unsigned long flags;
len = (skb->len - skb->data_len);
- spin_lock_irq(&tp->lock);
+ /* No BH disabling for tx_lock here. We are running in BH disabled
+ * context and TX reclaim runs via tp->poll inside of a software
+ * interrupt. Rejoice!
+ *
+ * Actually, things are not so simple. If we are to take a hw
+ * IRQ here, we can deadlock, consider:
+ *
+ * CPU1 CPU2
+ * tg3_start_xmit
+ * take tp->tx_lock
+ * tg3_timer
+ * take tp->lock
+ * tg3_interrupt
+ * spin on tp->lock
+ * spin on tp->tx_lock
+ *
+ * So we really do need to disable interrupts when taking
+ * tx_lock here.
+ */
+ spin_lock_irqsave(&tp->tx_lock, flags);
/* This is a hard error, log it. */
if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
netif_stop_queue(dev);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
return 1;
@@ -2443,6 +2586,13 @@
base_flags = 0;
if (skb->ip_summed == CHECKSUM_HW)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
+#if TG3_DO_TSO != 0
+ if ((mss = skb_shinfo(skb)->tso_size) != 0)
+ base_flags |= (TXD_FLAG_CPU_PRE_DMA |
+ TXD_FLAG_CPU_POST_DMA);
+#else
+ mss = 0;
+#endif
#if TG3_VLAN_TAG_USED
if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
@@ -2456,7 +2606,7 @@
pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len, base_flags,
- (skb_shinfo(skb)->nr_frags == 0));
+ (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
entry = NEXT_TX(entry);
@@ -2479,7 +2629,7 @@
pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len,
- base_flags, (i == last));
+ base_flags, (i == last) | (mss << 1));
entry = NEXT_TX(entry);
}
@@ -2493,16 +2643,31 @@
if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
TG3_64BIT_REG_LOW), entry);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
+ TG3_64BIT_REG_LOW);
} else {
+ /* First, make sure tg3 sees last descriptor fully
+ * in SRAM.
+ */
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
+ TG3_64BIT_REG_LOW);
+
tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
TG3_64BIT_REG_LOW), entry);
+
+ /* Now post the mailbox write itself. */
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
+ TG3_64BIT_REG_LOW);
}
tp->tx_prod = entry;
if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
netif_stop_queue(dev);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
dev->trans_start = jiffies;
@@ -2525,6 +2690,7 @@
}
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_halt(tp);
@@ -2538,6 +2704,7 @@
tg3_init_rings(tp);
tg3_init_hw(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return 0;
@@ -2547,7 +2714,7 @@
*
* The chip has been shut down and the driver detached from
* the networking, so no interrupts or new tx packets will
- * end up in the driver. tp->lock is not held and we are not
+ * end up in the driver. tp->{tx,}lock is not held and we are not
* in an interrupt context and thus may sleep.
*/
static void tg3_free_rings(struct tg3 *tp)
@@ -2564,7 +2731,7 @@
pci_unmap_addr(rxp, mapping),
RX_PKT_BUF_SZ - tp->rx_offset,
PCI_DMA_FROMDEVICE);
- dev_kfree_skb(rxp->skb);
+ dev_kfree_skb_any(rxp->skb);
rxp->skb = NULL;
}
#if TG3_MINI_RING_WORKS
@@ -2577,7 +2744,7 @@
pci_unmap_addr(rxp, mapping),
RX_MINI_PKT_BUF_SZ - tp->rx_offset,
PCI_DMA_FROMDEVICE);
- dev_kfree_skb(rxp->skb);
+ dev_kfree_skb_any(rxp->skb);
rxp->skb = NULL;
}
#endif
@@ -2590,12 +2757,12 @@
pci_unmap_addr(rxp, mapping),
RX_JUMBO_PKT_BUF_SZ - tp->rx_offset,
PCI_DMA_FROMDEVICE);
- dev_kfree_skb(rxp->skb);
+ dev_kfree_skb_any(rxp->skb);
rxp->skb = NULL;
}
for (i = 0; i < TG3_TX_RING_SIZE; ) {
- struct ring_info *txp;
+ struct tx_ring_info *txp;
struct sk_buff *skb;
int j;
@@ -2632,7 +2799,7 @@
*
* The chip has been shut down and the driver detached from
* the networking, so no interrupts or new tx packets will
- * end up in the driver. tp->lock is not held and we are not
+ * end up in the driver. tp->{tx,}lock is not held and we are not
* in an interrupt context and thus may sleep.
*/
static void tg3_init_rings(struct tg3 *tp)
@@ -2662,6 +2829,8 @@
writel(0, start);
start += 4;
}
+ for (i = 0; i < TG3_TX_RING_SIZE; i++)
+ tp->tx_buffers[i].prev_vlan_tag = 0;
}
/* Initialize invariants of the rings, we only set this
@@ -2784,12 +2953,13 @@
*/
static int tg3_alloc_consistent(struct tg3 *tp)
{
- tp->rx_std_buffers = kmalloc(sizeof(struct ring_info) *
- (TG3_RX_RING_SIZE +
+ tp->rx_std_buffers = kmalloc((sizeof(struct ring_info) *
+ (TG3_RX_RING_SIZE +
#if TG3_MINI_RING_WORKS
- TG3_RX_MINI_RING_SIZE +
+ TG3_RX_MINI_RING_SIZE +
#endif
- TG3_RX_JUMBO_RING_SIZE +
+ TG3_RX_JUMBO_RING_SIZE)) +
+ (sizeof(struct tx_ring_info) *
TG3_TX_RING_SIZE),
GFP_KERNEL);
if (!tp->rx_std_buffers)
@@ -2800,14 +2970,16 @@
(sizeof(struct ring_info) *
(TG3_RX_RING_SIZE +
TG3_RX_MINI_RING_SIZE +
- TG3_RX_JUMBO_RING_SIZE +
- TG3_TX_RING_SIZE)));
+ TG3_RX_JUMBO_RING_SIZE)) +
+ (sizeof(struct tx_ring_info) *
+ TG3_TX_RING_SIZE));
#else
memset(tp->rx_std_buffers, 0,
(sizeof(struct ring_info) *
(TG3_RX_RING_SIZE +
- TG3_RX_JUMBO_RING_SIZE +
- TG3_TX_RING_SIZE)));
+ TG3_RX_JUMBO_RING_SIZE)) +
+ (sizeof(struct tx_ring_info) *
+ TG3_TX_RING_SIZE));
#endif
#if TG3_MINI_RING_WORKS
@@ -2816,7 +2988,8 @@
#else
tp->rx_jumbo_buffers = &tp->rx_std_buffers[TG3_RX_RING_SIZE];
#endif
- tp->tx_buffers = &tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE];
+ tp->tx_buffers = (struct tx_ring_info *)
+ &tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE];
tp->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES,
&tp->rx_std_mapping);
@@ -2874,7 +3047,7 @@
return -ENOMEM;
}
-#define MAX_WAIT_CNT 10000
+#define MAX_WAIT_CNT 1000
/* To stop a block, clear the enable bit and poll till it
* clears. tp->lock is held.
@@ -2887,13 +3060,13 @@
val = tr32(ofs);
val &= ~enable_bit;
tw32(ofs, val);
+ tr32(ofs);
for (i = 0; i < MAX_WAIT_CNT; i++) {
+ udelay(100);
val = tr32(ofs);
-
if ((val & enable_bit) == 0)
break;
- udelay(100);
}
if (i == MAX_WAIT_CNT) {
@@ -2915,6 +3088,8 @@
tp->rx_mode &= ~RX_MODE_ENABLE;
tw32(MAC_RX_MODE, tp->rx_mode);
+ tr32(MAC_RX_MODE);
+ udelay(10);
err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
@@ -2934,9 +3109,13 @@
tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
tp->tx_mode &= ~TX_MODE_ENABLE;
tw32(MAC_TX_MODE, tp->tx_mode);
+ tr32(MAC_TX_MODE);
+
for (i = 0; i < MAX_WAIT_CNT; i++) {
udelay(100);
if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
@@ -2988,6 +3167,14 @@
}
tw32(GRC_MISC_CFG, GRC_MISC_CFG_CORECLK_RESET);
+
+ /* Flush PCI posted writes. The normal MMIO registers
+ * are inaccessible at this time so this is the only
+ * way to make this reliably. I tried to use indirect
+ * register read/write but this upset some 5701 variants.
+ */
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
+
udelay(40);
udelay(40);
udelay(40);
@@ -2997,9 +3184,11 @@
tp->misc_host_ctrl);
/* Set MAX PCI retry to zero. */
- pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE,
- (PCISTATE_ROM_ENABLE |
- PCISTATE_ROM_RETRY_ENABLE));
+ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
+ val |= PCISTATE_RETRY_SAME_DMA;
+ pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
pci_restore_state(tp->pdev, tp->pci_cfg_state);
@@ -3014,11 +3203,33 @@
}
/* tp->lock is held. */
+static void tg3_stop_fw(struct tg3 *tp)
+{
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+ u32 val;
+ int i;
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
+ val = tr32(GRC_RX_CPU_EVENT);
+ val |= (1 << 14);
+ tw32(GRC_RX_CPU_EVENT, val);
+
+ /* Wait for RX cpu to ACK the event. */
+ for (i = 0; i < 100; i++) {
+ if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
+ break;
+ udelay(1);
+ }
+ }
+}
+
+/* tp->lock is held. */
static int tg3_halt(struct tg3 *tp)
{
u32 val;
int i;
+ tg3_stop_fw(tp);
tg3_abort_hw(tp);
tg3_chip_reset(tp);
tg3_write_mem(tp,
@@ -3038,6 +3249,17 @@
return -ENODEV;
}
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+ if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_WOL);
+ else
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_UNLOAD);
+ } else
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_SUSPEND);
+
return 0;
}
@@ -3056,7 +3278,7 @@
#define TG3_FW_BSS_ADDR 0x08000a70
#define TG3_FW_BSS_LEN 0x10
-static u32 t3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
+static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000,
0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034,
@@ -3150,7 +3372,7 @@
0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000
};
-static u32 t3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
+static u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430,
0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
@@ -3159,7 +3381,7 @@
};
#if 0 /* All zeros, dont eat up space with it. */
-u32 t3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = {
+u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
@@ -3183,6 +3405,7 @@
break;
tw32(offset + CPU_STATE, 0xffffffff);
tw32(offset + CPU_MODE, CPU_MODE_RESET);
+ tr32(offset + CPU_MODE);
udelay(10);
} else {
for (i = 0; i < 10000; i++) {
@@ -3190,6 +3413,7 @@
break;
tw32(offset + CPU_STATE, 0xffffffff);
tw32(offset + CPU_MODE, CPU_MODE_RESET);
+ tr32(offset + CPU_MODE);
udelay(10);
}
}
@@ -3204,51 +3428,89 @@
return 0;
}
+struct fw_info {
+ unsigned int text_base;
+ unsigned int text_len;
+ u32 *text_data;
+ unsigned int rodata_base;
+ unsigned int rodata_len;
+ u32 *rodata_data;
+ unsigned int data_base;
+ unsigned int data_len;
+ u32 *data_data;
+};
+
/* tp->lock is held. */
static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base,
- int cpu_scratch_size)
+ int cpu_scratch_size, struct fw_info *info)
{
int err, i;
+ u32 orig_tg3_flags = tp->tg3_flags;
+
+ /* Force use of PCI config space for indirect register
+ * write calls.
+ */
+ tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
err = tg3_reset_cpu(tp, cpu_base);
if (err)
- return err;
+ goto out;
for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
tg3_write_indirect_reg32(tp, cpu_scratch_base + i, 0);
tw32(cpu_base + CPU_STATE, 0xffffffff);
tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
- for (i = 0; i < (TG3_FW_TEXT_LEN / sizeof(u32)); i++)
+ for (i = 0; i < (info->text_len / sizeof(u32)); i++)
tg3_write_indirect_reg32(tp, (cpu_scratch_base +
- (TG3_FW_TEXT_ADDR & 0xffff) +
+ (info->text_base & 0xffff) +
(i * sizeof(u32))),
- t3FwText[i]);
- for (i = 0; i < (TG3_FW_RODATA_LEN / sizeof(u32)); i++)
+ (info->text_data ?
+ info->text_data[i] : 0));
+ for (i = 0; i < (info->rodata_len / sizeof(u32)); i++)
tg3_write_indirect_reg32(tp, (cpu_scratch_base +
- (TG3_FW_RODATA_ADDR & 0xffff) +
+ (info->rodata_base & 0xffff) +
(i * sizeof(u32))),
- t3FwRodata[i]);
- for (i = 0; i < (TG3_FW_DATA_LEN / sizeof(u32)); i++)
+ (info->rodata_data ?
+ info->rodata_data[i] : 0));
+ for (i = 0; i < (info->data_len / sizeof(u32)); i++)
tg3_write_indirect_reg32(tp, (cpu_scratch_base +
- (TG3_FW_DATA_ADDR & 0xffff) +
+ (info->data_base & 0xffff) +
(i * sizeof(u32))),
- 0);
+ (info->data_data ?
+ info->data_data[i] : 0));
- return 0;
+ err = 0;
+
+out:
+ tp->tg3_flags = orig_tg3_flags;
+ return err;
}
/* tp->lock is held. */
static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
{
+ struct fw_info info;
int err, i;
+ info.text_base = TG3_FW_TEXT_ADDR;
+ info.text_len = TG3_FW_TEXT_LEN;
+ info.text_data = &tg3FwText[0];
+ info.rodata_base = TG3_FW_RODATA_ADDR;
+ info.rodata_len = TG3_FW_RODATA_LEN;
+ info.rodata_data = &tg3FwRodata[0];
+ info.data_base = TG3_FW_DATA_ADDR;
+ info.data_len = TG3_FW_DATA_LEN;
+ info.data_data = NULL;
+
err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
- RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE);
+ RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
+ &info);
if (err)
return err;
err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
- TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE);
+ TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
+ &info);
if (err)
return err;
@@ -3286,6 +3548,336 @@
return 0;
}
+#if TG3_DO_TSO != 0
+
+#define TG3_TSO_FW_RELEASE_MAJOR 0x1
+#define TG3_TSO_FW_RELASE_MINOR 0x8
+#define TG3_TSO_FW_RELEASE_FIX 0x0
+#define TG3_TSO_FW_START_ADDR 0x08000000
+#define TG3_TSO_FW_TEXT_ADDR 0x08000000
+#define TG3_TSO_FW_TEXT_LEN 0x1650
+#define TG3_TSO_FW_RODATA_ADDR 0x08001650
+#define TG3_TSO_FW_RODATA_LEN 0x30
+#define TG3_TSO_FW_DATA_ADDR 0x080016a0
+#define TG3_TSO_FW_DATA_LEN 0x20
+#define TG3_TSO_FW_SBSS_ADDR 0x080016c0
+#define TG3_TSO_FW_SBSS_LEN 0x14
+#define TG3_TSO_FW_BSS_ADDR 0x080016e0
+#define TG3_TSO_FW_BSS_LEN 0x8fc
+
+static u32 tg3TsoFwText[] = {
+ 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
+ 0x37bd4000, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000010, 0x00000000,
+ 0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0x3c1bc000,
+ 0xafbf0018, 0x0e000058, 0xaf60680c, 0x3c040800, 0x24841650, 0x03602821,
+ 0x24060001, 0x24070004, 0xafa00010, 0x0e00006c, 0xafa00014, 0x8f625c50,
+ 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001, 0xaf625c90, 0x2402ffff,
+ 0x0e000098, 0xaf625404, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000,
+ 0x00000000, 0x00000000, 0x24030b60, 0x24050fff, 0xac000b50, 0x00002021,
+ 0xac640000, 0x24630004, 0x0065102b, 0x1440fffc, 0x24840001, 0x24030b60,
+ 0x0065102b, 0x10400011, 0x00002021, 0x24090b54, 0x3c06dead, 0x34c6beef,
+ 0x24080b58, 0x24070b5c, 0x8c620000, 0x50440006, 0x24630004, 0xad260000,
+ 0x8c620000, 0xace40000, 0xad020000, 0x24630004, 0x0065102b, 0x1440fff6,
+ 0x24840001, 0x03e00008, 0x00000000, 0x27bdfff8, 0x18800009, 0x00002821,
+ 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a,
+ 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008, 0x3c020800, 0x34423000,
+ 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac2216c4,
+ 0x24020040, 0x3c010800, 0xac2216c8, 0x3c010800, 0xac2016c0, 0xac600000,
+ 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
+ 0x00804821, 0x8faa0010, 0x3c020800, 0x8c4216c0, 0x3c040800, 0x8c8416c8,
+ 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac2316c0, 0x14400003,
+ 0x00004021, 0x3c010800, 0xac2016c0, 0x3c020800, 0x8c4216c0, 0x3c030800,
+ 0x8c6316c4, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
+ 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c4216c0,
+ 0x3c030800, 0x8c6316c4, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008,
+ 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
+ 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x0e0000b6,
+ 0xafb00010, 0x24110001, 0x8f706820, 0x32020100, 0x10400003, 0x00000000,
+ 0x0e000127, 0x00000000, 0x8f706820, 0x32022000, 0x10400004, 0x32020001,
+ 0x0e00025a, 0x24040001, 0x32020001, 0x10400003, 0x00000000, 0x0e0000e6,
+ 0x00000000, 0x0a00009e, 0xaf715028, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841660, 0x00002821,
+ 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00006c, 0xafa00014,
+ 0x3c010800, 0xa4201fb8, 0x3c010800, 0xa02016f8, 0x3c010800, 0xac2016fc,
+ 0x3c010800, 0xac201700, 0x3c010800, 0xac201704, 0x3c010800, 0xac20170c,
+ 0x3c010800, 0xac201718, 0x3c010800, 0xac20171c, 0x8f624434, 0x3c010800,
+ 0xac2216e8, 0x8f624438, 0x3c010800, 0xac2216ec, 0x8f624410, 0x3c010800,
+ 0xac2016e0, 0x3c010800, 0xac2016e4, 0x3c010800, 0xac201fc0, 0x3c010800,
+ 0xac201f68, 0x3c010800, 0xac201f6c, 0x3c010800, 0xac2216f0, 0x8fbf0018,
+ 0x03e00008, 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x2484166c, 0x00002821,
+ 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00006c, 0xafa00014,
+ 0x3c040800, 0x24841660, 0x00002821, 0x00003021, 0x00003821, 0xafa00010,
+ 0x0e00006c, 0xafa00014, 0x3c010800, 0xa4201fb8, 0x3c010800, 0xa02016f8,
+ 0x3c010800, 0xac2016fc, 0x3c010800, 0xac201700, 0x3c010800, 0xac201704,
+ 0x3c010800, 0xac20170c, 0x3c010800, 0xac201718, 0x3c010800, 0xac20171c,
+ 0x8f624434, 0x3c010800, 0xac2216e8, 0x8f624438, 0x3c010800, 0xac2216ec,
+ 0x8f624410, 0x3c010800, 0xac2016e0, 0x3c010800, 0xac2016e4, 0x3c010800,
+ 0xac201fc0, 0x3c010800, 0xac201f68, 0x3c010800, 0xac201f6c, 0x3c010800,
+ 0xac2216f0, 0x0e000120, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020,
+ 0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008,
+ 0xaf636820, 0x27bdffd0, 0x3c0300ff, 0xafbf002c, 0xafb60028, 0xafb50024,
+ 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f665c5c,
+ 0x3c040800, 0x2484171c, 0x8c820000, 0x3463fff8, 0x14460005, 0x00c38824,
+ 0x3c020800, 0x904216f8, 0x14400115, 0x00000000, 0x00111902, 0x306300ff,
+ 0x30c20003, 0x000211c0, 0x00623825, 0x00e02821, 0x00061602, 0xac860000,
+ 0x3c030800, 0x906316f8, 0x3044000f, 0x1460002b, 0x00804021, 0x24020001,
+ 0x3c010800, 0xa02216f8, 0x00071100, 0x00821025, 0x3c010800, 0xac2016fc,
+ 0x3c010800, 0xac201700, 0x3c010800, 0xac201704, 0x3c010800, 0xac20170c,
+ 0x3c010800, 0xac201718, 0x3c010800, 0xac201710, 0x3c010800, 0xac201714,
+ 0x3c010800, 0xa4221fb8, 0x9623000c, 0x30628000, 0x10400008, 0x30627fff,
+ 0x2442003e, 0x3c010800, 0xa42216f6, 0x24020001, 0x3c010800, 0x0a00016e,
+ 0xac221fd4, 0x24620036, 0x3c010800, 0xa42216f6, 0x3c010800, 0xac201fd4,
+ 0x3c010800, 0xac201fd0, 0x3c010800, 0x0a000176, 0xac201fd8, 0x9622000c,
+ 0x3c010800, 0xa4221fcc, 0x3c040800, 0x248416fc, 0x8c820000, 0x00021100,
+ 0x3c010800, 0x00220821, 0xac311728, 0x8c820000, 0x00021100, 0x3c010800,
+ 0x00220821, 0xac26172c, 0x8c820000, 0x24a30001, 0x306701ff, 0x00021100,
+ 0x3c010800, 0x00220821, 0xac271730, 0x8c820000, 0x00021100, 0x3c010800,
+ 0x00220821, 0xac281734, 0x96230008, 0x3c020800, 0x8c42170c, 0x00432821,
+ 0x3c010800, 0xac25170c, 0x9622000a, 0x30420004, 0x14400019, 0x00071100,
+ 0x3c02c000, 0x00c21825, 0xaf635c5c, 0x8f625c50, 0x30420002, 0x1440fffc,
+ 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440001e, 0x00000000,
+ 0x8f630c14, 0x3c020800, 0x8c4216b4, 0x3063000f, 0x24420001, 0x3c010800,
+ 0xac2216b4, 0x2c620002, 0x1040fff7, 0x00000000, 0x0a0001c1, 0x00000000,
+ 0x3c030800, 0x8c6316e0, 0x3c040800, 0x948416f4, 0x01021025, 0x3c010800,
+ 0xa4221fba, 0x24020001, 0x3c010800, 0xac221718, 0x24630001, 0x0085202a,
+ 0x3c010800, 0x10800003, 0xac2316e0, 0x3c010800, 0xa42516f4, 0x3c030800,
+ 0x246316fc, 0x8c620000, 0x24420001, 0xac620000, 0x28420080, 0x14400005,
+ 0x24020001, 0x0e0002df, 0x24040002, 0x0a000250, 0x00000000, 0x3c030800,
+ 0x906316f8, 0x1462007c, 0x24020003, 0x3c160800, 0x96d616f6, 0x3c050800,
+ 0x8ca5170c, 0x32c4ffff, 0x00a4102a, 0x14400078, 0x00000000, 0x3c020800,
+ 0x8c421718, 0x10400005, 0x32c2ffff, 0x14a40003, 0x00000000, 0x3c010800,
+ 0xac231fd0, 0x10400062, 0x00009021, 0x0040a021, 0x3c150800, 0x26b51700,
+ 0x26b30010, 0x8ea20000, 0x00028100, 0x3c110800, 0x02308821, 0x0e0002e1,
+ 0x8e311728, 0x00403021, 0x10c00059, 0x00000000, 0x9628000a, 0x31020040,
+ 0x10400004, 0x2407180c, 0x8e22000c, 0x2407188c, 0xacc20018, 0x31021000,
+ 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825, 0x3c030800,
+ 0x00701821, 0x8c631730, 0x3c020800, 0x00501021, 0x8c421734, 0x00031d00,
+ 0x00021400, 0x00621825, 0xacc30014, 0x8ea30004, 0x96220008, 0x00432023,
+ 0x3242ffff, 0x3083ffff, 0x00431021, 0x0282102a, 0x14400002, 0x02d22823,
+ 0x00802821, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000, 0x8e220000,
+ 0xacc20000, 0x8e220004, 0x8e63fff4, 0x00431021, 0xacc20004, 0xa4c5000e,
+ 0x8e62fff4, 0x00441021, 0xae62fff4, 0x96230008, 0x0043102a, 0x14400005,
+ 0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0xae62fff0, 0xacc00008,
+ 0x3242ffff, 0x14540008, 0x24020305, 0x31020080, 0x54400001, 0x34e70010,
+ 0x24020905, 0xa4c2000c, 0x0a000233, 0x34e70020, 0xa4c2000c, 0x30e2ffff,
+ 0xacc20010, 0x3c020800, 0x8c421fd0, 0x10400003, 0x3c024b65, 0x0a00023d,
+ 0x34427654, 0x3c02b49a, 0x344289ab, 0xacc2001c, 0x0e000560, 0x00c02021,
+ 0x3242ffff, 0x0054102b, 0x1440ffa4, 0x00000000, 0x24020002, 0x3c010800,
+ 0x0a000250, 0xa02216f8, 0x8ea208bc, 0x24420001, 0x0a000250, 0xaea208bc,
+ 0x14620003, 0x00000000, 0x0e000450, 0x00000000, 0x8fbf002c, 0x8fb60028,
+ 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0030, 0x27bdffd8, 0xafb3001c, 0x00809821, 0xafbf0020,
+ 0xafb20018, 0xafb10014, 0xafb00010, 0x8f725c9c, 0x3c0200ff, 0x3442fff8,
+ 0x3c040800, 0x24841714, 0x02428824, 0x9623000e, 0x8c820000, 0x00431021,
+ 0xac820000, 0x8e220010, 0x30420020, 0x14400011, 0x00000000, 0x0e0002f7,
+ 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002,
+ 0x10400061, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1040005c,
+ 0x00000000, 0x0a000278, 0x00000000, 0x8e220008, 0x00021c02, 0x000321c0,
+ 0x3042ffff, 0x3c030800, 0x906316f8, 0x000229c0, 0x24020002, 0x14620003,
+ 0x3c034b65, 0x0a000290, 0x00008021, 0x8e22001c, 0x34637654, 0x10430002,
+ 0x24100002, 0x24100001, 0x0e000300, 0x02003021, 0x24020003, 0x3c010800,
+ 0xa02216f8, 0x24020002, 0x1202000a, 0x24020001, 0x3c030800, 0x8c631fd0,
+ 0x10620006, 0x00000000, 0x3c020800, 0x94421fb8, 0x00021400, 0x0a0002cd,
+ 0xae220014, 0x3c040800, 0x24841fba, 0x94820000, 0x00021400, 0xae220014,
+ 0x3c020800, 0x8c42171c, 0x3c03c000, 0x3c010800, 0xa02016f8, 0x00431025,
+ 0xaf625c5c, 0x8f625c50, 0x30420002, 0x10400009, 0x00000000, 0x2484f762,
+ 0x8c820000, 0x00431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa,
+ 0x00000000, 0x3c020800, 0x244216e4, 0x8c430000, 0x24630001, 0xac430000,
+ 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 0x00009821, 0x8f630c14,
+ 0x3c020800, 0x8c4216b4, 0x3063000f, 0x24420001, 0x3c010800, 0xac2216b4,
+ 0x2c620002, 0x1040fff7, 0x00009821, 0x3c024000, 0x02421825, 0xaf635c9c,
+ 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x12600003, 0x00000000,
+ 0x0e000450, 0x00000000, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0028, 0x0a0002df, 0x00000000, 0x8f634450,
+ 0x3c040800, 0x248416e8, 0x8c820000, 0x00031c02, 0x0043102b, 0x14400007,
+ 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc,
+ 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000, 0x00822025, 0xaf645c38,
+ 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000, 0x03e00008, 0x00000000,
+ 0x27bdffe0, 0x00805021, 0x14c00017, 0x254c0008, 0x3c020800, 0x8c421fd4,
+ 0x1040000a, 0x2402003e, 0x3c010800, 0xa4221fb0, 0x24020016, 0x3c010800,
+ 0xa4221fb2, 0x2402002a, 0x3c010800, 0x0a00031a, 0xa4221fb4, 0x95420014,
+ 0x3c010800, 0xa4221fb0, 0x8d430010, 0x00031402, 0x3c010800, 0xa4221fb2,
+ 0x3c010800, 0xa4231fb4, 0x3c040800, 0x94841fb4, 0x3c030800, 0x94631fb2,
+ 0x958d0006, 0x3c020800, 0x94421fb0, 0x00832023, 0x01a27023, 0x3065ffff,
+ 0x24a20028, 0x01824021, 0x3082ffff, 0x14c0001a, 0x01025821, 0x9562000c,
+ 0x3042003f, 0x3c010800, 0xa4221fb6, 0x95620004, 0x95630006, 0x3c010800,
+ 0xac201fc4, 0x3c010800, 0xac201fc8, 0x00021400, 0x00431025, 0x3c010800,
+ 0xac221720, 0x95020004, 0x3c010800, 0xa4221724, 0x95030002, 0x01a51023,
+ 0x0043102a, 0x10400010, 0x24020001, 0x3c010800, 0x0a00034e, 0xac221fd8,
+ 0x3c030800, 0x8c631fc8, 0x3c020800, 0x94421724, 0x00431021, 0xa5020004,
+ 0x3c020800, 0x94421720, 0xa5620004, 0x3c020800, 0x8c421720, 0xa5620006,
+ 0x3c020800, 0x8c421fd0, 0x3c070800, 0x8ce71fc4, 0x3c050800, 0x144000c7,
+ 0x8ca51fc8, 0x3c020800, 0x94421724, 0x00451821, 0x3063ffff, 0x0062182b,
+ 0x24020002, 0x10c2000d, 0x00a32823, 0x3c020800, 0x94421fb6, 0x30420009,
+ 0x10400008, 0x00000000, 0x9562000c, 0x3042fff6, 0xa562000c, 0x3c020800,
+ 0x94421fb6, 0x30420009, 0x00e23823, 0x3c020800, 0x8c421fd8, 0x1040004b,
+ 0x24020002, 0x01003021, 0x3c020800, 0x94421fb2, 0x00003821, 0xa500000a,
+ 0x01a21023, 0xa5020002, 0x3082ffff, 0x00021042, 0x18400008, 0x00002821,
+ 0x00401821, 0x94c20000, 0x24e70001, 0x00a22821, 0x00e3102a, 0x1440fffb,
+ 0x24c60002, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, 0x00a22821,
+ 0x00a04821, 0x00051027, 0xa502000a, 0x00002821, 0x2506000c, 0x00003821,
+ 0x94c20000, 0x24e70001, 0x00a22821, 0x2ce20004, 0x1440fffb, 0x24c60002,
+ 0x95020002, 0x00003821, 0x91030009, 0x00442023, 0x01603021, 0x3082ffff,
+ 0xa4c00010, 0x00621821, 0x00021042, 0x18400010, 0x00a32821, 0x00404021,
+ 0x94c20000, 0x24c60002, 0x00a22821, 0x30c2007f, 0x14400006, 0x24e70001,
+ 0x8d430000, 0x3c02007f, 0x3442ff80, 0x00625024, 0x25460008, 0x00e8102a,
+ 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00051c02, 0xa0c00001,
+ 0x94c20000, 0x00a22821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402,
+ 0x00a22821, 0x0a000415, 0x30a5ffff, 0x14c20063, 0x00000000, 0x3c090800,
+ 0x95291fb2, 0x95030002, 0x01a91023, 0x1062005d, 0x01003021, 0x00003821,
+ 0x00002821, 0x01a91023, 0xa5020002, 0x3082ffff, 0x00021042, 0x18400008,
+ 0xa500000a, 0x00401821, 0x94c20000, 0x24e70001, 0x00a22821, 0x00e3102a,
+ 0x1440fffb, 0x24c60002, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402,
+ 0x00a22821, 0x00a04821, 0x00051027, 0xa502000a, 0x00002821, 0x2506000c,
+ 0x00003821, 0x94c20000, 0x24e70001, 0x00a22821, 0x2ce20004, 0x1440fffb,
+ 0x24c60002, 0x95020002, 0x00003821, 0x91030009, 0x00442023, 0x01603021,
+ 0x3082ffff, 0xa4c00010, 0x3c040800, 0x94841fb4, 0x00621821, 0x00a32821,
+ 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051c02, 0x3c020800, 0x94421fb0,
+ 0x00a34021, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043, 0x18400010,
+ 0x00002821, 0x00402021, 0x94c20000, 0x24c60002, 0x00a22821, 0x30c2007f,
+ 0x14400006, 0x24e70001, 0x8d430000, 0x3c02007f, 0x3442ff80, 0x00625024,
+ 0x25460008, 0x00e4102a, 0x1440fff3, 0x00000000, 0x3c020800, 0x94421fcc,
+ 0x00a22821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, 0x00a22821,
+ 0x3102ffff, 0x00a22821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402,
+ 0x00a22821, 0x00a02021, 0x00051027, 0xa5620010, 0xad800014, 0x0a000435,
+ 0xad800000, 0x8d830010, 0x00602021, 0x10a00007, 0x00034c02, 0x01252821,
+ 0x00051402, 0x30a3ffff, 0x00432821, 0x00051402, 0x00a24821, 0x00091027,
+ 0xa502000a, 0x3c030800, 0x94631fb4, 0x3082ffff, 0x01a21021, 0x00432823,
+ 0x00a72821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, 0x00a22821,
+ 0x00a02021, 0x00051027, 0xa5620010, 0x3082ffff, 0x00091c00, 0x00431025,
+ 0xad820010, 0x3c020800, 0x8c421fd4, 0x10400002, 0x25a2fff2, 0xa5820034,
+ 0x3c020800, 0x8c421fc8, 0x3c030800, 0x8c631720, 0x24420001, 0x3c010800,
+ 0xac221fc8, 0x3c020800, 0x8c421fc4, 0x31c4ffff, 0x00641821, 0x3c010800,
+ 0xac231720, 0x00441021, 0x3c010800, 0xac221fc4, 0x03e00008, 0x27bd0020,
+ 0x27bdffc8, 0x3c040800, 0x248416f8, 0xafbf0034, 0xafbe0030, 0xafb7002c,
+ 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014,
+ 0xafb00010, 0x90830000, 0x24020003, 0x146200f4, 0x00000000, 0x3c020800,
+ 0x8c421710, 0x3c030800, 0x8c63170c, 0x3c1e0800, 0x97de16f6, 0x0043102a,
+ 0x104000eb, 0x3c168000, 0x249708c4, 0x33d5ffff, 0x24920018, 0x3c020800,
+ 0x8c421718, 0x104000e4, 0x00000000, 0x3c140800, 0x96941fb0, 0x3282ffff,
+ 0x104000d6, 0x00008021, 0x00409821, 0x00008821, 0x8f634450, 0x3c020800,
+ 0x8c4216e8, 0x00031c02, 0x0043102b, 0x14400008, 0x00000000, 0x3c040800,
+ 0x8c8416ec, 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x00000000,
+ 0xaf764444, 0x8f624444, 0x00561024, 0x10400006, 0x00000000, 0x3c038000,
+ 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x3046ffff,
+ 0x10c0005f, 0x00000000, 0x3c090800, 0x01314821, 0x8d291728, 0x9528000a,
+ 0x31020040, 0x10400004, 0x2407180c, 0x8d22000c, 0x2407188c, 0xacc20018,
+ 0x31021000, 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825,
+ 0x31020080, 0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421730,
+ 0x3c030800, 0x00711821, 0x8c631734, 0x00021500, 0x00031c00, 0x00431025,
+ 0xacc20014, 0x95240008, 0x3202ffff, 0x00821021, 0x0262102a, 0x14400002,
+ 0x02902823, 0x00802821, 0x8d220000, 0x02058021, 0xacc20000, 0x8d220004,
+ 0x00c02021, 0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e,
+ 0xac820010, 0x24020305, 0x0e000560, 0xa482000c, 0x3202ffff, 0x0053102b,
+ 0x1440ffaf, 0x3202ffff, 0x0a00054c, 0x00000000, 0x8e420000, 0x8e43fffc,
+ 0x0043102a, 0x10400084, 0x00000000, 0x8e45fff0, 0x8f644450, 0x3c030800,
+ 0x8c6316e8, 0x00051100, 0x3c090800, 0x01224821, 0x8d291728, 0x00041402,
+ 0x0062182b, 0x14600008, 0x00000000, 0x3c030800, 0x8c6316ec, 0x8f624450,
+ 0x00021402, 0x0062102b, 0x1040fffc, 0x00000000, 0xaf764444, 0x8f624444,
+ 0x00561024, 0x10400006, 0x00000000, 0x3c038000, 0x8f624444, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x8f624448, 0x3046ffff, 0x14c00005, 0x00000000,
+ 0x8ee20000, 0x24420001, 0x0a000554, 0xaee20000, 0x9528000a, 0x31020040,
+ 0x10400004, 0x2407180c, 0x8d22000c, 0x2407188c, 0xacc20018, 0x31021000,
+ 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825, 0x00051900,
+ 0x3c020800, 0x00431021, 0x8c421730, 0x3c010800, 0x00230821, 0x8c231734,
+ 0x00021500, 0x00031c00, 0x00431025, 0xacc20014, 0x3c030800, 0x8c631704,
+ 0x95220008, 0x00432023, 0x3202ffff, 0x3083ffff, 0x00431021, 0x02a2102a,
+ 0x14400002, 0x03d02823, 0x00802821, 0x8e420000, 0x30a4ffff, 0x00441021,
+ 0xae420000, 0xa4c5000e, 0x8d220000, 0xacc20000, 0x8d220004, 0x8e43fff4,
+ 0x00431021, 0xacc20004, 0x8e43fff4, 0x95220008, 0x00641821, 0x0062102a,
+ 0x14400006, 0x02058021, 0x8e42fff0, 0xae40fff4, 0x24420001, 0x0a000530,
+ 0xae42fff0, 0xae43fff4, 0xacc00008, 0x3202ffff, 0x10550003, 0x31020004,
+ 0x10400006, 0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020,
+ 0x24020905, 0xa4c2000c, 0x30e2ffff, 0xacc20010, 0x3c030800, 0x8c63170c,
+ 0x3c020800, 0x8c421710, 0x54620004, 0x3c02b49a, 0x3c024b65, 0x0a000548,
+ 0x34427654, 0x344289ab, 0xacc2001c, 0x0e000560, 0x00c02021, 0x3202ffff,
+ 0x0055102b, 0x1440ff7e, 0x00000000, 0x8e420000, 0x8e43fffc, 0x0043102a,
+ 0x1440ff1a, 0x00000000, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028,
+ 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0038, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450,
+ 0x8f634410, 0x0a00056f, 0x00808021, 0x8f626820, 0x30422000, 0x10400003,
+ 0x00000000, 0x0e00025a, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff,
+ 0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002,
+ 0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c4216b4, 0x3063000f,
+ 0x24420001, 0x3c010800, 0xac2216b4, 0x2c620002, 0x1040fff7, 0x00000000,
+ 0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820,
+ 0x30422000, 0x1040fff8, 0x00000000, 0x0e00025a, 0x00002021, 0x0a000582,
+ 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000,
+ 0x00000000
+};
+
+u32 tg3TsoFwRodata[] = {
+ 0x4d61696e, 0x43707542, 0x00000000, 0x00000000, 0x74637073, 0x6567496e,
+ 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000
+};
+
+#if 0 /* All zeros, dont eat up space with it. */
+u32 tg3TsoFwData[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000
+};
+#endif
+
+/* tp->lock is held. */
+static int tg3_load_tso_firmware(struct tg3 *tp)
+{
+ struct fw_info info;
+ int err, i;
+
+ info.text_base = TG3_TSO_FW_TEXT_ADDR;
+ info.text_len = TG3_TSO_FW_TEXT_LEN;
+ info.text_data = &tg3TsoFwText[0];
+ info.rodata_base = TG3_TSO_FW_RODATA_ADDR;
+ info.rodata_len = TG3_TSO_FW_RODATA_LEN;
+ info.rodata_data = &tg3TsoFwRodata[0];
+ info.data_base = TG3_TSO_FW_DATA_ADDR;
+ info.data_len = TG3_TSO_FW_DATA_LEN;
+ info.data_data = NULL;
+
+ err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
+ TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
+ &info);
+ if (err)
+ return err;
+
+ /* Now startup only the TX cpu. */
+ tw32(TX_CPU_BASE + CPU_STATE, 0xffffffff);
+ tw32(TX_CPU_BASE + CPU_PC, TG3_TSO_FW_TEXT_ADDR);
+
+ /* Flush posted writes. */
+ tr32(TX_CPU_BASE + CPU_PC);
+ for (i = 0; i < 5; i++) {
+ if (tr32(TX_CPU_BASE + CPU_PC) == TG3_TSO_FW_TEXT_ADDR)
+ break;
+ tw32(TX_CPU_BASE + CPU_STATE, 0xffffffff);
+ tw32(TX_CPU_BASE + CPU_MODE, CPU_MODE_HALT);
+ tw32(TX_CPU_BASE + CPU_PC, TG3_TSO_FW_TEXT_ADDR);
+
+ /* Flush posted writes. */
+ tr32(TX_CPU_BASE + CPU_PC);
+
+ udelay(1000);
+ }
+ if (i >= 5) {
+ printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s "
+ "to set TX CPU PC, is %08x should be %08x\n",
+ tp->dev->name, tr32(TX_CPU_BASE + CPU_PC),
+ TG3_TSO_FW_TEXT_ADDR);
+ return -ENODEV;
+ }
+ tw32(TX_CPU_BASE + CPU_STATE, 0xffffffff);
+ tw32(TX_CPU_BASE + CPU_MODE, 0x00000000);
+
+ /* Flush posted writes. */
+ tr32(TX_CPU_BASE + CPU_MODE);
+
+ return 0;
+}
+
+#endif /* TG3_DO_TSO != 0 */
+
/* tp->lock is held. */
static void __tg3_set_mac_addr(struct tg3 *tp)
{
@@ -3365,6 +3957,8 @@
tg3_disable_ints(tp);
+ tg3_stop_fw(tp);
+
if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
err = tg3_abort_hw(tp);
if (err)
@@ -3382,6 +3976,8 @@
tw32(MAC_MODE, tp->mac_mode);
} else
tw32(MAC_MODE, 0);
+ tr32(MAC_MODE);
+ udelay(40);
/* Wait for firmware initialization to complete. */
for (i = 0; i < 100000; i++) {
@@ -3397,6 +3993,13 @@
return -ENODEV;
}
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_START);
+ else
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_SUSPEND);
+
/* This works around an issue with Athlon chipsets on
* B3 tigon3 silicon. This bit has no effect on any
* other revision.
@@ -3404,12 +4007,22 @@
val = tr32(TG3PCI_CLOCK_CTRL);
val |= CLOCK_CTRL_DELAY_PCI_GRANT;
tw32(TG3PCI_CLOCK_CTRL, val);
+ tr32(TG3PCI_CLOCK_CTRL);
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
+ val = tr32(TG3PCI_PCISTATE);
+ val |= PCISTATE_RETRY_SAME_DMA;
+ tw32(TG3PCI_PCISTATE, val);
+ }
/* Clear statistics/status block in chip, and status block in ram. */
for (i = NIC_SRAM_STATS_BLK;
i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
- i += sizeof(u32))
+ i += sizeof(u32)) {
tg3_write_mem(tp, i, 0);
+ udelay(40);
+ }
memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
/* This value is determined during the probe time DMA
@@ -3440,7 +4053,10 @@
/* Initialize MBUF/DESC pool. */
tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
- tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
+ else
+ tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
@@ -3560,6 +4176,8 @@
tp->tx_cons = 0;
tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
tw32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
@@ -3581,6 +4199,8 @@
tp->rx_rcb_ptr = 0;
tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
tp->rx_rcb_mapping,
@@ -3591,10 +4211,14 @@
tp->rx_std_ptr = tp->rx_pending;
tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
tp->rx_std_ptr);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
#if TG3_MINI_RING_WORKS
tp->rx_mini_ptr = tp->rx_mini_pending;
tw32_mailbox(MAILBOX_RCV_MINI_PROD_IDX + TG3_64BIT_REG_LOW,
tp->rx_mini_ptr);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCV_MINI_PROD_IDX + TG3_64BIT_REG_LOW);
#endif
if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)
@@ -3603,6 +4227,8 @@
tp->rx_jumbo_ptr = 0;
tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
tp->rx_jumbo_ptr);
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
/* Initialize MAC address and backoff seed. */
__tg3_set_mac_addr(tp);
@@ -3638,24 +4264,16 @@
udelay(10);
}
- tw32(HOSTCC_RXCOL_TICKS,
- tp->coalesce_config.rx_coalesce_ticks);
- tw32(HOSTCC_RXMAX_FRAMES,
- tp->coalesce_config.rx_max_coalesced_frames);
- tw32(HOSTCC_RXCOAL_TICK_INT,
- tp->coalesce_config.rx_coalesce_ticks_during_int);
- tw32(HOSTCC_RXCOAL_MAXF_INT,
- tp->coalesce_config.rx_max_coalesced_frames_during_int);
- tw32(HOSTCC_TXCOL_TICKS,
- tp->coalesce_config.tx_coalesce_ticks);
- tw32(HOSTCC_TXMAX_FRAMES,
- tp->coalesce_config.tx_max_coalesced_frames);
- tw32(HOSTCC_TXCOAL_TICK_INT,
- tp->coalesce_config.tx_coalesce_ticks_during_int);
- tw32(HOSTCC_TXCOAL_MAXF_INT,
- tp->coalesce_config.tx_max_coalesced_frames_during_int);
+ tw32(HOSTCC_RXCOL_TICKS, 0);
+ tw32(HOSTCC_RXMAX_FRAMES, 1);
+ tw32(HOSTCC_RXCOAL_TICK_INT, 0);
+ tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
+ tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
+ tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
+ tw32(HOSTCC_TXCOAL_TICK_INT, 0);
+ tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
tw32(HOSTCC_STAT_COAL_TICKS,
- tp->coalesce_config.stats_coalesce_ticks);
+ DEFAULT_STAT_COAL_TICKS);
/* Status/statistics block address. */
tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
@@ -3678,25 +4296,53 @@
tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
tw32(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
+ tr32(MAC_MODE);
+ udelay(40);
- tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_AUTO_SEEPROM;
+ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OUTPUT1);
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+ tr32(GRC_LOCAL_CTRL);
+ udelay(100);
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
+ tr32(MAILBOX_INTERRUPT_0);
tw32(DMAC_MODE, DMAC_MODE_ENABLE);
+ tr32(DMAC_MODE);
+ udelay(40);
tw32(WDMAC_MODE, (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
WDMAC_MODE_LNGREAD_ENAB));
- tw32(RDMAC_MODE, (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
- RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
- RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
- RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
- RDMAC_MODE_LNGREAD_ENAB));
+ tr32(WDMAC_MODE);
+ udelay(40);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+ (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
+ val = tr32(TG3PCI_X_CAPS);
+ val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
+ val |= (PCIX_CAPS_MAX_BURST_5704 << PCIX_CAPS_BURST_SHIFT);
+ if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
+ val |= (tp->split_mode_max_reqs <<
+ PCIX_CAPS_SPLIT_SHIFT);
+ tw32(TG3PCI_X_CAPS, val);
+ }
+
+ val = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
+ RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
+ RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
+ RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
+ RDMAC_MODE_LNGREAD_ENAB);
+ if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
+ val |= RDMAC_MODE_SPLIT_ENABLE;
+ tw32(RDMAC_MODE, val);
+ tr32(RDMAC_MODE);
+ udelay(40);
tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
@@ -3714,10 +4360,21 @@
return err;
}
+#if TG3_DO_TSO != 0
+ err = tg3_load_tso_firmware(tp);
+ if (err)
+ return err;
+#endif
+
tp->tx_mode = TX_MODE_ENABLE;
tw32(MAC_TX_MODE, tp->tx_mode);
+ tr32(MAC_TX_MODE);
+ udelay(100);
+
tp->rx_mode = RX_MODE_ENABLE;
tw32(MAC_RX_MODE, tp->rx_mode);
+ tr32(MAC_RX_MODE);
+ udelay(10);
if (tp->link_config.phy_is_low_power) {
tp->link_config.phy_is_low_power = 0;
@@ -3728,11 +4385,17 @@
tp->mi_mode = MAC_MI_MODE_BASE;
tw32(MAC_MI_MODE, tp->mi_mode);
+ tr32(MAC_MI_MODE);
+ udelay(40);
+
tw32(MAC_LED_CTRL, 0);
tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
tw32(MAC_RX_MODE, RX_MODE_RESET);
+ tr32(MAC_RX_MODE);
udelay(10);
tw32(MAC_RX_MODE, tp->rx_mode);
+ tr32(MAC_RX_MODE);
+ udelay(10);
if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
tw32(MAC_SERDES_CFG, 0x616000);
@@ -3792,6 +4455,8 @@
if (err)
goto out;
+ tg3_switch_clocks(tp);
+
tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
err = tg3_reset_hw(tp);
@@ -3805,25 +4470,24 @@
struct tg3 *tp = (struct tg3 *) __opaque;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
- if (!(tp->tg3_flags & TG3_FLAG_TAGGED_IRQ_STATUS)) {
- /* All of this garbage is because on the 5700 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,
- (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
- }
+ /* 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)) {
- tg3_halt(tp);
- tg3_init_rings(tp);
- tg3_init_hw(tp);
- }
+ if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+ tg3_halt(tp);
+ tg3_init_rings(tp);
+ tg3_init_hw(tp);
}
/* This part only runs once per second. */
@@ -3859,8 +4523,11 @@
tw32(MAC_MODE,
(tp->mac_mode &
~MAC_MODE_PORT_MODE_MASK));
+ tr32(MAC_MODE);
udelay(40);
tw32(MAC_MODE, tp->mac_mode);
+ tr32(MAC_MODE);
+ udelay(40);
tg3_setup_phy(tp);
}
}
@@ -3868,6 +4535,22 @@
tp->timer_counter = tp->timer_multiplier;
}
+ /* Heartbeat is only sent once every 120 seconds. */
+ if (!--tp->asf_counter) {
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+ u32 val;
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_ALIVE);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 3);
+ val = tr32(GRC_RX_CPU_EVENT);
+ val |= (1 << 14);
+ tw32(GRC_RX_CPU_EVENT, val);
+ }
+ tp->asf_counter = tp->asf_multiplier;
+ }
+
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tp->timer.expires = jiffies + tp->timer_offset;
@@ -3880,10 +4563,12 @@
int err;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_disable_ints(tp);
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
/* If you move this call, make sure TG3_FLAG_HOST_TXDS in
@@ -3893,12 +4578,8 @@
if (err)
return err;
- if (tp->tg3_flags & TG3_FLAG_TAGGED_IRQ_STATUS)
- err = request_irq(dev->irq, tg3_interrupt_tagged,
- SA_SHIRQ, dev->name, dev);
- else
- err = request_irq(dev->irq, tg3_interrupt,
- SA_SHIRQ, dev->name, dev);
+ err = request_irq(dev->irq, tg3_interrupt,
+ SA_SHIRQ, dev->name, dev);
if (err) {
tg3_free_consistent(tp);
@@ -3906,6 +4587,7 @@
}
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_init_rings(tp);
@@ -3914,13 +4596,9 @@
tg3_halt(tp);
tg3_free_rings(tp);
} else {
- if (tp->tg3_flags & TG3_FLAG_TAGGED_IRQ_STATUS) {
- tp->timer_offset = HZ;
- tp->timer_counter = tp->timer_multiplier = 1;
- } else {
- tp->timer_offset = HZ / 10;
- tp->timer_counter = tp->timer_multiplier = 10;
- }
+ tp->timer_offset = HZ / 10;
+ tp->timer_counter = tp->timer_multiplier = 10;
+ tp->asf_counter = tp->asf_multiplier = (10 * 120);
init_timer(&tp->timer);
tp->timer.expires = jiffies + tp->timer_offset;
@@ -3928,13 +4606,10 @@
tp->timer.function = tg3_timer;
add_timer(&tp->timer);
- tp->last_rate_sample = jiffies;
- tp->last_rx_count = 0;
- tp->last_tx_count = 0;
-
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
}
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
if (err) {
@@ -3946,9 +4621,11 @@
netif_start_queue(dev);
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_enable_ints(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return 0;
@@ -4210,6 +4887,7 @@
del_timer_sync(&tp->timer);
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
#if 0
tg3_dump_state(tp);
#endif
@@ -4223,6 +4901,7 @@
TG3_FLAG_GOT_SERDES_FLOWCTL);
netif_carrier_off(tp->dev);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
free_irq(dev->irq, dev);
@@ -4240,10 +4919,7 @@
unsigned long ret;
#if (BITS_PER_LONG == 32)
- if (val->high != 0)
- ret = ~0UL;
- else
- ret = val->low;
+ ret = val->low;
#else
ret = ((u64)val->high << 32) | ((u64)val->low);
#endif
@@ -4357,10 +5033,10 @@
static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all)
{
/* accept or reject all multicast frames */
- tw32 (MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
- tw32 (MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
- tw32 (MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
- tw32 (MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
}
static void __tg3_set_rx_mode(struct net_device *dev)
@@ -4368,7 +5044,17 @@
struct tg3 *tp = dev->priv;
u32 rx_mode;
- rx_mode = tp->rx_mode & ~RX_MODE_PROMISC;
+ rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
+ RX_MODE_KEEP_VLAN_TAG);
+#if TG3_VLAN_TAG_USED
+ if (!tp->vlgrp)
+ rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+#else
+ /* By definition, VLAN is disabled always in this
+ * case.
+ */
+ rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+#endif
if (dev->flags & IFF_PROMISC) {
/* Promiscuous mode. */
@@ -4398,15 +5084,17 @@
mc_filter[regidx] |= (1 << bit);
}
- tw32 (MAC_HASH_REG_0, mc_filter[0]);
- tw32 (MAC_HASH_REG_1, mc_filter[1]);
- tw32 (MAC_HASH_REG_2, mc_filter[2]);
- tw32 (MAC_HASH_REG_3, mc_filter[3]);
+ tw32(MAC_HASH_REG_0, mc_filter[0]);
+ tw32(MAC_HASH_REG_1, mc_filter[1]);
+ tw32(MAC_HASH_REG_2, mc_filter[2]);
+ tw32(MAC_HASH_REG_3, mc_filter[3]);
}
if (rx_mode != tp->rx_mode) {
tp->rx_mode = rx_mode;
- tw32 (MAC_RX_MODE, rx_mode);
+ tw32(MAC_RX_MODE, rx_mode);
+ tr32(MAC_RX_MODE);
+ udelay(10);
}
}
@@ -4433,6 +5121,7 @@
memset(orig_p, 0, TG3_REGDUMP_LEN);
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
#define __GET_REG32(reg) (*((u32 *)(p))++ = tr32(reg))
#define GET_REG32_LOOP(base,len) \
@@ -4481,182 +5170,12 @@
#undef GET_REG32_LOOP
#undef GET_REG32_1
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return orig_p;
}
-static void tg3_to_ethtool_coal(struct tg3 *tp,
- struct ethtool_coalesce *ecoal)
-{
- ecoal->rx_coalesce_usecs =
- tp->coalesce_config.rx_coalesce_ticks_def;
- ecoal->rx_max_coalesced_frames =
- tp->coalesce_config.rx_max_coalesced_frames_def;
- ecoal->rx_coalesce_usecs_irq =
- tp->coalesce_config.rx_coalesce_ticks_during_int_def;
- ecoal->rx_max_coalesced_frames_irq =
- tp->coalesce_config.rx_max_coalesced_frames_during_int_def;
-
- ecoal->tx_coalesce_usecs =
- tp->coalesce_config.tx_coalesce_ticks_def;
- ecoal->tx_max_coalesced_frames =
- tp->coalesce_config.tx_max_coalesced_frames_def;
- ecoal->tx_coalesce_usecs_irq =
- tp->coalesce_config.tx_coalesce_ticks_during_int_def;
- ecoal->tx_max_coalesced_frames_irq =
- tp->coalesce_config.tx_max_coalesced_frames_during_int_def;
-
- ecoal->stats_block_coalesce_usecs =
- tp->coalesce_config.stats_coalesce_ticks_def;
-
- ecoal->use_adaptive_rx_coalesce =
- (tp->tg3_flags & TG3_FLAG_ADAPTIVE_RX) != 0;
- ecoal->use_adaptive_tx_coalesce =
- (tp->tg3_flags & TG3_FLAG_ADAPTIVE_TX) != 0;
-
- ecoal->pkt_rate_low =
- tp->coalesce_config.pkt_rate_low;
- ecoal->rx_coalesce_usecs_low =
- tp->coalesce_config.rx_coalesce_ticks_low;
- ecoal->rx_max_coalesced_frames_low =
- tp->coalesce_config.rx_max_coalesced_frames_low;
- ecoal->tx_coalesce_usecs_low =
- tp->coalesce_config.tx_coalesce_ticks_low;
- ecoal->tx_max_coalesced_frames_low =
- tp->coalesce_config.tx_max_coalesced_frames_low;
-
- ecoal->pkt_rate_high =
- tp->coalesce_config.pkt_rate_high;
- ecoal->rx_coalesce_usecs_high =
- tp->coalesce_config.rx_coalesce_ticks_high;
- ecoal->rx_max_coalesced_frames_high =
- tp->coalesce_config.rx_max_coalesced_frames_high;
- ecoal->tx_coalesce_usecs_high =
- tp->coalesce_config.tx_coalesce_ticks_high;
- ecoal->tx_max_coalesced_frames_high =
- tp->coalesce_config.tx_max_coalesced_frames_high;
-
- ecoal->rate_sample_interval =
- tp->coalesce_config.rate_sample_jiffies / HZ;
-}
-
-static int tg3_from_ethtool_coal(struct tg3 *tp,
- struct ethtool_coalesce *ecoal)
-{
- /* Make sure we are not getting garbage. */
- if ((ecoal->rx_coalesce_usecs == 0 &&
- ecoal->rx_max_coalesced_frames == 0) ||
- (ecoal->tx_coalesce_usecs == 0 &&
- ecoal->tx_max_coalesced_frames == 0) ||
- ecoal->stats_block_coalesce_usecs == 0)
- return -EINVAL;
- if (ecoal->use_adaptive_rx_coalesce ||
- ecoal->use_adaptive_tx_coalesce) {
- if (ecoal->pkt_rate_low > ecoal->pkt_rate_high)
- return -EINVAL;
- if (ecoal->rate_sample_interval == 0)
- return -EINVAL;
- if (ecoal->use_adaptive_rx_coalesce &&
- ((ecoal->rx_coalesce_usecs_low == 0 &&
- ecoal->rx_max_coalesced_frames_low == 0) ||
- (ecoal->rx_coalesce_usecs_high == 0 &&
- ecoal->rx_max_coalesced_frames_high == 0)))
- return -EINVAL;
- if (ecoal->use_adaptive_tx_coalesce &&
- ((ecoal->tx_coalesce_usecs_low == 0 &&
- ecoal->tx_max_coalesced_frames_low == 0) ||
- (ecoal->tx_coalesce_usecs_high == 0 &&
- ecoal->tx_max_coalesced_frames_high == 0)))
- return -EINVAL;
- }
-
- /* Looks good, let it rip. */
- spin_lock_irq(&tp->lock);
- tp->coalesce_config.rx_coalesce_ticks =
- tp->coalesce_config.rx_coalesce_ticks_def =
- ecoal->rx_coalesce_usecs;
- tp->coalesce_config.rx_max_coalesced_frames =
- tp->coalesce_config.rx_max_coalesced_frames_def =
- ecoal->rx_max_coalesced_frames;
- tp->coalesce_config.rx_coalesce_ticks_during_int =
- tp->coalesce_config.rx_coalesce_ticks_during_int_def =
- ecoal->rx_coalesce_usecs_irq;
- tp->coalesce_config.rx_max_coalesced_frames_during_int =
- tp->coalesce_config.rx_max_coalesced_frames_during_int_def =
- ecoal->rx_max_coalesced_frames_irq;
- tp->coalesce_config.tx_coalesce_ticks =
- tp->coalesce_config.tx_coalesce_ticks_def =
- ecoal->tx_coalesce_usecs;
- tp->coalesce_config.tx_max_coalesced_frames =
- tp->coalesce_config.tx_max_coalesced_frames_def =
- ecoal->tx_max_coalesced_frames;
- tp->coalesce_config.tx_coalesce_ticks_during_int =
- tp->coalesce_config.tx_coalesce_ticks_during_int_def =
- ecoal->tx_coalesce_usecs_irq;
- tp->coalesce_config.tx_max_coalesced_frames_during_int =
- tp->coalesce_config.tx_max_coalesced_frames_during_int_def =
- ecoal->tx_max_coalesced_frames_irq;
- tp->coalesce_config.stats_coalesce_ticks =
- tp->coalesce_config.stats_coalesce_ticks_def =
- ecoal->stats_block_coalesce_usecs;
-
- if (ecoal->use_adaptive_rx_coalesce)
- tp->tg3_flags |= TG3_FLAG_ADAPTIVE_RX;
- else
- tp->tg3_flags &= ~TG3_FLAG_ADAPTIVE_RX;
- if (ecoal->use_adaptive_tx_coalesce)
- tp->tg3_flags |= TG3_FLAG_ADAPTIVE_TX;
- else
- tp->tg3_flags &= ~TG3_FLAG_ADAPTIVE_TX;
-
- tp->coalesce_config.pkt_rate_low = ecoal->pkt_rate_low;
- tp->coalesce_config.pkt_rate_high = ecoal->pkt_rate_high;
- tp->coalesce_config.rate_sample_jiffies =
- ecoal->rate_sample_interval * HZ;
-
- tp->coalesce_config.rx_coalesce_ticks_low =
- ecoal->rx_coalesce_usecs_low;
- tp->coalesce_config.rx_max_coalesced_frames_low =
- ecoal->rx_max_coalesced_frames_low;
- tp->coalesce_config.tx_coalesce_ticks_low =
- ecoal->tx_coalesce_usecs_low;
- tp->coalesce_config.tx_max_coalesced_frames_low =
- ecoal->tx_max_coalesced_frames_low;
-
- tp->coalesce_config.rx_coalesce_ticks_high =
- ecoal->rx_coalesce_usecs_high;
- tp->coalesce_config.rx_max_coalesced_frames_high =
- ecoal->rx_max_coalesced_frames_high;
- tp->coalesce_config.tx_coalesce_ticks_high =
- ecoal->tx_coalesce_usecs_high;
- tp->coalesce_config.tx_max_coalesced_frames_high =
- ecoal->tx_max_coalesced_frames_high;
-
- tw32(HOSTCC_RXCOL_TICKS,
- tp->coalesce_config.rx_coalesce_ticks_def);
- tw32(HOSTCC_RXMAX_FRAMES,
- tp->coalesce_config.rx_max_coalesced_frames_def);
- tw32(HOSTCC_RXCOAL_TICK_INT,
- tp->coalesce_config.rx_coalesce_ticks_during_int_def);
- tw32(HOSTCC_RXCOAL_MAXF_INT,
- tp->coalesce_config.rx_max_coalesced_frames_during_int_def);
- tw32(HOSTCC_TXCOL_TICKS,
- tp->coalesce_config.tx_coalesce_ticks_def);
- tw32(HOSTCC_TXMAX_FRAMES,
- tp->coalesce_config.tx_max_coalesced_frames_def);
- tw32(HOSTCC_TXCOAL_TICK_INT,
- tp->coalesce_config.tx_coalesce_ticks_during_int_def);
- tw32(HOSTCC_TXCOAL_MAXF_INT,
- tp->coalesce_config.tx_max_coalesced_frames_during_int_def);
- tw32(HOSTCC_STAT_COAL_TICKS,
- tp->coalesce_config.stats_coalesce_ticks_def);
-
- spin_unlock_irq(&tp->lock);
-
- return 0;
-}
-
static int tg3_ethtool_ioctl (struct net_device *dev, void *useraddr)
{
struct tg3 *tp = dev->priv;
@@ -4708,8 +5227,8 @@
cmd.phy_address = PHY_ADDR;
cmd.transceiver = 0;
cmd.autoneg = tp->link_config.autoneg;
- cmd.maxtxpkt = tp->coalesce_config.tx_max_coalesced_frames_def;
- cmd.maxrxpkt = tp->coalesce_config.rx_max_coalesced_frames_def;
+ cmd.maxtxpkt = 0;
+ cmd.maxrxpkt = 0;
if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
return -EFAULT;
return 0;
@@ -4750,6 +5269,7 @@
}
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tp->link_config.autoneg = cmd.autoneg;
if (cmd.autoneg == AUTONEG_ENABLE) {
@@ -4761,23 +5281,8 @@
tp->link_config.duplex = cmd.duplex;
}
- if (cmd.maxtxpkt || cmd.maxrxpkt) {
- tp->coalesce_config.tx_max_coalesced_frames_def =
- tp->coalesce_config.tx_max_coalesced_frames =
- cmd.maxtxpkt;
- tp->coalesce_config.rx_max_coalesced_frames_def =
- tp->coalesce_config.rx_max_coalesced_frames =
- cmd.maxrxpkt;
-
- /* Coalescing config bits can be updated without
- * a full chip reset.
- */
- tw32(HOSTCC_TXMAX_FRAMES,
- tp->coalesce_config.tx_max_coalesced_frames);
- tw32(HOSTCC_RXMAX_FRAMES,
- tp->coalesce_config.rx_max_coalesced_frames);
- }
tg3_setup_phy(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return 0;
@@ -4826,6 +5331,11 @@
return -EFAULT;
if (wol.wolopts & ~WAKE_MAGIC)
return -EINVAL;
+ if ((wol.wolopts & WAKE_MAGIC) &&
+ tp->phy_id == PHY_ID_SERDES &&
+ !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
+ return -EINVAL;
+
spin_lock_irq(&tp->lock);
if (wol.wolopts & WAKE_MAGIC)
tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
@@ -4873,22 +5383,6 @@
return -EFAULT;
return 0;
}
- case ETHTOOL_GCOALESCE: {
- struct ethtool_coalesce ecoal = { ETHTOOL_GCOALESCE };
-
- tg3_to_ethtool_coal(tp, &ecoal);
- if (copy_to_user(useraddr, &ecoal, sizeof(ecoal)))
- return -EFAULT;
- return 0;
- }
- case ETHTOOL_SCOALESCE: {
- struct ethtool_coalesce ecoal;
-
- if (copy_from_user(&ecoal, useraddr, sizeof(ecoal)))
- return -EINVAL;
-
- return tg3_from_ethtool_coal(tp, &ecoal);
- }
case ETHTOOL_GRINGPARAM: {
struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
@@ -4928,6 +5422,7 @@
return -EINVAL;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tp->rx_pending = ering.rx_pending;
#if TG3_MINI_RING_WORKS
@@ -4940,6 +5435,7 @@
tg3_init_rings(tp);
tg3_init_hw(tp);
netif_wake_queue(tp->dev);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return 0;
@@ -4964,6 +5460,7 @@
return -EFAULT;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
if (epause.autoneg)
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
else
@@ -4979,6 +5476,7 @@
tg3_halt(tp);
tg3_init_rings(tp);
tg3_init_hw(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return 0;
@@ -5116,7 +5614,14 @@
struct tg3 *tp = dev->priv;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
+
tp->vlgrp = grp;
+
+ /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
+ __tg3_set_rx_mode(dev);
+
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
}
@@ -5125,8 +5630,10 @@
struct tg3 *tp = dev->priv;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
if (tp->vlgrp)
tp->vlgrp->vlan_devices[vid] = NULL;
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
}
#endif
@@ -5148,6 +5655,7 @@
/* Enable seeprom accesses. */
tw32(GRC_LOCAL_CTRL,
tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
+ tr32(GRC_LOCAL_CTRL);
udelay(100);
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
@@ -5355,12 +5863,17 @@
eeprom_led_mode = led_mode_auto;
break;
};
+ if ((tp->pci_chip_rev_id == CHIPREV_ID_5703_A1 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5703_A2) &&
+ (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
+ tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+
+ if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE)
+ tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
+ if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
+ tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
}
- err = tg3_phy_reset(tp, 0);
- if (err)
- return err;
-
/* Now read the physical PHY_ID from the chip and verify
* that it is sane. If it doesn't look good, we fall back
* to either the hard-coded table based PHY_ID and failing
@@ -5390,30 +5903,24 @@
}
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
- }
+ err = tg3_phy_reset(tp, 1);
+ if (err)
+ return err;
if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
- tp->tg3_flags |= TG3_FLAG_PHY_RESET_ON_INIT;
-
- if (tp->tg3_flags & TG3_FLAG_PHY_RESET_ON_INIT) {
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
u32 mii_tg3_ctrl;
-
- err = tg3_phy_reset(tp, 1);
- if (err)
- return err;
-
- /* These chips, when reset, only advertise 10Mb capabilities.
- * Fix that.
+
+ /* These chips, when reset, only advertise 10Mb
+ * capabilities. Fix that.
*/
err = tg3_writephy(tp, MII_ADVERTISE,
(ADVERTISE_CSMA |
- ADVERTISE_10HALF | ADVERTISE_10FULL |
- ADVERTISE_100HALF | ADVERTISE_100FULL));
+ ADVERTISE_PAUSE_CAP |
+ ADVERTISE_10HALF |
+ ADVERTISE_10FULL |
+ ADVERTISE_100HALF |
+ ADVERTISE_100FULL));
mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
MII_TG3_CTRL_ADV_1000_FULL |
MII_TG3_CTRL_AS_MASTER |
@@ -5426,6 +5933,22 @@
(BMCR_ANRESTART | BMCR_ANENABLE));
}
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ tg3_writephy(tp, 0x1c, 0x8d68);
+ tg3_writephy(tp, 0x1c, 0x8d68);
+ }
+
+ /* Enable Ethernet@WireSpeed */
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007);
+ tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4)));
+
if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) {
err = tg3_init_5401phy_dsp(tp);
}
@@ -5523,6 +6046,20 @@
u16 pci_cmd;
int err;
+ /* If we have an AMD 762 or Intel ICH/ICH0 chipset, write
+ * reordering to the mailbox registers done by the host
+ * controller can cause major troubles. We read back from
+ * every mailbox register write to force the writes to be
+ * posted to the chip in order.
+ */
+ if (pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801AA_8, NULL) ||
+ pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801AB_8, NULL) ||
+ pci_find_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL))
+ tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
+
/* Force memory write invalidate off. If we leave it on,
* then on 5700_BX chips we have to enable a workaround.
* The workaround is to set the TG3PCI_DMA_RW_CTRL boundry
@@ -5534,12 +6071,24 @@
pci_cmd &= ~PCI_COMMAND_INVALIDATE;
pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+ /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
+ * has the register indirect write enable bit set before
+ * we try to access any of the MMIO registers. It is also
+ * critical that the PCI-X hw workaround situation is decided
+ * before that as well.
+ */
pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
&misc_ctrl_reg);
tp->pci_chip_rev_id = (misc_ctrl_reg >>
MISC_HOST_CTRL_CHIPREV_SHIFT);
+ /* Initialize misc host control in PCI block. */
+ tp->misc_host_ctrl |= (misc_ctrl_reg &
+ MISC_HOST_CTRL_CHIPREV);
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
pci_read_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
&cacheline_sz_reg);
@@ -5641,62 +6190,29 @@
tp->tg3_flags |= TG3_FLAG_WOL_SPEED_100MB;
}
- /* Only 5701 and later support tagged irq status mode. */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) {
- tp->tg3_flags |= TG3_FLAG_TAGGED_IRQ_STATUS;
- tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
-
- /* ??? Due to a glitch Broadcom's driver ALWAYS sets
- * ??? these bits in coalesce_mode. Because MM_GetConfig
- * ??? always sets pDevice->UseTaggedStatus correctly
- * ??? the following test at tigon3.c:LM_GetAdapterInfo()
- * ???
- * ??? pDevice->UseTaggedStatus &&
- * ??? (pDevice->ChipRevId == T3_CHIP_ID_5700_C0 ||
- * ??? T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_AX ||
- * ??? T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX)
- * ???
- * ??? will never pass and thus pDevice->CoalesceMode will never
- * ??? get set to zero. For now I'll mirror what I believe is
- * ??? the intention of their driver.
- * ???
- * ??? Update: This is fixed in Broadcom's 2.2.3 and later
- * ??? drivers. All the current 2.0.x drivers still
- * ??? have the bug.
- */
- tp->coalesce_mode = (HOSTCC_MODE_CLRTICK_RXBD |
- HOSTCC_MODE_CLRTICK_TXBD);
- } else {
- tp->coalesce_mode = 0;
-
- /* If not using tagged status, set the *_during_int
- * coalesce default config values to zero.
- */
- tp->coalesce_config.rx_coalesce_ticks_during_int_def = 0;
- tp->coalesce_config.rx_max_coalesced_frames_during_int_def = 0;
- tp->coalesce_config.tx_coalesce_ticks_during_int_def = 0;
- tp->coalesce_config.tx_max_coalesced_frames_during_int_def = 0;
- }
+ /* Only 5701 and later support tagged irq status mode.
+ *
+ * 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;
- /* Initialize misc host control in PCI block. */
- tp->misc_host_ctrl |= (misc_ctrl_reg &
- MISC_HOST_CTRL_CHIPREV);
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
-
/* Initialize MAC MI mode, polling disabled. */
tw32(MAC_MI_MODE, tp->mi_mode);
+ tr32(MAC_MI_MODE);
udelay(40);
/* Initialize data/descriptor byte/word swapping. */
tw32(GRC_MODE, tp->grc_mode);
- /* Clear these out for sanity. */
- tw32(TG3PCI_CLOCK_CTRL, 0);
+ tg3_switch_clocks(tp);
+
+ /* Clear this out for sanity. */
tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
@@ -5744,9 +6260,16 @@
grc_misc_cfg != GRC_MISC_CFG_BOARD_ID_5702FE &&
grc_misc_cfg != GRC_MISC_CFG_BOARD_ID_5703 &&
grc_misc_cfg != GRC_MISC_CFG_BOARD_ID_5703S &&
+ grc_misc_cfg != GRC_MISC_CFG_BOARD_ID_5704 &&
grc_misc_cfg != GRC_MISC_CFG_BOARD_ID_AC91002A1)
return -ENODEV;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+ grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
+ tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
+ tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
+ }
+
/* ROFL, you should see Broadcom's driver code implementing
* this, stuff like "if (a || b)" where a and b are always
* mutually exclusive. DaveM finds like 6 bugs today, hello!
@@ -5825,13 +6348,23 @@
(tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
tp->rx_offset = 0;
+ /* By default, disable wake-on-lan. User can change this
+ * using ETHTOOL_SWOL.
+ */
+ tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
+
return err;
}
static int __devinit tg3_get_device_address(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
- u32 hi, lo;
+ u32 hi, lo, mac_offset;
+
+ if (PCI_FUNC(tp->pdev->devfn) == 0)
+ mac_offset = 0x7c;
+ else
+ mac_offset = 0xcc;
/* First try to get it from MAC address mailbox. */
tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
@@ -5846,8 +6379,8 @@
dev->dev_addr[5] = (lo >> 0) & 0xff;
}
/* Next, try NVRAM. */
- else if (!tg3_nvram_read(tp, 0x7c, &hi) &&
- !tg3_nvram_read(tp, 0x80, &lo)) {
+ else if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+ !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
dev->dev_addr[0] = ((hi >> 16) & 0xff);
dev->dev_addr[1] = ((hi >> 24) & 0xff);
dev->dev_addr[2] = ((lo >> 0) & 0xff);
@@ -5898,11 +6431,21 @@
if (to_device) {
test_desc.cqid_sqid = (13 << 8) | 2;
tw32(RDMAC_MODE, RDMAC_MODE_RESET);
+ tr32(RDMAC_MODE);
+ udelay(40);
+
tw32(RDMAC_MODE, RDMAC_MODE_ENABLE);
+ tr32(RDMAC_MODE);
+ udelay(40);
} else {
test_desc.cqid_sqid = (16 << 8) | 7;
tw32(WDMAC_MODE, WDMAC_MODE_RESET);
+ tr32(WDMAC_MODE);
+ udelay(40);
+
tw32(WDMAC_MODE, WDMAC_MODE_ENABLE);
+ tr32(WDMAC_MODE);
+ udelay(40);
}
test_desc.flags = 0x00000004;
@@ -5965,16 +6508,26 @@
(0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
(0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
} else {
- tp->dma_rwctrl =
- (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
- (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
- (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
- (0x3 << DMA_RWCTRL_READ_WATER_SHIFT) |
- (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tp->dma_rwctrl =
+ (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
+ (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
+ (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+ (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
+ (0x00 << DMA_RWCTRL_MIN_DMA_SHIFT);
+ else
+ tp->dma_rwctrl =
+ (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
+ (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
+ (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+ (0x3 << DMA_RWCTRL_READ_WATER_SHIFT) |
+ (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
/* Wheee, some more chip bugs... */
if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5703_A2)
+ tp->pci_chip_rev_id == CHIPREV_ID_5703_A2 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5703_A3 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
}
@@ -6121,61 +6674,6 @@
tp->link_config.orig_autoneg = AUTONEG_INVALID;
}
-static void __devinit tg3_init_coalesce_config(struct tg3 *tp)
-{
- tp->coalesce_config.rx_coalesce_ticks_def = DEFAULT_RXCOL_TICKS;
- tp->coalesce_config.rx_max_coalesced_frames_def = DEFAULT_RXMAX_FRAMES;
- tp->coalesce_config.rx_coalesce_ticks_during_int_def =
- DEFAULT_RXCOAL_TICK_INT;
- tp->coalesce_config.rx_max_coalesced_frames_during_int_def =
- DEFAULT_RXCOAL_MAXF_INT;
- tp->coalesce_config.tx_coalesce_ticks_def = DEFAULT_TXCOL_TICKS;
- tp->coalesce_config.tx_max_coalesced_frames_def = DEFAULT_TXMAX_FRAMES;
- tp->coalesce_config.tx_coalesce_ticks_during_int_def =
- DEFAULT_TXCOAL_TICK_INT;
- tp->coalesce_config.tx_max_coalesced_frames_during_int_def =
- DEFAULT_TXCOAL_MAXF_INT;
- tp->coalesce_config.stats_coalesce_ticks_def =
- DEFAULT_STAT_COAL_TICKS;
-
- tp->coalesce_config.rx_coalesce_ticks_low =
- LOW_RXCOL_TICKS;
- tp->coalesce_config.rx_max_coalesced_frames_low =
- LOW_RXMAX_FRAMES;
- tp->coalesce_config.tx_coalesce_ticks_low =
- LOW_TXCOL_TICKS;
- tp->coalesce_config.tx_max_coalesced_frames_low =
- LOW_TXMAX_FRAMES;
-
- tp->coalesce_config.rx_coalesce_ticks_high =
- HIGH_RXCOL_TICKS;
- tp->coalesce_config.rx_max_coalesced_frames_high =
- HIGH_RXMAX_FRAMES;
- tp->coalesce_config.tx_coalesce_ticks_high =
- HIGH_TXCOL_TICKS;
- tp->coalesce_config.tx_max_coalesced_frames_high =
- HIGH_TXMAX_FRAMES;
-
- /* Active == default */
- tp->coalesce_config.rx_coalesce_ticks =
- tp->coalesce_config.rx_coalesce_ticks_def;
- tp->coalesce_config.rx_max_coalesced_frames =
- tp->coalesce_config.rx_max_coalesced_frames_def;
- tp->coalesce_config.tx_coalesce_ticks =
- tp->coalesce_config.tx_coalesce_ticks_def;
- tp->coalesce_config.tx_max_coalesced_frames =
- tp->coalesce_config.tx_max_coalesced_frames_def;
- tp->coalesce_config.stats_coalesce_ticks =
- tp->coalesce_config.stats_coalesce_ticks_def;
-
- tp->coalesce_config.rate_sample_jiffies = (1 * HZ);
- tp->coalesce_config.pkt_rate_low = 22000;
- tp->coalesce_config.pkt_rate_high = 61000;
-
- tp->tg3_flags |= TG3_FLAG_ADAPTIVE_RX;
- tp->tg3_flags &= ~(TG3_FLAG_ADAPTIVE_TX);
-}
-
static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
{
tp->bufmgr_config.mbuf_read_dma_low_water =
@@ -6204,6 +6702,7 @@
case PHY_ID_BCM5411: return "5411";
case PHY_ID_BCM5701: return "5701";
case PHY_ID_BCM5703: return "5703";
+ case PHY_ID_BCM5704: return "5704";
case PHY_ID_BCM8002: return "8002";
case PHY_ID_SERDES: return "serdes";
default: return "unknown";
@@ -6285,6 +6784,9 @@
dev->vlan_rx_register = tg3_vlan_rx_register;
dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
#endif
+#if TG3_DO_TSO != 0
+ dev->features |= NETIF_F_TSO;
+#endif
tp = dev->priv;
tp->pdev = pdev;
@@ -6321,6 +6823,7 @@
tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
#endif
spin_lock_init(&tp->lock);
+ spin_lock_init(&tp->tx_lock);
spin_lock_init(&tp->indirect_lock);
tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
@@ -6333,8 +6836,6 @@
tg3_init_link_config(tp);
- tg3_init_coalesce_config(tp);
-
tg3_init_bufmgr_config(tp);
tp->rx_pending = TG3_DEF_RX_RING_PENDING;
@@ -6351,6 +6852,8 @@
dev->set_mac_address = tg3_set_mac_addr;
dev->do_ioctl = tg3_ioctl;
dev->tx_timeout = tg3_tx_timeout;
+ dev->poll = tg3_poll;
+ dev->weight = 64;
dev->watchdog_timeo = TG3_TX_TIMEOUT;
dev->change_mtu = tg3_change_mtu;
dev->irq = pdev->irq;
@@ -6456,22 +6959,28 @@
return 0;
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_disable_ints(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_device_detach(dev);
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_halt(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
err = tg3_set_power_state(tp, state);
if (err) {
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_init_rings(tp);
tg3_init_hw(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_device_attach(dev);
@@ -6496,23 +7005,25 @@
netif_device_attach(dev);
spin_lock_irq(&tp->lock);
+ spin_lock(&tp->tx_lock);
tg3_init_rings(tp);
tg3_init_hw(tp);
tg3_enable_ints(tp);
+ spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
return 0;
}
static struct pci_driver tg3_driver = {
- name: DRV_MODULE_NAME,
- id_table: tg3_pci_tbl,
- probe: tg3_init_one,
- remove: __devexit_p(tg3_remove_one),
- suspend: tg3_suspend,
- resume: tg3_resume
+ .name = DRV_MODULE_NAME,
+ .id_table = tg3_pci_tbl,
+ .probe = tg3_init_one,
+ .remove = __devexit_p(tg3_remove_one),
+ .suspend = tg3_suspend,
+ .resume = tg3_resume
};
static int __init tg3_init(void)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)