From c13e3713857d5ea572cd67f3d5749100b1963ad2 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Sat, 5 May 2007 11:50:04 -0700 Subject: [TG3]: Fix TSO bugs. 1. Remove the check for skb->len greater than MTU when doing TSO. When the destination has a smaller MSS than the source, a TSO packet may be smaller than the MTU and we still need to process it as a TSO packet. 2. On 5705A3 devices with TSO enabled, the DMA engine can hang due to a hardware bug. This patch avoids the hanging condition by reducing the DMA burst size. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9488f49ea56..b8141be56d7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3895,8 +3895,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 +4052,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; @@ -6346,8 +6344,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)) { -- cgit v1.2.3 From 989a9d239c5b9ae6053aed6e3819304930baf27d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Sat, 5 May 2007 11:51:05 -0700 Subject: [TG3]: Improve NVRAM sizing. This patch changes the NVRAM sizing procedure so that the driver can take advantage of devices with 1:1 NVRAM strapping configurations. This is useful in cases where the traditional NVRAM sizing method fails. In the event that the flash size cannot be determined, the largest known NVRAM size is used. The patch also removes support for 5755 NVRAM devices that are not supported by Broadcom and adds explicit sizing for this device. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b8141be56d7..c01bd861ac5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9286,7 +9286,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) @@ -9405,33 +9405,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: @@ -9440,6 +9438,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; } } @@ -9515,6 +9519,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) @@ -9526,7 +9532,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); -- cgit v1.2.3 From aaf84465fc994e9a840a8c0c6fa842b54cdb3426 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Sat, 5 May 2007 11:51:45 -0700 Subject: [TG3]: Clear GPIO mask before storing. The GPIO settings may change during reset and so the stored values in tp->grc_local_ctrl should be cleared first. Signed-off-by: Gary Zambrano Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c01bd861ac5..00027a14eaa 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6454,6 +6454,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 */ -- cgit v1.2.3 From a85feb8cfc53c08b6f0d770f930ca9cc6885f414 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Sat, 5 May 2007 11:52:19 -0700 Subject: [TG3]: WoL fixes. Change TG3_FLAG_SERDES_WOL_CAP to TG3_FLAG_WOL_CAP to make it easier to manage WoL. This flag is now used consistently during ethtool WoL setup and power setting changes. Signed-off-by: Gary Zambrano Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 25 +++++++++++++++---------- drivers/net/tg3.h | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 00027a14eaa..e829262ded4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -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); @@ -8034,7 +8036,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; @@ -8048,8 +8053,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); @@ -10001,8 +10005,8 @@ 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)) { @@ -10125,8 +10129,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; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index d515ed23841..f76e3107e8d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2215,7 +2215,7 @@ struct tg3 { #define TG3_FLAG_PCI_32BIT 0x00080000 #define TG3_FLAG_SRAM_USE_CONFIG 0x00100000 #define TG3_FLAG_TX_RECOVERY_PENDING 0x00200000 -#define TG3_FLAG_SERDES_WOL_CAP 0x00400000 +#define TG3_FLAG_WOL_CAP 0x00400000 #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 -- cgit v1.2.3 From 986e0aeb9ae09127b401c3baa66f15b7a31f354c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 5 May 2007 12:10:20 -0700 Subject: [TG3]: Remove reset during MAC address changes. The reset was added a while back so that ASF could re-init whatever MAC address it wanted to use after the MAC address was changed. Instead of resetting, we can just keep MAC address 1 unchanged during MAC address changes if MAC address 1 is different from MAC address 0. This fixes 2 problems: 1. Bonding calls set_mac_address in contexts that cannot sleep. It no longer sleeps with the chip reset removed. 2. When ASF shares the same MAC address as the NIC, it needs to always do that even when the MAC address is changed. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e829262ded4..321121874c7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5934,7 +5934,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 +5946,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 +5974,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 +5985,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 +6316,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); -- cgit v1.2.3 From 5cf64b8a7399999439f0d6748babb1ccb6bcad7c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 5 May 2007 12:11:21 -0700 Subject: [TG3]: Eliminate the TG3_FLAG_GOT_SERDES_FLOWCTL flag. This flag does not do anything useful. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 10 ++-------- drivers/net/tg3.h | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 321121874c7..ff157b70486 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2595,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; @@ -2616,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++) { @@ -2639,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); @@ -7400,9 +7396,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); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index f76e3107e8d..dd04a46c6f1 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2222,7 +2222,6 @@ struct tg3 { #define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 -#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 #define TG3_FLAG_CHIP_RESETTING 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; -- cgit v1.2.3 From 98efd8a6be79550767f5a9be6f3db8e7e9b747da Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Sat, 5 May 2007 12:47:25 -0700 Subject: [TG3]: Eliminate the TG3_FLAG_5701_REG_WRITE_BUG flag. This patch removes the use of the TG3_FLAG_5701_REG_WRITE_BUG flag. It's logic is only used to set a function pointer and thus the logic can be collapsed and the flag removed. [ Comment tidy by Christoph Hellwig. -DaveM ] Signed-off-by: Matt Carlson Signed-off-by: Michael Chan --- drivers/net/tg3.c | 24 ++++++++++++------------ drivers/net/tg3.h | 1 - 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ff157b70486..4154e1285d5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10673,17 +10673,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) @@ -10707,8 +10696,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)) { diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index dd04a46c6f1..c52acb0a602 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2199,7 +2199,6 @@ struct tg3 { #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 #define TG3_FLAG_USE_MI_INTERRUPT 0x00000010 #define TG3_FLAG_ENABLE_ASF 0x00000020 -#define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040 #define TG3_FLAG_POLL_SERDES 0x00000080 #define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100 #define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 -- cgit v1.2.3 From 7544b0972c1fc1a0e6c54baa1f44c81019743daa Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 5 May 2007 13:08:32 -0700 Subject: [TG3]: Add TG3_FLAG_SUPPORT_MSI flag. And fix up the code to always allow MSI on 5714 A2. Call tg3_find_peer() earlier because we need that information before we can determine whether we can set TG3_FLAG_SUPPORT_MSI or not. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 24 +++++++++++++++--------- drivers/net/tg3.h | 2 ++ 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4154e1285d5..59d6e74a4a5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7033,11 +7033,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. */ @@ -10404,6 +10400,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[] = { @@ -10559,6 +10557,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 || @@ -10572,6 +10574,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) { @@ -11897,10 +11907,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, " diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c52acb0a602..dcdfc084966 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -131,6 +131,7 @@ #define CHIPREV_ID_5752_A0_HW 0x5000 #define CHIPREV_ID_5752_A0 0x6000 #define CHIPREV_ID_5752_A1 0x6001 +#define CHIPREV_ID_5714_A2 0x9002 #define CHIPREV_ID_5906_A1 0xc001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 @@ -2221,6 +2222,7 @@ struct tg3 { #define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 +#define TG3_FLAG_SUPPORT_MSI 0x20000000 #define TG3_FLAG_CHIP_RESETTING 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; -- cgit v1.2.3