]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/tg3.c
[PATCH] isdn4linux: Siemens Gigaset drivers: mutex conversion
[linux-2.6-omap-h63xx.git] / drivers / net / tg3.c
index b5473325bff44060a8dc4b8cba7938e1e13bb964..73e271e59c6a20c4401c3aaef08fb98642787286 100644 (file)
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.54"
-#define DRV_MODULE_RELDATE     "Mar 23, 2006"
+#define DRV_MODULE_VERSION     "3.56"
+#define DRV_MODULE_RELDATE     "Apr 1, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
        unsigned long flags;
 
        spin_lock_irqsave(&tp->indirect_lock, flags);
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+       if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
-       /* Always leave this as zero. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-       spin_unlock_irqrestore(&tp->indirect_lock, flags);
-}
+               /* Always leave this as zero. */
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       } else {
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+               tw32_f(TG3PCI_MEM_WIN_DATA, val);
 
-static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
-{
-       /* If no workaround is needed, write to mem space directly */
-       if (tp->write32 != tg3_write_indirect_reg32)
-               tw32(NIC_SRAM_WIN_BASE + off, val);
-       else
-               tg3_write_mem(tp, off, val);
+               /* Always leave this as zero. */
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       }
+       spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
 static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
@@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
        unsigned long flags;
 
        spin_lock_irqsave(&tp->indirect_lock, flags);
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-       pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+       if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+               pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
-       /* Always leave this as zero. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+               /* Always leave this as zero. */
+               pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       } else {
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+               *val = tr32(TG3PCI_MEM_WIN_DATA);
+
+               /* Always leave this as zero. */
+               tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+       }
        spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
@@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                }
        }
 
+       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
        /* Finally, set the new power state. */
        pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
        udelay(100);    /* Delay after power state change */
 
-       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
        return 0;
 }
 
@@ -2959,9 +2966,7 @@ static void tg3_tx(struct tg3 *tp)
                struct sk_buff *skb = ri->skb;
                int i;
 
-               if (unlikely(skb == NULL))
-                       BUG();
-
+               BUG_ON(skb == NULL);
                pci_unmap_single(tp->pdev,
                                 pci_unmap_addr(ri, mapping),
                                 skb_headlen(skb),
@@ -2972,12 +2977,10 @@ static void tg3_tx(struct tg3 *tp)
                sw_idx = NEXT_TX(sw_idx);
 
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       if (unlikely(sw_idx == hw_idx))
-                               BUG();
+                       BUG_ON(sw_idx == hw_idx);
 
                        ri = &tp->tx_buffers[sw_idx];
-                       if (unlikely(ri->skb != NULL))
-                               BUG();
+                       BUG_ON(ri->skb != NULL);
 
                        pci_unmap_page(tp->pdev,
                                       pci_unmap_addr(ri, mapping),
@@ -3600,7 +3603,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
                                          int len)
 {
 #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
-       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+       if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
                return (((u64) mapping + len) > DMA_40BIT_MASK);
        return 0;
 #else
@@ -4928,9 +4931,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 {
        int i;
 
-       if (offset == TX_CPU_BASE &&
-           (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
-               BUG();
+       BUG_ON(offset == TX_CPU_BASE &&
+           (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
 
        if (offset == RX_CPU_BASE) {
                for (i = 0; i < 10000; i++) {
@@ -5833,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp)
                          GRC_MODE_NO_TX_PHDR_CSUM |
                          GRC_MODE_NO_RX_PHDR_CSUM);
        tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-       if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
-               tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
-       if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
-               tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+       /* Pseudo-header checksum is done by hardware logic and not
+        * the offload processers, so make the chip do the pseudo-
+        * header checksums on receive.  For transmit it is more
+        * convenient to do the pseudo-header checksum in software
+        * as Linux does that on transmit for us in all cases.
+        */
+       tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 
        tw32(GRC_MODE,
             tp->grc_mode |
@@ -6461,6 +6467,9 @@ static void tg3_timer(unsigned long __opaque)
 {
        struct tg3 *tp = (struct tg3 *) __opaque;
 
+       if (tp->irq_sync)
+               goto restart_timer;
+
        spin_lock(&tp->lock);
 
        if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
@@ -6537,11 +6546,11 @@ static void tg3_timer(unsigned long __opaque)
                if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
                        u32 val;
 
-                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
-                                          FWCMD_NICDRV_ALIVE2);
-                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
+                                     FWCMD_NICDRV_ALIVE2);
+                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
                        /* 5 seconds timeout */
-                       tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
+                       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
                        val = tr32(GRC_RX_CPU_EVENT);
                        val |= (1 << 14);
                        tw32(GRC_RX_CPU_EVENT, val);
@@ -6551,6 +6560,7 @@ static void tg3_timer(unsigned long __opaque)
 
        spin_unlock(&tp->lock);
 
+restart_timer:
        tp->timer.expires = jiffies + tp->timer_offset;
        add_timer(&tp->timer);
 }
@@ -8035,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp)
                for (i = 0; i < size; i++)
                        csum8 += buf8[i];
 
-               if (csum8 == 0)
-                       return 0;
-               return -EIO;
+               if (csum8 == 0) {
+                       err = 0;
+                       goto out;
+               }
+
+               err = -EIO;
+               goto out;
        }
 
        /* Bootstrap checksum at offset 0x10 */
@@ -8399,8 +8413,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                }
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
                           MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
-               if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+               if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
                        mac_mode &= ~MAC_MODE_LINK_POLARITY;
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                                    MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+               }
                tw32(MAC_MODE, mac_mode);
        }
        else
@@ -9529,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
        /* Do not even try poking around in here on Sun parts.  */
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
+       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+               /* All SUN chips are built-in LOMs. */
+               tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
                return;
+       }
 
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -9628,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
                        tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-               if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
-                   (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
+               if (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) {
@@ -10255,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
        }
 
+       if (tp->write32 == tg3_write_indirect_reg32 ||
+           ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
+           (tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+               tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
+
        /* Get eeprom hw config before calling tg3_set_power_state().
         * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
         * determined before calling tg3_set_power_state() so that
@@ -10297,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
                tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
 
-       /* Pseudo-header checksum is done by hardware logic and not
-        * the offload processers, so make the chip do the pseudo-
-        * header checksums on receive.  For transmit it is more
-        * convenient to do the pseudo-header checksum in software
-        * as Linux does that on transmit for us in all cases.
-        */
-       tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
-       tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
-
        /* Derive initial jumbo mode from MTU assigned in
         * ether_setup() via the alloc_etherdev() call
         */
@@ -10531,6 +10547,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
        u32 hi, lo, mac_offset;
+       int addr_ok = 0;
 
 #ifdef CONFIG_SPARC64
        if (!tg3_get_macaddr_sparc(tp))
@@ -10560,29 +10577,34 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
                dev->dev_addr[3] = (lo >> 16) & 0xff;
                dev->dev_addr[4] = (lo >>  8) & 0xff;
                dev->dev_addr[5] = (lo >>  0) & 0xff;
-       }
-       /* Next, try NVRAM. */
-       else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
-                !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);
-               dev->dev_addr[3] = ((lo >>  8) & 0xff);
-               dev->dev_addr[4] = ((lo >> 16) & 0xff);
-               dev->dev_addr[5] = ((lo >> 24) & 0xff);
-       }
-       /* Finally just fetch it out of the MAC control regs. */
-       else {
-               hi = tr32(MAC_ADDR_0_HIGH);
-               lo = tr32(MAC_ADDR_0_LOW);
 
-               dev->dev_addr[5] = lo & 0xff;
-               dev->dev_addr[4] = (lo >> 8) & 0xff;
-               dev->dev_addr[3] = (lo >> 16) & 0xff;
-               dev->dev_addr[2] = (lo >> 24) & 0xff;
-               dev->dev_addr[1] = hi & 0xff;
-               dev->dev_addr[0] = (hi >> 8) & 0xff;
+               /* Some old bootcode may report a 0 MAC address in SRAM */
+               addr_ok = is_valid_ether_addr(&dev->dev_addr[0]);
+       }
+       if (!addr_ok) {
+               /* Next, try NVRAM. */
+               if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
+                   !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);
+                       dev->dev_addr[3] = ((lo >>  8) & 0xff);
+                       dev->dev_addr[4] = ((lo >> 16) & 0xff);
+                       dev->dev_addr[5] = ((lo >> 24) & 0xff);
+               }
+               /* Finally just fetch it out of the MAC control regs. */
+               else {
+                       hi = tr32(MAC_ADDR_0_HIGH);
+                       lo = tr32(MAC_ADDR_0_LOW);
+
+                       dev->dev_addr[5] = lo & 0xff;
+                       dev->dev_addr[4] = (lo >> 8) & 0xff;
+                       dev->dev_addr[3] = (lo >> 16) & 0xff;
+                       dev->dev_addr[2] = (lo >> 24) & 0xff;
+                       dev->dev_addr[1] = hi & 0xff;
+                       dev->dev_addr[0] = (hi >> 8) & 0xff;
+               }
        }
 
        if (!is_valid_ether_addr(&dev->dev_addr[0])) {