diff options
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 207 |
1 files changed, 125 insertions, 82 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9488f49ea56..e5e901ecd80 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.75" -#define DRV_MODULE_RELDATE "March 23, 2007" +#define DRV_MODULE_VERSION "3.76" +#define DRV_MODULE_RELDATE "May 5, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1300,9 +1300,11 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) msleep(1); } } - tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE | - WOL_DRV_STATE_SHUTDOWN | - WOL_DRV_WOL | WOL_SET_MAGIC_PKT); + if (tp->tg3_flags & TG3_FLAG_WOL_CAP) + tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE | + WOL_DRV_STATE_SHUTDOWN | + WOL_DRV_WOL | + WOL_SET_MAGIC_PKT); pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps); @@ -2593,10 +2595,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) { int current_link_up = 0; - if (!(mac_status & MAC_STATUS_PCS_SYNCED)) { - tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; + if (!(mac_status & MAC_STATUS_PCS_SYNCED)) goto out; - } if (tp->link_config.autoneg == AUTONEG_ENABLE) { u32 flags; @@ -2614,7 +2614,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) tg3_setup_flow_control(tp, local_adv, remote_adv); - tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; current_link_up = 1; } for (i = 0; i < 30; i++) { @@ -2637,7 +2636,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) } else { /* Forcing 1000FD link up. */ current_link_up = 1; - tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); udelay(40); @@ -3021,6 +3019,16 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) } } + if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) { + u32 val = tr32(PCIE_PWR_MGMT_THRESH); + if (!netif_carrier_ok(tp->dev)) + val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) | + tp->pwrmgmt_thresh; + else + val |= PCIE_PWR_MGMT_L1_THRESH_MSK; + tw32(PCIE_PWR_MGMT_THRESH, val); + } + return err; } @@ -3582,8 +3590,12 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) * Writing non-zero to intr-mbox-0 additional tells the * NIC to stop sending us irqs, engaging "in-intr-handler" * event coalescing. + * + * Flush the mailbox to de-assert the IRQ immediately to prevent + * spurious interrupts. The flush impacts performance but + * excessive spurious interrupts can be worse in some cases. */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (tg3_irq_sync(tp)) goto out; sblk->status &= ~SD_STATUS_UPDATED; @@ -3627,8 +3639,12 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * writing non-zero to intr-mbox-0 additional tells the * NIC to stop sending us irqs, engaging "in-intr-handler" * event coalescing. + * + * Flush the mailbox to de-assert the IRQ immediately to prevent + * spurious interrupts. The flush impacts performance but + * excessive spurious interrupts can be worse in some cases. */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (tg3_irq_sync(tp)) goto out; if (netif_rx_schedule_prep(dev)) { @@ -3895,8 +3911,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) entry = tp->tx_prod; base_flags = 0; mss = 0; - if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->gso_size) != 0) { + if ((mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -4053,8 +4068,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; mss = 0; - if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->gso_size) != 0) { + if ((mss = skb_shinfo(skb)->gso_size) != 0) { struct iphdr *iph; int tcp_opt_len, ip_tcp_len, hdr_len; @@ -5934,7 +5948,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp) /* tp->lock is held. */ -static void __tg3_set_mac_addr(struct tg3 *tp) +static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1) { u32 addr_high, addr_low; int i; @@ -5946,6 +5960,8 @@ static void __tg3_set_mac_addr(struct tg3 *tp) (tp->dev->dev_addr[4] << 8) | (tp->dev->dev_addr[5] << 0)); for (i = 0; i < 4; i++) { + if (i == 1 && skip_mac_1) + continue; tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high); tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); } @@ -5972,7 +5988,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) { struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; - int err = 0; + int err = 0, skip_mac_1 = 0; if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; @@ -5983,22 +5999,21 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) return 0; if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - /* Reset chip so that ASF can re-init any MAC addresses it - * needs. - */ - tg3_netif_stop(tp); - tg3_full_lock(tp, 1); + u32 addr0_high, addr0_low, addr1_high, addr1_low; - tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - err = tg3_restart_hw(tp, 0); - if (!err) - tg3_netif_start(tp); - tg3_full_unlock(tp); - } else { - spin_lock_bh(&tp->lock); - __tg3_set_mac_addr(tp); - spin_unlock_bh(&tp->lock); + addr0_high = tr32(MAC_ADDR_0_HIGH); + addr0_low = tr32(MAC_ADDR_0_LOW); + addr1_high = tr32(MAC_ADDR_1_HIGH); + addr1_low = tr32(MAC_ADDR_1_LOW); + + /* Skip MAC addr 1 if ASF is using it. */ + if ((addr0_high != addr1_high || addr0_low != addr1_low) && + !(addr1_high == 0 && addr1_low == 0)) + skip_mac_1 = 1; } + spin_lock_bh(&tp->lock); + __tg3_set_mac_addr(tp, skip_mac_1); + spin_unlock_bh(&tp->lock); return err; } @@ -6315,7 +6330,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->rx_jumbo_ptr); /* Initialize MAC address and backoff seed. */ - __tg3_set_mac_addr(tp); + __tg3_set_mac_addr(tp, 0); /* MTU + ethernet header + FCS + optional VLAN tag */ tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8); @@ -6346,8 +6361,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) { if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE && - (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 || - tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128; } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { @@ -6457,6 +6471,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; + tp->grc_local_ctrl &= ~gpio_mask; tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ @@ -7036,11 +7051,7 @@ static int tg3_open(struct net_device *dev) if (err) return err; - if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) && - (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) && - !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) && - (tp->pdev_peer == tp->pdev))) { + if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) { /* All MSI supporting chips should support tagged * status. Assert that this is the case. */ @@ -7399,9 +7410,7 @@ static int tg3_close(struct net_device *dev) tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); - tp->tg3_flags &= - ~(TG3_FLAG_INIT_COMPLETE | - TG3_FLAG_GOT_SERDES_FLOWCTL); + tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; tg3_full_unlock(tp); @@ -8036,7 +8045,10 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct tg3 *tp = netdev_priv(dev); - wol->supported = WAKE_MAGIC; + if (tp->tg3_flags & TG3_FLAG_WOL_CAP) + wol->supported = WAKE_MAGIC; + else + wol->supported = 0; wol->wolopts = 0; if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) wol->wolopts = WAKE_MAGIC; @@ -8050,8 +8062,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; if ((wol->wolopts & WAKE_MAGIC) && - tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && - !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) + !(tp->tg3_flags & TG3_FLAG_WOL_CAP)) return -EINVAL; spin_lock_bh(&tp->lock); @@ -9289,7 +9300,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) return; } } - tp->nvram_size = 0x20000; + tp->nvram_size = 0x80000; } static void __devinit tg3_get_nvram_info(struct tg3 *tp) @@ -9408,33 +9419,31 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) { - u32 nvcfg1; + u32 nvcfg1, protect = 0; nvcfg1 = tr32(NVRAM_CFG1); /* NVRAM protection for TPM */ - if (nvcfg1 & (1 << 27)) + if (nvcfg1 & (1 << 27)) { tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + protect = 1; + } - switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { - case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ: - case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; - - nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; - tw32(NVRAM_CFG1, nvcfg1); - break; - case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK; + switch (nvcfg1) { case FLASH_5755VENDOR_ATMEL_FLASH_1: case FLASH_5755VENDOR_ATMEL_FLASH_2: case FLASH_5755VENDOR_ATMEL_FLASH_3: - case FLASH_5755VENDOR_ATMEL_FLASH_4: tp->nvram_jedecnum = JEDEC_ATMEL; tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; tp->tg3_flags2 |= TG3_FLG2_FLASH; tp->nvram_pagesize = 264; + if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1) + tp->nvram_size = (protect ? 0x3e200 : 0x80000); + else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2) + tp->nvram_size = (protect ? 0x1f200 : 0x40000); + else + tp->nvram_size = (protect ? 0x1f200 : 0x20000); break; case FLASH_5752VENDOR_ST_M45PE10: case FLASH_5752VENDOR_ST_M45PE20: @@ -9443,6 +9452,12 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; tp->tg3_flags2 |= TG3_FLG2_FLASH; tp->nvram_pagesize = 256; + if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10) + tp->nvram_size = (protect ? 0x10000 : 0x20000); + else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20) + tp->nvram_size = (protect ? 0x10000 : 0x40000); + else + tp->nvram_size = (protect ? 0x20000 : 0x80000); break; } } @@ -9518,6 +9533,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) } tg3_enable_nvram_access(tp); + tp->nvram_size = 0; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) @@ -9529,7 +9546,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) else tg3_get_nvram_info(tp); - tg3_get_nvram_size(tp); + if (tp->nvram_size == 0) + tg3_get_nvram_size(tp); tg3_disable_nvram_access(tp); tg3_nvram_unlock(tp); @@ -9996,14 +10014,16 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = PHY_ID_INVALID; tp->led_ctrl = LED_CTRL_MODE_PHY_1; - /* Assume an onboard device by default. */ - tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + /* Assume an onboard device and WOL capable by default. */ + tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT | TG3_FLAG_WOL_CAP; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) { tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; tp->tg3_flags2 |= TG3_FLG2_IS_NIC; } + if (tr32(VCPU_CFGSHDW) & VCPU_CFGSHDW_ASPM_DBNC) + tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; return; } @@ -10120,8 +10140,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; } - if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) - tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; + if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && + !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)) + tp->tg3_flags &= ~TG3_FLAG_WOL_CAP; if (cfg2 & (1 << 17)) tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; @@ -10130,6 +10151,14 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) /* bootcode if bit 18 is set */ if (cfg2 & (1 << 18)) tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; + + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + u32 cfg3; + + tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3); + if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE) + tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; + } } } @@ -10399,6 +10428,8 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) } } +static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); + static int __devinit tg3_get_invariants(struct tg3 *tp) { static struct pci_device_id write_reorder_chipsets[] = { @@ -10554,6 +10585,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff; tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) + tp->pdev_peer = tg3_find_peer(tp); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || @@ -10567,6 +10602,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { + tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI; + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX || + GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 && + tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 && + tp->pdev_peer == tp->pdev)) + tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { @@ -10668,17 +10711,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG; - /* Back to back register writes can cause problems on this chip, - * the workaround is to read back all reg writes except those to - * mailbox regs. See tg3_write_indirect_reg32(). - * - * PCI Express 5750_A0 rev chips need this workaround too. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || - ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && - tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) - tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG; - if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0) tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED; if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0) @@ -10702,8 +10734,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Various workaround register access methods */ if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) tp->write32 = tg3_write_indirect_reg32; - else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || + ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && + tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) { + /* + * Back to back register writes can cause problems on these + * chips, the workaround is to read back all reg writes + * except those to mailbox regs. + * + * See tg3_write_indirect_reg32(). + */ tp->write32 = tg3_write_flush_reg32; + } + if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) || (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) { @@ -10983,6 +11026,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; + if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) + tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) & + PCIE_PWR_MGMT_L1_THRESH_MSK; + return err; } @@ -11892,10 +11939,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->rx_pending = 63; } - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) - tp->pdev_peer = tg3_find_peer(tp); - err = tg3_get_device_address(tp); if (err) { printk(KERN_ERR PFX "Could not obtain valid ethernet address, " |