diff options
Diffstat (limited to 'src/drivers/net/e1000/e1000.c')
-rw-r--r-- | src/drivers/net/e1000/e1000.c | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/src/drivers/net/e1000/e1000.c b/src/drivers/net/e1000/e1000.c index af8e0936..81e15790 100644 --- a/src/drivers/net/e1000/e1000.c +++ b/src/drivers/net/e1000/e1000.c @@ -73,6 +73,7 @@ e1000_get_hw_control ( struct e1000_adapter *adapter ) break; case e1000_82571: case e1000_82572: + case e1000_82576: case e1000_80003es2lan: case e1000_ich8lan: ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); @@ -253,6 +254,7 @@ e1000_configure_tx ( struct e1000_adapter *adapter ) { struct e1000_hw *hw = &adapter->hw; uint32_t tctl; + uint32_t txdctl; DBG ( "e1000_configure_tx\n" ); @@ -271,6 +273,12 @@ e1000_configure_tx ( struct e1000_adapter *adapter ) adapter->tx_tail = 0; adapter->tx_fill_ctr = 0; + if (hw->mac_type == e1000_82576) { + txdctl = E1000_READ_REG ( hw, TXDCTL ); + txdctl |= E1000_TXDCTL_QUEUE_ENABLE; + E1000_WRITE_REG ( hw, TXDCTL, txdctl ); + } + /* Setup Transmit Descriptor Settings for eop descriptor */ tctl = E1000_TCTL_PSP | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) | @@ -359,13 +367,15 @@ static void e1000_configure_rx ( struct e1000_adapter *adapter ) { struct e1000_hw *hw = &adapter->hw; - uint32_t rctl; + uint32_t rctl, rxdctl, mrqc, rxcsum; DBG ( "e1000_configure_rx\n" ); /* disable receives while setting up the descriptors */ rctl = E1000_READ_REG ( hw, RCTL ); E1000_WRITE_REG ( hw, RCTL, rctl & ~E1000_RCTL_EN ); + E1000_WRITE_FLUSH ( hw ); + mdelay(10); adapter->rx_curr = 0; @@ -377,16 +387,57 @@ e1000_configure_rx ( struct e1000_adapter *adapter ) E1000_WRITE_REG ( hw, RDLEN, adapter->rx_ring_size ); E1000_WRITE_REG ( hw, RDH, 0 ); - E1000_WRITE_REG ( hw, RDT, NUM_RX_DESC - 1 ); - - /* Enable Receives */ - rctl = ( E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_MPE - ); + if (hw->mac_type == e1000_82576) + E1000_WRITE_REG ( hw, RDT, 0 ); + else + E1000_WRITE_REG ( hw, RDT, NUM_RX_DESC - 1 ); + + /* This doesn't seem to be necessary for correct operation, + * but it seems as well to be implicit + */ + if (hw->mac_type == e1000_82576) { + rxdctl = E1000_READ_REG ( hw, RXDCTL ); + rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; + rxdctl &= 0xFFF00000; + rxdctl |= IGB_RX_PTHRESH; + rxdctl |= IGB_RX_HTHRESH << 8; + rxdctl |= IGB_RX_WTHRESH << 16; + E1000_WRITE_REG ( hw, RXDCTL, rxdctl ); + E1000_WRITE_FLUSH ( hw ); + + rxcsum = E1000_READ_REG(hw, RXCSUM); + rxcsum &= ~( E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE ); + E1000_WRITE_REG ( hw, RXCSUM, 0 ); + + /* The initial value for MRQC disables multiple receive + * queues, however this setting is not recommended. + * - IntelĀ® 82576 Gigabit Ethernet Controller Datasheet r2.41 + * Section 8.10.9 Multiple Queues Command Register - MRQC + */ + mrqc = E1000_MRQC_ENABLE_VMDQ; + E1000_WRITE_REG ( hw, MRQC, mrqc ); + } + /* Enable Receives */ + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | + E1000_RCTL_MPE; E1000_WRITE_REG ( hw, RCTL, rctl ); E1000_WRITE_FLUSH ( hw ); + /* On the 82576, RDT([0]) must not be "bumped" before + * the enable bit of RXDCTL([0]) is set. + * - IntelĀ® 82576 Gigabit Ethernet Controller Datasheet r2.41 + * Section 4.5.9 receive Initialization + * + * By observation I have found to occur when the enable bit of + * RCTL is set. The datasheet recommends polling for this bit, + * however as I see no evidence of this in the Linux igb driver + * I have omitted that step. + * - Simon Horman, May 2009 + */ + if (hw->mac_type == e1000_82576) + E1000_WRITE_REG ( hw, RDT, NUM_RX_DESC - 1 ); + DBG ( "RDBAL: %#08x\n", E1000_READ_REG ( hw, RDBAL ) ); DBG ( "RDLEN: %d\n", E1000_READ_REG ( hw, RDLEN ) ); DBG ( "RCTL: %#08x\n", E1000_READ_REG ( hw, RCTL ) ); @@ -433,6 +484,9 @@ e1000_reset ( struct e1000_adapter *adapter ) case e1000_82573: pba = E1000_PBA_20K; break; + case e1000_82576: + pba = E1000_PBA_64K; + break; case e1000_ich8lan: pba = E1000_PBA_8K; case e1000_undefined: @@ -446,6 +500,7 @@ e1000_reset ( struct e1000_adapter *adapter ) /* Set the FC high water mark to 90% of the FIFO size. * Required to clear last 3 LSB */ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8; + /* We can't use 90% on small FIFOs because the remainder * would be less than 1 full frame. In this case, we size * it to allow at least a full frame above the high water @@ -453,9 +508,20 @@ e1000_reset ( struct e1000_adapter *adapter ) if (pba < E1000_PBA_16K) fc_high_water_mark = (pba * 1024) - 1600; - adapter->hw.fc_high_water = fc_high_water_mark; - adapter->hw.fc_low_water = fc_high_water_mark - 8; - if (adapter->hw.mac_type == e1000_80003es2lan) + /* This actually applies to < e1000_82575, one revision less than + * e1000_82576, but e1000_82575 isn't currently defined in the code */ + if (adapter->hw.mac_type < e1000_82576) { + /* 8-byte granularity */ + adapter->hw.fc_high_water = fc_high_water_mark & 0xFFF8; + adapter->hw.fc_low_water = adapter->hw.fc_high_water - 8; + } else { + /* 16-byte granularity */ + adapter->hw.fc_high_water = fc_high_water_mark & 0xFFF0; + adapter->hw.fc_low_water = adapter->hw.fc_high_water - 16; + } + + if (adapter->hw.mac_type == e1000_80003es2lan || + adapter->hw.mac_type == e1000_82576) adapter->hw.fc_pause_time = 0xFFFF; else adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; @@ -1102,6 +1168,7 @@ static struct pci_device_id e1000_nics[] = { PCI_ROM(0x8086, 0x10bc, "e1000-0x10bc", "e1000-0x10bc", 0), PCI_ROM(0x8086, 0x10c4, "e1000-0x10c4", "e1000-0x10c4", 0), PCI_ROM(0x8086, 0x10c5, "e1000-0x10c5", "e1000-0x10c5", 0), + PCI_ROM(0x8086, 0x10c9, "e1000-0x10c9", "e1000-0x10c9", 0), PCI_ROM(0x8086, 0x10d9, "e1000-0x10d9", "e1000-0x10d9", 0), PCI_ROM(0x8086, 0x10da, "e1000-0x10da", "e1000-0x10da", 0), }; |