void igb_rx_fifo_flush_82575(struct e1000_hw *hw) { u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; if (hw->mac.type != e1000_82575 || !(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; for (i = 0; i < 4; i++) { rxdctl[i] = rd32(E1000_RXDCTL(i)); wr32(E1000_RXDCTL(i), rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); } for (ms_wait = 0; ms_wait < 10; ms_wait++) { msleep(1); rx_enabled = 0; for (i = 0; i < 4; i++) rx_enabled |= rd32(E1000_RXDCTL(i)); if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) break; } if (ms_wait == 10) hw_dbg("Queue disable timed out after 10ms\n"); rfctl = rd32(E1000_RFCTL); wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = rd32(E1000_RLPML); wr32(E1000_RLPML, 0); rctl = rd32(E1000_RCTL); temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); temp_rctl |= E1000_RCTL_LPE; wr32(E1000_RCTL, temp_rctl); wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN); wrfl(); msleep(2); for (i = 0; i < 4; i++) wr32(E1000_RXDCTL(i), rxdctl[i]); wr32(E1000_RCTL, rctl); wrfl(); wr32(E1000_RLPML, rlpml); wr32(E1000_RFCTL, rfctl); rd32(E1000_ROC); rd32(E1000_RNBC); rd32(E1000_MPC); }
/** * intelConfigureRx - Configure Receive Unit after Reset * @adapter: board private structure * * Configure the Rx unit of the MAC after a reset. **/ void IntelMausi::intelConfigureRx(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 rctl, rxcsum, ctrl_ext; /* disable receives while setting up the descriptors */ rctl = intelReadMem32(E1000_RCTL); intelFlush(); usleep_range(10000, 20000); /* set the Receive Delay Timer Register */ intelWriteMem32(E1000_RDTR, adapter->rx_int_delay); /* irq moderation */ intelWriteMem32(E1000_RADV, adapter->rx_abs_int_delay); /* Set interrupt throttle value. */ intelWriteMem32(E1000_ITR, intrThrValue); /* Auto-Mask interrupts upon ICR access. */ ctrl_ext = intelReadMem32(E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_IAME; intelWriteMem32(E1000_IAM, 0xffffffff); intelWriteMem32(E1000_CTRL_EXT, ctrl_ext); e1e_flush(); /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ intelInitRxRing(); /* Enable Receive Checksum Offload for TCP and UDP */ rxcsum = intelReadMem32(E1000_RXCSUM); rxcsum |= E1000_RXCSUM_TUOFL; intelWriteMem32(E1000_RXCSUM, rxcsum); /* With jumbo frames, excessive C-state transition latencies result * in dropped transactions. */ if (mtu > ETH_DATA_LEN) { //u32 lat = ((intelReadMem32(E1000_PBA) & E1000_PBA_RXA_MASK) * 1024 - adapter->max_frame_size) * 8 / 1000; if (adapter->flags & FLAG_IS_ICH) { u32 rxdctl = intelReadMem32(E1000_RXDCTL(0)); intelWriteMem32(E1000_RXDCTL(0), rxdctl | 0x3); } //pm_qos_update_request(&adapter->netdev->pm_qos_req, lat); } else { //pm_qos_update_request(&adapter->netdev->pm_qos_req, PM_QOS_DEFAULT_VALUE); } intelWriteMem32(E1000_RCTL, rctl); }
/** * e1000e_open - Called when a network interface is made active * * @v netdev network interface device structure * @ret rc Return status code, 0 on success, negative value on failure * **/ static int e1000e_open ( struct net_device *netdev ) { struct e1000_adapter *adapter = netdev_priv(netdev); int err; DBGP ( "e1000e_open\n" ); /* allocate transmit descriptors */ err = e1000e_setup_tx_resources ( adapter ); if ( err ) { DBG ( "Error setting up TX resources!\n" ); goto err_setup_tx; } /* allocate receive descriptors */ err = e1000e_setup_rx_resources ( adapter ); if ( err ) { DBG ( "Error setting up RX resources!\n" ); goto err_setup_rx; } e1000e_configure_tx ( adapter ); e1000e_configure_rx ( adapter ); DBG ( "E1000_RXDCTL(0): %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) ); return 0; err_setup_rx: DBG ( "err_setup_rx\n" ); e1000e_free_tx_resources ( adapter ); err_setup_tx: DBG ( "err_setup_tx\n" ); e1000e_reset ( adapter ); return err; }
/* * e1000g_rx_setup - setup rx data structures * * This routine initializes all of the receive related * structures. This includes the receive descriptors, the * actual receive buffers, and the rx_sw_packet software * structures. */ void e1000g_rx_setup(struct e1000g *Adapter) { struct e1000_hw *hw; p_rx_sw_packet_t packet; struct e1000_rx_desc *descriptor; uint32_t buf_low; uint32_t buf_high; uint32_t reg_val; uint32_t rctl; uint32_t rxdctl; uint32_t ert; uint16_t phy_data; int i; int size; e1000g_rx_data_t *rx_data; hw = &Adapter->shared; rx_data = Adapter->rx_ring->rx_data; /* * zero out all of the receive buffer descriptor memory * assures any previous data or status is erased */ bzero(rx_data->rbd_area, sizeof (struct e1000_rx_desc) * Adapter->rx_desc_num); if (!Adapter->rx_buffer_setup) { /* Init the list of "Receive Buffer" */ QUEUE_INIT_LIST(&rx_data->recv_list); /* Init the list of "Free Receive Buffer" */ QUEUE_INIT_LIST(&rx_data->free_list); /* Init the list of "Free Receive Buffer" */ QUEUE_INIT_LIST(&rx_data->recycle_list); /* * Setup Receive list and the Free list. Note that * the both were allocated in one packet area. */ packet = rx_data->packet_area; descriptor = rx_data->rbd_first; for (i = 0; i < Adapter->rx_desc_num; i++, packet = packet->next, descriptor++) { ASSERT(packet != NULL); ASSERT(descriptor != NULL); descriptor->buffer_addr = packet->rx_buf->dma_address; /* Add this rx_sw_packet to the receive list */ QUEUE_PUSH_TAIL(&rx_data->recv_list, &packet->Link); } for (i = 0; i < Adapter->rx_freelist_num; i++, packet = packet->next) { ASSERT(packet != NULL); /* Add this rx_sw_packet to the free list */ QUEUE_PUSH_TAIL(&rx_data->free_list, &packet->Link); } rx_data->avail_freepkt = Adapter->rx_freelist_num; rx_data->recycle_freepkt = 0; Adapter->rx_buffer_setup = B_TRUE; } else { /* Setup the initial pointer to the first rx descriptor */ packet = (p_rx_sw_packet_t) QUEUE_GET_HEAD(&rx_data->recv_list); descriptor = rx_data->rbd_first; for (i = 0; i < Adapter->rx_desc_num; i++) { ASSERT(packet != NULL); ASSERT(descriptor != NULL); descriptor->buffer_addr = packet->rx_buf->dma_address; /* Get next rx_sw_packet */ packet = (p_rx_sw_packet_t) QUEUE_GET_NEXT(&rx_data->recv_list, &packet->Link); descriptor++; } } E1000_WRITE_REG(&Adapter->shared, E1000_RDTR, Adapter->rx_intr_delay); E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, "E1000_RDTR: 0x%x\n", Adapter->rx_intr_delay); if (hw->mac.type >= e1000_82540) { E1000_WRITE_REG(&Adapter->shared, E1000_RADV, Adapter->rx_intr_abs_delay); E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, "E1000_RADV: 0x%x\n", Adapter->rx_intr_abs_delay); } /* * Setup our descriptor pointers */ rx_data->rbd_next = rx_data->rbd_first; size = Adapter->rx_desc_num * sizeof (struct e1000_rx_desc); E1000_WRITE_REG(hw, E1000_RDLEN(0), size); size = E1000_READ_REG(hw, E1000_RDLEN(0)); /* To get lower order bits */ buf_low = (uint32_t)rx_data->rbd_dma_addr; /* To get the higher order bits */ buf_high = (uint32_t)(rx_data->rbd_dma_addr >> 32); E1000_WRITE_REG(hw, E1000_RDBAH(0), buf_high); E1000_WRITE_REG(hw, E1000_RDBAL(0), buf_low); /* * Setup our HW Rx Head & Tail descriptor pointers */ E1000_WRITE_REG(hw, E1000_RDT(0), (uint32_t)(rx_data->rbd_last - rx_data->rbd_first)); E1000_WRITE_REG(hw, E1000_RDH(0), 0); /* * Setup the Receive Control Register (RCTL), and ENABLE the * receiver. The initial configuration is to: Enable the receiver, * accept broadcasts, discard bad packets (and long packets), * disable VLAN filter checking, set the receive descriptor * minimum threshold size to 1/2, and the receive buffer size to * 2k. */ rctl = E1000_RCTL_EN | /* Enable Receive Unit */ E1000_RCTL_BAM | /* Accept Broadcast Packets */ E1000_RCTL_LPE | /* Large Packet Enable bit */ (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | E1000_RCTL_RDMTS_HALF | E1000_RCTL_LBM_NO; /* Loopback Mode = none */ if (Adapter->strip_crc) rctl |= E1000_RCTL_SECRC; /* Strip Ethernet CRC */ if (Adapter->mem_workaround_82546 && ((hw->mac.type == e1000_82545) || (hw->mac.type == e1000_82546) || (hw->mac.type == e1000_82546_rev_3))) { rctl |= E1000_RCTL_SZ_2048; } else { if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_2K) && (Adapter->max_frame_size <= FRAME_SIZE_UPTO_4K)) rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_4K) && (Adapter->max_frame_size <= FRAME_SIZE_UPTO_8K)) rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_8K) && (Adapter->max_frame_size <= FRAME_SIZE_UPTO_16K)) rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX; else rctl |= E1000_RCTL_SZ_2048; } if (e1000_tbi_sbp_enabled_82543(hw)) rctl |= E1000_RCTL_SBP; /* * Enable Early Receive Threshold (ERT) on supported devices. * Only takes effect when packet size is equal or larger than the * specified value (in 8 byte units), e.g. using jumbo frames. */ if ((hw->mac.type == e1000_82573) || (hw->mac.type == e1000_82574) || (hw->mac.type == e1000_ich9lan) || (hw->mac.type == e1000_ich10lan)) { ert = E1000_ERT_2048; /* * Special modification when ERT and * jumbo frames are enabled */ if (Adapter->default_mtu > ETHERMTU) { rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 0x3); ert |= (1 << 13); } E1000_WRITE_REG(hw, E1000_ERT, ert); } /* Workaround errata on 82577/8 adapters with large frames */ if ((hw->mac.type == e1000_pchlan) && (Adapter->default_mtu > ETHERMTU)) { (void) e1000_read_phy_reg(hw, PHY_REG(770, 26), &phy_data); phy_data &= 0xfff8; phy_data |= (1 << 2); (void) e1000_write_phy_reg(hw, PHY_REG(770, 26), phy_data); if (hw->phy.type == e1000_phy_82577) { (void) e1000_read_phy_reg(hw, 22, &phy_data); phy_data &= 0x0fff; phy_data |= (1 << 14); (void) e1000_write_phy_reg(hw, 0x10, 0x2823); (void) e1000_write_phy_reg(hw, 0x11, 0x0003); (void) e1000_write_phy_reg(hw, 22, phy_data); } } reg_val = E1000_RXCSUM_TUOFL | /* TCP/UDP checksum offload Enable */ E1000_RXCSUM_IPOFL; /* IP checksum offload Enable */ E1000_WRITE_REG(hw, E1000_RXCSUM, reg_val); /* * Workaround: Set bit 16 (IPv6_ExDIS) to disable the * processing of received IPV6 extension headers */ if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { reg_val = E1000_READ_REG(hw, E1000_RFCTL); reg_val |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); E1000_WRITE_REG(hw, E1000_RFCTL, reg_val); } /* Write to enable the receive unit */ E1000_WRITE_REG(hw, E1000_RCTL, rctl); }
/** * igb_rx_fifo_flush_82575 - Clean rx fifo after RX enable * @hw: pointer to the HW structure * * After rx enable if managability is enabled then there is likely some * bad data at the start of the fifo and possibly in the DMA fifo. This * function clears the fifos and flushes any packets that came in as rx was * being enabled. **/ void igb_rx_fifo_flush_82575(struct e1000_hw *hw) { u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; if (hw->mac.type != e1000_82575 || !(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; /* Disable all RX queues */ for (i = 0; i < 4; i++) { rxdctl[i] = rd32(E1000_RXDCTL(i)); wr32(E1000_RXDCTL(i), rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); } /* Poll all queues to verify they have shut down */ for (ms_wait = 0; ms_wait < 10; ms_wait++) { msleep(1); rx_enabled = 0; for (i = 0; i < 4; i++) rx_enabled |= rd32(E1000_RXDCTL(i)); if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) break; } if (ms_wait == 10) hw_dbg("Queue disable timed out after 10ms\n"); /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all * incoming packets are rejected. Set enable and wait 2ms so that * any packet that was coming in as RCTL.EN was set is flushed */ rfctl = rd32(E1000_RFCTL); wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = rd32(E1000_RLPML); wr32(E1000_RLPML, 0); rctl = rd32(E1000_RCTL); temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); temp_rctl |= E1000_RCTL_LPE; wr32(E1000_RCTL, temp_rctl); wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN); wrfl(); msleep(2); /* Enable RX queues that were previously enabled and restore our * previous state */ for (i = 0; i < 4; i++) wr32(E1000_RXDCTL(i), rxdctl[i]); wr32(E1000_RCTL, rctl); wrfl(); wr32(E1000_RLPML, rlpml); wr32(E1000_RFCTL, rfctl); /* Flush receive errors generated by workaround */ rd32(E1000_ROC); rd32(E1000_RNBC); rd32(E1000_MPC); }
/* * mac_dump - dump important mac registers */ void mac_dump(void *instance) { struct e1000g *Adapter = (struct e1000g *)instance; struct e1000_hw *hw = &Adapter->shared; int i; /* {name, offset} for each mac register */ Regi_t macreg[NUM_REGS] = { {"CTRL", E1000_CTRL}, {"STATUS", E1000_STATUS}, {"EECD", E1000_EECD}, {"EERD", E1000_EERD}, {"CTRL_EXT", E1000_CTRL_EXT}, {"FLA", E1000_FLA}, {"MDIC", E1000_MDIC}, {"SCTL", E1000_SCTL}, {"FCAL", E1000_FCAL}, {"FCAH", E1000_FCAH}, {"FCT", E1000_FCT}, {"VET", E1000_VET}, {"ICR", E1000_ICR}, {"ITR", E1000_ITR}, {"ICS", E1000_ICS}, {"IMS", E1000_IMS}, {"IMC", E1000_IMC}, {"IAM", E1000_IAM}, {"RCTL", E1000_RCTL}, {"FCTTV", E1000_FCTTV}, {"TXCW", E1000_TXCW}, {"RXCW", E1000_RXCW}, {"TCTL", E1000_TCTL}, {"TIPG", E1000_TIPG}, {"AIT", E1000_AIT}, {"LEDCTL", E1000_LEDCTL}, {"PBA", E1000_PBA}, {"PBS", E1000_PBS}, {"EEMNGCTL", E1000_EEMNGCTL}, {"ERT", E1000_ERT}, {"FCRTL", E1000_FCRTL}, {"FCRTH", E1000_FCRTH}, {"PSRCTL", E1000_PSRCTL}, {"RDBAL(0)", E1000_RDBAL(0)}, {"RDBAH(0)", E1000_RDBAH(0)}, {"RDLEN(0)", E1000_RDLEN(0)}, {"RDH(0)", E1000_RDH(0)}, {"RDT(0)", E1000_RDT(0)}, {"RDTR", E1000_RDTR}, {"RXDCTL(0)", E1000_RXDCTL(0)}, {"RADV", E1000_RADV}, {"RDBAL(1)", E1000_RDBAL(1)}, {"RDBAH(1)", E1000_RDBAH(1)}, {"RDLEN(1)", E1000_RDLEN(1)}, {"RDH(1)", E1000_RDH(1)}, {"RDT(1)", E1000_RDT(1)}, {"RXDCTL(1)", E1000_RXDCTL(1)}, {"RSRPD", E1000_RSRPD}, {"RAID", E1000_RAID}, {"CPUVEC", E1000_CPUVEC}, {"TDFH", E1000_TDFH}, {"TDFT", E1000_TDFT}, {"TDFHS", E1000_TDFHS}, {"TDFTS", E1000_TDFTS}, {"TDFPC", E1000_TDFPC}, {"TDBAL(0)", E1000_TDBAL(0)}, {"TDBAH(0)", E1000_TDBAH(0)}, {"TDLEN(0)", E1000_TDLEN(0)}, {"TDH(0)", E1000_TDH(0)}, {"TDT(0)", E1000_TDT(0)}, {"TIDV", E1000_TIDV}, {"TXDCTL(0)", E1000_TXDCTL(0)}, {"TADV", E1000_TADV}, {"TARC(0)", E1000_TARC(0)}, {"TDBAL(1)", E1000_TDBAL(1)}, {"TDBAH(1)", E1000_TDBAH(1)}, {"TDLEN(1)", E1000_TDLEN(1)}, {"TDH(1)", E1000_TDH(1)}, {"TDT(1)", E1000_TDT(1)}, {"TXDCTL(1)", E1000_TXDCTL(1)}, {"TARC(1)", E1000_TARC(1)}, {"ALGNERRC", E1000_ALGNERRC}, {"RXERRC", E1000_RXERRC}, {"MPC", E1000_MPC}, {"SCC", E1000_SCC}, {"ECOL", E1000_ECOL}, {"MCC", E1000_MCC}, {"LATECOL", E1000_LATECOL}, {"COLC", E1000_COLC}, {"DC", E1000_DC}, {"TNCRS", E1000_TNCRS}, {"SEC", E1000_SEC}, {"CEXTERR", E1000_CEXTERR}, {"RLEC", E1000_RLEC}, {"XONRXC", E1000_XONRXC}, {"XONTXC", E1000_XONTXC}, {"XOFFRXC", E1000_XOFFRXC}, {"XOFFTXC", E1000_XOFFTXC}, {"FCRUC", E1000_FCRUC}, {"PRC64", E1000_PRC64}, {"PRC127", E1000_PRC127}, {"PRC255", E1000_PRC255}, {"PRC511", E1000_PRC511}, {"PRC1023", E1000_PRC1023}, {"PRC1522", E1000_PRC1522}, {"GPRC", E1000_GPRC}, {"BPRC", E1000_BPRC}, {"MPRC", E1000_MPRC}, {"GPTC", E1000_GPTC}, {"GORCL", E1000_GORCL}, {"GORCH", E1000_GORCH}, {"GOTCL", E1000_GOTCL}, {"GOTCH", E1000_GOTCH}, {"RNBC", E1000_RNBC}, {"RUC", E1000_RUC}, {"RFC", E1000_RFC}, {"ROC", E1000_ROC}, {"RJC", E1000_RJC}, {"MGTPRC", E1000_MGTPRC}, {"MGTPDC", E1000_MGTPDC}, {"MGTPTC", E1000_MGTPTC}, {"TORL", E1000_TORL}, {"TORH", E1000_TORH}, {"TOTL", E1000_TOTL}, {"TOTH", E1000_TOTH}, {"TPR", E1000_TPR}, {"TPT", E1000_TPT}, {"PTC64", E1000_PTC64}, {"PTC127", E1000_PTC127}, {"PTC255", E1000_PTC255}, {"PTC511", E1000_PTC511}, {"PTC1023", E1000_PTC1023}, {"PTC1522", E1000_PTC1522}, {"MPTC", E1000_MPTC}, {"BPTC", E1000_BPTC}, {"TSCTC", E1000_TSCTC}, {"TSCTFC", E1000_TSCTFC}, {"IAC", E1000_IAC}, {"ICRXPTC", E1000_ICRXPTC}, {"ICRXATC", E1000_ICRXATC}, {"ICTXPTC", E1000_ICTXPTC}, {"ICTXATC", E1000_ICTXATC}, {"ICTXQEC", E1000_ICTXQEC}, {"ICTXQMTC", E1000_ICTXQMTC}, {"ICRXDMTC", E1000_ICRXDMTC}, {"ICRXOC", E1000_ICRXOC}, {"RXCSUM", E1000_RXCSUM}, {"RFCTL", E1000_RFCTL}, {"WUC", E1000_WUC}, {"WUFC", E1000_WUFC}, {"WUS", E1000_WUS}, {"MRQC", E1000_MRQC}, {"MANC", E1000_MANC}, {"IPAV", E1000_IPAV}, {"MANC2H", E1000_MANC2H}, {"RSSIM", E1000_RSSIM}, {"RSSIR", E1000_RSSIR}, {"WUPL", E1000_WUPL}, {"GCR", E1000_GCR}, {"GSCL_1", E1000_GSCL_1}, {"GSCL_2", E1000_GSCL_2}, {"GSCL_3", E1000_GSCL_3}, {"GSCL_4", E1000_GSCL_4}, {"FACTPS", E1000_FACTPS}, {"FWSM", E1000_FWSM}, }; e1000g_log(Adapter, CE_CONT, "Begin MAC dump\n"); for (i = 0; i < NUM_REGS; i++) { e1000g_log(Adapter, CE_CONT, "macreg %10s offset: 0x%x value: 0x%x\n", macreg[i].name, macreg[i].offset, e1000_read_reg(hw, macreg[i].offset)); } }