]> err.no Git - linux-2.6/commitdiff
e1000: Fixes for 8357x
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 13 Dec 2005 05:06:22 +0000 (00:06 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 13 Dec 2005 05:06:22 +0000 (00:06 -0500)
- TSO workaround
- Fixes eeprom version reporting
- Fix loopback test
- Fix for WOL

Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c

index 3f653a93e1bc78dc9ab7e730bdc9490cac4f5650..e02e9ba2e18b0b66166f2f877a2e282f0a4926f8 100644 (file)
@@ -188,11 +188,13 @@ struct e1000_tx_ring {
        /* array of buffer information structs */
        struct e1000_buffer *buffer_info;
 
-       struct e1000_buffer previous_buffer_info;
        spinlock_t tx_lock;
        uint16_t tdh;
        uint16_t tdt;
        uint64_t pkt;
+
+       boolean_t last_tx_tso;
+
 };
 
 struct e1000_rx_ring {
index 8646914964e7fa16be01f50db5c508af73ae9b10..c88f1a3c1b1db7d58a87a779d6517480e514d31c 100644 (file)
@@ -562,10 +562,29 @@ e1000_get_drvinfo(struct net_device *netdev,
                        struct ethtool_drvinfo *drvinfo)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
+       char firmware_version[32];
+       uint16_t eeprom_data;
 
        strncpy(drvinfo->driver,  e1000_driver_name, 32);
        strncpy(drvinfo->version, e1000_driver_version, 32);
-       strncpy(drvinfo->fw_version, "N/A", 32);
+       
+       /* EEPROM image version # is reported as firware version # for
+        * 8257{1|2|3} controllers */
+       e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
+       switch (adapter->hw.mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+       case e1000_82573:
+               sprintf(firmware_version, "%d.%d-%d", 
+                       (eeprom_data & 0xF000) >> 12,
+                       (eeprom_data & 0x0FF0) >> 4,
+                       eeprom_data & 0x000F);
+               break;
+       default:
+               sprintf(firmware_version, "n/a");
+       }
+
+       strncpy(drvinfo->fw_version, firmware_version, 32);
        strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
        drvinfo->n_stats = E1000_STATS_LEN;
        drvinfo->testinfo_len = E1000_TEST_LEN;
@@ -1309,21 +1328,32 @@ static int
 e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
        uint32_t rctl;
+       struct e1000_hw *hw = &adapter->hw;
 
-       if(adapter->hw.media_type == e1000_media_type_fiber ||
-          adapter->hw.media_type == e1000_media_type_internal_serdes) {
-               if(adapter->hw.mac_type == e1000_82545 ||
-                  adapter->hw.mac_type == e1000_82546 ||
-                  adapter->hw.mac_type == e1000_82545_rev_3 ||
-                  adapter->hw.mac_type == e1000_82546_rev_3)
+       if (hw->media_type == e1000_media_type_fiber ||
+          hw->media_type == e1000_media_type_internal_serdes) {
+               switch (hw->mac_type) {
+               case e1000_82545:
+               case e1000_82546:
+               case e1000_82545_rev_3:
+               case e1000_82546_rev_3:
                        return e1000_set_phy_loopback(adapter);
-               else {
-                       rctl = E1000_READ_REG(&adapter->hw, RCTL);
+                       break;
+               case e1000_82571:
+               case e1000_82572:
+#define E1000_SERDES_LB_ON 0x410
+                       e1000_set_phy_loopback(adapter);
+                       E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+                       msec_delay(10);
+                       return 0;
+                       break;
+               default:
+                       rctl = E1000_READ_REG(hw, RCTL);
                        rctl |= E1000_RCTL_LBM_TCVR;
-                       E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+                       E1000_WRITE_REG(hw, RCTL, rctl);
                        return 0;
                }
-       } else if(adapter->hw.media_type == e1000_media_type_copper)
+       } else if (hw->media_type == e1000_media_type_copper)
                return e1000_set_phy_loopback(adapter);
 
        return 7;
@@ -1334,25 +1364,36 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
        uint32_t rctl;
        uint16_t phy_reg;
+       struct e1000_hw *hw = &adapter->hw;
 
        rctl = E1000_READ_REG(&adapter->hw, RCTL);
        rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
        E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 
-       if(adapter->hw.media_type == e1000_media_type_copper ||
-          ((adapter->hw.media_type == e1000_media_type_fiber ||
-            adapter->hw.media_type == e1000_media_type_internal_serdes) &&
-           (adapter->hw.mac_type == e1000_82545 ||
-            adapter->hw.mac_type == e1000_82546 ||
-            adapter->hw.mac_type == e1000_82545_rev_3 ||
-            adapter->hw.mac_type == e1000_82546_rev_3))) {
-               adapter->hw.autoneg = TRUE;
-               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
-               if(phy_reg & MII_CR_LOOPBACK) {
+       switch (hw->mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               if (hw->media_type == e1000_media_type_fiber ||
+                  hw->media_type == e1000_media_type_internal_serdes){
+#define E1000_SERDES_LB_OFF 0x400
+                       E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+                       msec_delay(10);
+                       break;
+               }
+               /* fall thru for Cu adapters */
+       case e1000_82545:
+       case e1000_82546:
+       case e1000_82545_rev_3:
+       case e1000_82546_rev_3:
+       default:
+               hw->autoneg = TRUE;
+               e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
+               if (phy_reg & MII_CR_LOOPBACK) {
                        phy_reg &= ~MII_CR_LOOPBACK;
-                       e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
-                       e1000_phy_reset(&adapter->hw);
+                       e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
+                       e1000_phy_reset(hw);
                }
+               break;
        }
 }
 
@@ -1681,6 +1722,14 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
                msleep_interruptible(data * 1000);
                del_timer_sync(&adapter->blink_timer);
        }
+       else if(adapter->hw.mac_type < e1000_82573) {
+               E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
+                       E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+                       (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+                       (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+                       (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+               msleep_interruptible(data * 1000);
+       }
        else {
                E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
                        E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | 
index a267c5235fc0d153b08c07a7b4fe3fc41a1df666..136fc031e4ad555d168a8b0ac002b460ebea8ebb 100644 (file)
@@ -563,11 +563,13 @@ e1000_reset_hw(struct e1000_hw *hw)
             msec_delay(20);
             break;
         case e1000_82573:
-            udelay(10);
-            ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
-            ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-            E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-            E1000_WRITE_FLUSH(hw);
+            if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
+                udelay(10);
+                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+                E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+                E1000_WRITE_FLUSH(hw);
+            }
             /* fall through */
         case e1000_82571:
         case e1000_82572:
@@ -844,19 +846,27 @@ e1000_setup_link(struct e1000_hw *hw)
      * control setting, then the variable hw->fc will
      * be initialized based on a value in the EEPROM.
      */
-    if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
-        DEBUGOUT("EEPROM Read Error\n");
-        return -E1000_ERR_EEPROM;
-    }
-
-    if(hw->fc == e1000_fc_default) {
-        if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
-            hw->fc = e1000_fc_none;
-        else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
-                EEPROM_WORD0F_ASM_DIR)
-            hw->fc = e1000_fc_tx_pause;
-        else
+    if (hw->fc == e1000_fc_default) {
+        switch (hw->mac_type) {
+        case e1000_82573:
             hw->fc = e1000_fc_full;
+            break;
+        default:
+            ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+                                        1, &eeprom_data);
+            if (ret_val) {
+                DEBUGOUT("EEPROM Read Error\n");
+                return -E1000_ERR_EEPROM;
+            }
+            if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
+                hw->fc = e1000_fc_none;
+            else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
+                    EEPROM_WORD0F_ASM_DIR)
+                hw->fc = e1000_fc_tx_pause;
+            else
+                hw->fc = e1000_fc_full;
+            break;
+        }
     }
 
     /* We want to save off the original Flow Control configuration just
@@ -2962,13 +2972,22 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
     if(hw->mac_type > e1000_82543) {
         /* Read the device control register and assert the E1000_CTRL_PHY_RST
          * bit. Then, take it out of reset.
+         * For pre-e1000_82571 hardware, we delay for 10ms between the assert 
+         * and deassert.  For e1000_82571 hardware and later, we instead delay
+         * for 10ms after the deassertion.
          */
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
         E1000_WRITE_FLUSH(hw);
-        msec_delay(10);
+        
+        if (hw->mac_type < e1000_82571) 
+            msec_delay(10);
+        
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
+        
+        if (hw->mac_type >= e1000_82571)
+            msec_delay(10);
     } else {
         /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
          * bit to put the PHY into reset. Then, take it out of reset.
@@ -5278,9 +5297,13 @@ e1000_get_bus_info(struct e1000_hw *hw)
         hw->bus_speed = e1000_bus_speed_unknown;
         hw->bus_width = e1000_bus_width_unknown;
         break;
-    case e1000_82571:
     case e1000_82572:
     case e1000_82573:
+        hw->bus_type = e1000_bus_type_pci_express;
+        hw->bus_speed = e1000_bus_speed_2500;
+        hw->bus_width = e1000_bus_width_pciex_1;
+        break;
+    case e1000_82571:
         hw->bus_type = e1000_bus_type_pci_express;
         hw->bus_speed = e1000_bus_speed_2500;
         hw->bus_width = e1000_bus_width_pciex_4;
@@ -6650,6 +6673,12 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
         break;
     }
 
+    /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+     * Need to wait for PHY configuration completion before accessing NVM
+     * and PHY. */
+    if (hw->mac_type == e1000_82573)
+        msec_delay(25);
+
     return E1000_SUCCESS;
 }
 
index 76ce12809a11641cc6788fcc75a99cdca1d5dd70..7caa35748ceac9c8236d1510f9335b2e57f9073b 100644 (file)
@@ -123,6 +123,7 @@ typedef enum {
     e1000_bus_width_32,
     e1000_bus_width_64,
     e1000_bus_width_pciex_1,
+    e1000_bus_width_pciex_2,
     e1000_bus_width_pciex_4,
     e1000_bus_width_reserved
 } e1000_bus_width;
@@ -149,6 +150,7 @@ typedef enum {
     e1000_igp_cable_length_90  = 90,
     e1000_igp_cable_length_100 = 100,
     e1000_igp_cable_length_110 = 110,
+    e1000_igp_cable_length_115 = 115,
     e1000_igp_cable_length_120 = 120,
     e1000_igp_cable_length_130 = 130,
     e1000_igp_cable_length_140 = 140,
@@ -1457,6 +1459,7 @@ struct e1000_hw {
 #define E1000_EECD_AUPDEN    0x00100000 /* Enable Autonomous FLASH update */
 #define E1000_EECD_SHADV     0x00200000 /* Shadow RAM Data Valid */
 #define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
+#define E1000_EECD_SECVAL_SHIFT      22
 #define E1000_STM_OPCODE     0xDB00
 #define E1000_HICR_FW_RESET  0xC0
 
@@ -1951,7 +1954,6 @@ struct e1000_host_command_info {
 
 #define E1000_MDALIGN          4096
 
-#define E1000_GCR_BEM32                 0x00400000
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
 #define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
index e0ae248b4313084337e07ff85279d4ed8d2de116..438a931fd55df4c6dd57e00d9480f35c4e9fb461 100644 (file)
@@ -711,6 +711,7 @@ e1000_probe(struct pci_dev *pdev,
                break;
        case e1000_82546:
        case e1000_82546_rev_3:
+       case e1000_82571:
                if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
                   && (adapter->hw.media_type == e1000_media_type_copper)) {
                        e1000_read_eeprom(&adapter->hw,
@@ -1158,7 +1159,6 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
                return -ENOMEM;
        }
        memset(txdr->buffer_info, 0, size);
-       memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
 
        /* round up to nearest 4K */
 
@@ -1813,11 +1813,6 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
 
        /* Free all the Tx ring sk_buffs */
 
-       if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
-               e1000_unmap_and_free_tx_resource(adapter,
-                               &tx_ring->previous_buffer_info);
-       }
-
        for(i = 0; i < tx_ring->count; i++) {
                buffer_info = &tx_ring->buffer_info[i];
                e1000_unmap_and_free_tx_resource(adapter, buffer_info);
@@ -1832,6 +1827,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
 
        tx_ring->next_to_use = 0;
        tx_ring->next_to_clean = 0;
+       tx_ring->last_tx_tso = 0;
 
        writel(0, adapter->hw.hw_addr + tx_ring->tdh);
        writel(0, adapter->hw.hw_addr + tx_ring->tdt);
@@ -2437,6 +2433,16 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
                buffer_info = &tx_ring->buffer_info[i];
                size = min(len, max_per_txd);
 #ifdef NETIF_F_TSO
+               /* Workaround for Controller erratum --
+                * descriptor for non-tso packet in a linear SKB that follows a
+                * tso gets written back prematurely before the data is fully
+                * DMAd to the controller */
+               if (!skb->data_len && tx_ring->last_tx_tso &&
+                               !skb_shinfo(skb)->tso_size) {
+                       tx_ring->last_tx_tso = 0;
+                       size -= 4;
+               }
+
                /* Workaround for premature desc write-backs
                 * in TSO mode.  Append 4-byte sentinel desc */
                if(unlikely(mss && !nr_frags && size == len && size > 8))
@@ -2693,6 +2699,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if(skb->ip_summed == CHECKSUM_HW)
                count++;
 #endif
+
+#ifdef NETIF_F_TSO
+       /* Controller Erratum workaround */
+       if (!skb->data_len && tx_ring->last_tx_tso &&
+               !skb_shinfo(skb)->tso_size)
+               count++;
+#endif
+
        count += TXD_USE_COUNT(len, max_txd_pwr);
 
        if(adapter->pcix_82544)
@@ -2774,9 +2788,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                return NETDEV_TX_OK;
        }
 
-       if (likely(tso))
+       if (likely(tso)) {
+               tx_ring->last_tx_tso = 1;
                tx_flags |= E1000_TX_FLAGS_TSO;
-       else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+       else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
                tx_flags |= E1000_TX_FLAGS_CSUM;
 
        /* Old method was to assume IPv4 packet by default if TSO was enabled.
@@ -3227,37 +3242,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
        eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
        while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
-               /* Premature writeback of Tx descriptors clear (free buffers
-                * and unmap pci_mapping) previous_buffer_info */
-               if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
-                       e1000_unmap_and_free_tx_resource(adapter,
-                                       &tx_ring->previous_buffer_info);
-               }
-
                for(cleaned = FALSE; !cleaned; ) {
                        tx_desc = E1000_TX_DESC(*tx_ring, i);
                        buffer_info = &tx_ring->buffer_info[i];
                        cleaned = (i == eop);
 
-#ifdef NETIF_F_TSO
-                       if (!(netdev->features & NETIF_F_TSO)) {
-#endif
-                               e1000_unmap_and_free_tx_resource(adapter,
-                                                                buffer_info);
-#ifdef NETIF_F_TSO
-                       } else {
-                               if (cleaned) {
-                                       memcpy(&tx_ring->previous_buffer_info,
-                                              buffer_info,
-                                              sizeof(struct e1000_buffer));
-                                       memset(buffer_info, 0,
-                                              sizeof(struct e1000_buffer));
-                               } else {
-                                       e1000_unmap_and_free_tx_resource(
-                                           adapter, buffer_info);
-                               }
-                       }
-#endif
+                       e1000_unmap_and_free_tx_resource(adapter, buffer_info);
 
                        tx_desc->buffer_addr = 0;
                        tx_desc->lower.data = 0;
@@ -3318,12 +3308,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
                        netif_stop_queue(netdev);
                }
        }
-#ifdef NETIF_F_TSO
-       if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
-           time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
-               e1000_unmap_and_free_tx_resource(
-                   adapter, &tx_ring->previous_buffer_info);
-#endif
        return cleaned;
 }