static int e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) { *data = 0; if (adapter->hw.media_type == e1000_media_type_internal_serdes) { int i = 0; adapter->hw.serdes_link_down = TRUE; /* On some blade server designs, link establishment * could take as long as 2-3 minutes */ do { e1000_check_for_link(&adapter->hw); if (adapter->hw.serdes_link_down == FALSE) return *data; msec_delay(20); } while (i++ < 3750); *data = 1; } else { e1000_check_for_link(&adapter->hw); if(adapter->hw.autoneg) /* if auto_neg is set wait for it */ msec_delay(4000); if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { *data = 1; } } return *data; }
/** * e1000_reset_hw_82540 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82540(struct e1000_hw *hw) { u32 ctrl, manc; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_reset_hw_82540"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); /* * Delay to allow any outstanding PCI transactions to complete * before resetting the device. */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n"); switch (hw->mac.type) { case e1000_82545_rev_3: case e1000_82546_rev_3: E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST); break; default: /* * These controllers can't ack the 64-bit write when * issuing the reset, so we use IO-mapping as a * workaround to issue the reset. */ E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); break; } /* Wait for EEPROM reload */ msec_delay(5); /* Disable HW ARPs on ASF enabled adapters */ manc = E1000_READ_REG(hw, E1000_MANC); manc &= ~E1000_MANC_ARP_EN; E1000_WRITE_REG(hw, E1000_MANC, manc); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); return ret_val; }
/** * e1000_reset_hw_82543 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_reset_hw_82543"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); e1000_set_tbi_sbp_82543(hw, FALSE); /* * Delay to allow any outstanding PCI transactions to complete before * resetting the device */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n"); if (hw->mac.type == e1000_82543) { E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); } else { /* * The 82544 can't ACK the 64-bit write when issuing the * reset, so use IO-mapping as a workaround. */ E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); } /* * After MAC reset, force reload of NVM to restore power-on * settings to device. */ hw->nvm.ops.reload(hw); msec_delay(2); /* Masking off and clearing any pending interrupts */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); return ret_val; }
static int e1000_run_loopback_test(struct e1000_adapter *adapter) { struct e1000_desc_ring *txdr = &adapter->test_tx_ring; struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; struct pci_dev *pdev = adapter->pdev; int i; E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); for(i = 0; i < 64; i++) { e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma, txdr->buffer_info[i].length, PCI_DMA_TODEVICE); } E1000_WRITE_REG(&adapter->hw, TDT, i); msec_delay(200); i = 0; do { pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[i].dma, rxdr->buffer_info[i].length, PCI_DMA_FROMDEVICE); if (!e1000_check_lbtest_frame(rxdr->buffer_info[i++].skb, 1024)) return 0; } while (i < 64); return 13; }
/** * ixgbe_blink_led_start_82598 - Blink LED based on index. * @hw: pointer to hardware structure * @index: led number to blink **/ int32_t ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, uint32_t index) { ixgbe_link_speed speed = 0; int link_up = 0; uint32_t autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); uint32_t led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); /* * Link must be up to auto-blink the LEDs on the 82598EB MAC; * force it if link is down. */ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); if (!link_up) { autoc_reg |= IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); msec_delay(10); } led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; }
IOReturn AtherosL1Ethernet::disable(IONetworkInterface *netif) { DbgPrint("disable()\n"); at_adapter *adapter=&adapter_; setLinkStatus(kIONetworkLinkValid, 0); transmitQueue_->flush(); transmitQueue_->stop(); transmitQueue_->setCapacity(0); /* reset MAC to disable all RX/TX */ at_reset_hw(&adapter->hw); adapter->cmb.cmb->int_stats = 0; msec_delay(1); at_irq_disable(adapter); adapter->link_speed = SPEED_0; adapter->link_duplex = -1; at_clean_tx_ring(adapter); at_clean_rx_ring(adapter); if (adapter->pdev && adapter->pdev->isOpen () ) adapter->pdev->close(this); return kIOReturnSuccess; }
/** * e1000_phy_hw_reset_82543 - PHY hardware reset * @hw: pointer to the HW structure * * Sets the PHY_RESET_DIR bit in the extended device control register * to put the PHY into a reset and waits for completion. Once the reset * has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out * of reset. **/ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) { u32 ctrl_ext; s32 ret_val; DEBUGFUNC("e1000_phy_hw_reset_82543"); /* * Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset... */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); msec_delay(10); /* ...then take it out of reset. */ ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); usec_delay(150); if (!(hw->phy.ops.get_cfg_done)) return E1000_SUCCESS; ret_val = hw->phy.ops.get_cfg_done(hw); return ret_val; }
/** * e1000_pll_workaround_i210 * @hw: pointer to the HW structure * * Works around an errata in the PLL circuit where it occasionally * provides the wrong clock frequency after power up. **/ static s32 e1000_pll_workaround_i210(struct e1000_hw *hw) { s32 ret_val; u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val; u16 nvm_word, phy_word, pci_word, tmp_nvm; int i; /* Get and set needed register values */ wuc = E1000_READ_REG(hw, E1000_WUC); mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO; E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val); /* Get data from NVM, or set default */ ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD, &nvm_word); if (ret_val != E1000_SUCCESS) nvm_word = E1000_INVM_DEFAULT_AL; tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL; for (i = 0; i < E1000_MAX_PLL_TRIES; i++) { /* check current state directly from internal PHY */ e1000_read_phy_reg_gs40g(hw, (E1000_PHY_PLL_FREQ_PAGE | E1000_PHY_PLL_FREQ_REG), &phy_word); if ((phy_word & E1000_PHY_PLL_UNCONF) != E1000_PHY_PLL_UNCONF) { ret_val = E1000_SUCCESS; break; } else { ret_val = -E1000_ERR_PHY; } /* directly reset the internal PHY */ ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl|E1000_CTRL_PHY_RST); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_REG(hw, E1000_WUC, 0); reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16); E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val); e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); pci_word |= E1000_PCI_PMCSR_D3; e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); msec_delay(1); pci_word &= ~E1000_PCI_PMCSR_D3; e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16); E1000_WRITE_REG(hw, E1000_EEARBC_I210, reg_val); /* restore WUC register */ E1000_WRITE_REG(hw, E1000_WUC, wuc); } /* restore MDICNFG setting */ E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); return ret_val; }
STATIC void ifcvf_reset(struct ifcvf_hw *hw) { ifcvf_set_status(hw, 0); /* flush status write */ while (ifcvf_get_status(hw)) msec_delay(1); }
/** * e1000_reset_hw_82542 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82542(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; s32 ret_val = E1000_SUCCESS; u32 ctrl; DEBUGFUNC("e1000_reset_hw_82542"); if (hw->revision_id == E1000_REVISION_2) { DEBUGOUT("Disabling MWI on 82542 rev 2\n"); e1000_pci_clear_mwi(hw); } DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); /* * Delay to allow any outstanding PCI transactions to complete before * resetting the device */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); hw->nvm.ops.reload(hw); msec_delay(2); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); if (hw->revision_id == E1000_REVISION_2) { if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } return ret_val; }
/** * e1000_setup_fiber_link_82543 - Setup link for fiber * @hw: pointer to the HW structure * * Configures collision distance and flow control for fiber links. Upon * successful setup, poll for link. **/ static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_setup_fiber_link_82543"); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Take the link out of reset */ ctrl &= ~E1000_CTRL_LRST; e1000_config_collision_dist_generic(hw); ret_val = e1000_commit_fc_settings_generic(hw); if (ret_val) goto out; DEBUGOUT("Auto-negotiation enabled\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); msec_delay(1); /* * For these adapters, the SW definable pin 1 is cleared when the * optics detect a signal. If we have a signal, then poll for a * "Link-Up" indication. */ if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { ret_val = e1000_poll_fiber_serdes_link_generic(hw); } else { DEBUGOUT("No signal detected\n"); } out: return ret_val; }
/** * ixgbe_setup_mac_link_multispeed_fixed_fiber - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ static s32 ixgbe_setup_mac_link_multispeed_fixed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = IXGBE_SUCCESS; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; u32 speedcnt = 0; u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); u32 i = 0; bool link_up = false; bool negotiation; DEBUGFUNC(""); /* Mask off requested but non-supported speeds */ status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation); if (status != IXGBE_SUCCESS) return status; speed &= link_speed; /* * Try each speed one by one, highest priority first. We do this in * software because 10gb fiber doesn't support speed autonegotiation. */ if (speed & IXGBE_LINK_SPEED_10GB_FULL) { speedcnt++; highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) goto out; /* Set the module link speed */ ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_10GB_FULL); /* Set the module link speed */ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); /* Allow module to change analog characteristics (1G->10G) */ msec_delay(40); status = ixgbe_setup_mac_link_82599(hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) return status; /* Flap the tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* * Wait for the controller to acquire link. Per IEEE 802.3ap, * Section 73.10.2, we may have to wait up to 500ms if KR is * attempted. 82599 uses the same timing for 10g SFI. */ for (i = 0; i < 5; i++) { /* Wait for the link partner to also set speed */ msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if (link_up) goto out; } } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { speedcnt++; if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) goto out; /* Set the module link speed */ ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_1GB_FULL); /* Allow module to change analog characteristics (10G->1G) */ msec_delay(40); status = ixgbe_setup_mac_link_82599(hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) return status; /* Flap the tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* Wait for the link partner to also set speed */ msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if (link_up) goto out; } /* * We didn't get link. Configure back to the highest speed we tried, * (if there was more than one). We call ourselves back with just the * single highest speed that the user requested. */ if (speedcnt > 1) status = ixgbe_setup_mac_link_multispeed_fixed_fiber(hw, highest_link_speed, autoneg, autoneg_wait_to_complete); out: /* Set autoneg_advertised value based on input link speed */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; return status; }
/** * ixgbe_reset_hw_X540 - Perform hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks * and clears all interrupts, and perform a reset. **/ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) { s32 status; u32 ctrl, i; DEBUGFUNC("ixgbe_reset_hw_X540"); /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != IXGBE_SUCCESS) goto reset_hw_out; /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); mac_reset_top: ctrl = IXGBE_CTRL_RST; ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST_MASK)) break; } if (ctrl & IXGBE_CTRL_RST_MASK) { status = IXGBE_ERR_RESET_FAILED; ERROR_REPORT1(IXGBE_ERROR_POLLING, "Reset polling failed to complete.\n"); } msec_delay(100); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to allow time * for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } /* Set the Rx packet buffer size. */ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT); /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); /* Store the permanent SAN mac address */ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); /* Save the SAN MAC RAR index */ hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; /* Reserve the last RAR for the SAN MAC address */ hw->mac.num_rar_entries--; } /* Store the alternative WWNN/WWPN prefix */ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, &hw->mac.wwpn_prefix); reset_hw_out: return status; }
/** * ixgbe_setup_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ int32_t ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) { ixgbe_link_speed speed; int link_up; uint32_t autoc_reg; uint32_t links_reg; uint32_t i; int32_t status = IXGBE_SUCCESS; autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.link_settings_loaded) { autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; autoc_reg |= hw->mac.link_attach_type; autoc_reg |= hw->mac.link_mode_select; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); IXGBE_WRITE_FLUSH(hw); msec_delay(50); } /* Restart link */ autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ if (hw->phy.autoneg_wait_to_complete) { if (hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN || hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { links_reg = 0; /* Just in case Autoneg time = 0 */ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msec_delay(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; DEBUGOUT("Autonegotiation did not complete.\n"); } } } /* * We want to save off the original Flow Control configuration just in * case we get disconnected and then reconnected into a different hub * or switch with different Flow Control capabilities. */ hw->fc.original_type = hw->fc.type; /* * Set up the SerDes link if in 1Gb mode, otherwise just set up * 10Gb flow control. */ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); if (speed == IXGBE_LINK_SPEED_1GB_FULL) status = ixgbe_setup_fiber_serdes_link_82598(hw); else ixgbe_setup_fc_82598(hw, 0); /* Add delay to filter out noises during initial link setup */ msec_delay(50); return status; }
/** * ixgbe_check_mac_link_82598 - Get link/speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: TRUE is link is up, FALSE otherwise * @link_up_wait_to_complete: int used to wait for link up or not * * Reads the links register to determine if link is up and the current speed **/ int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, int *link_up, int link_up_wait_to_complete) { uint32_t links_reg; uint32_t i; uint16_t link_reg, adapt_comp_reg; if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.read_reg(hw, 1, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 1, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if ((link_reg & (1 << 2)) && ((adapt_comp_reg & 1) == 0)) { *link_up = TRUE; break; } else { *link_up = FALSE; } msec_delay(100); hw->phy.ops.read_reg(hw, 1, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); } } else { if ((link_reg & (1 << 2)) && ((adapt_comp_reg & 1) == 0)) *link_up = TRUE; else *link_up = FALSE; } if (*link_up == FALSE) goto out; } links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = TRUE; break; } else { *link_up = FALSE; } msec_delay(100); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); } } else { if (links_reg & IXGBE_LINKS_UP) *link_up = TRUE; else *link_up = FALSE; } if (links_reg & IXGBE_LINKS_SPEED) *speed = IXGBE_LINK_SPEED_10GB_FULL; else *speed = IXGBE_LINK_SPEED_1GB_FULL; out: return IXGBE_SUCCESS; }
/** * e1000_init_phy_params_82543 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ static s32 e1000_init_phy_params_82543(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_phy_params_82543"); if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; } else { phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper; } phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 10000; phy->type = e1000_phy_m88; /* Function Pointers */ phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543; phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.get_cfg_done = e1000_get_cfg_done_generic; phy->ops.read_reg = (hw->mac.type == e1000_82543) ? e1000_read_phy_reg_82543 : e1000_read_phy_reg_m88; phy->ops.reset = (hw->mac.type == e1000_82543) ? e1000_phy_hw_reset_82543 : e1000_phy_hw_reset_generic; phy->ops.write_reg = (hw->mac.type == e1000_82543) ? e1000_write_phy_reg_82543 : e1000_write_phy_reg_m88; phy->ops.get_info = e1000_get_phy_info_m88; /* * The external PHY of the 82543 can be in a funky state. * Resetting helps us read the PHY registers for acquiring * the PHY ID. */ if (!e1000_init_phy_disabled_82543(hw)) { ret_val = phy->ops.reset(hw); if (ret_val) { DEBUGOUT("Resetting PHY during init failed.\n"); goto out; } msec_delay(20); } ret_val = e1000_get_phy_id(hw); if (ret_val) goto out; /* Verify phy id */ switch (hw->mac.type) { case e1000_82543: if (phy->id != M88E1000_E_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; } break; case e1000_82544: if (phy->id != M88E1000_I_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; } break; default: ret_val = -E1000_ERR_PHY; goto out; break; } out: return ret_val; }
/** * e1000_host_interface_command - Writes buffer to host interface * @hw: pointer to the HW structure * @buffer: contains a command to write * @length: the byte length of the buffer, must be multiple of 4 bytes * * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS * else returns E1000_ERR_HOST_INTERFACE_COMMAND. **/ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length) { u32 hicr, i; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_host_interface_command"); if (!(hw->mac.arc_subsystem_valid)) { DEBUGOUT("Hardware doesn't support host interface command.\n"); goto out; } if (!hw->mac.asf_firmware_present) { DEBUGOUT("Firmware is not present.\n"); goto out; } if (length == 0 || length & 0x3 || length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) { DEBUGOUT("Buffer length failure.\n"); ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; goto out; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if ((hicr & E1000_HICR_EN) == 0) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; goto out; } /* Calculate length in DWORDs */ length >>= 2; /* * The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < length; i++) E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, *((u32 *)buffer + i)); /* Setting this bit tells the ARC that a new command is pending. */ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay(1); } /* Check command successful completion. */ if (i == E1000_HI_COMMAND_TIMEOUT || (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) { DEBUGOUT("Command has failed with no status valid.\n"); ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; goto out; } for (i = 0; i < length; i++) *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i); out: return ret_val; }
/** * ixgbe_configure_fiber_serdes_fc_82598 - Configure fiber flow control * @hw: pointer to hardware structure * * Reads PCS registers and sets flow control settings, based on * link-partner's abilities. **/ int32_t ixgbe_configure_fiber_serdes_fc_82598(struct ixgbe_hw *hw) { int32_t ret_val = IXGBE_SUCCESS; uint32_t pcs_anadv_reg, pcs_lpab_reg, pcs_lstat_reg, i; DEBUGFUNC("ixgbe_configure_fiber_serdes_fc_82598"); /* Check that autonegotiation has completed */ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { msec_delay(10); pcs_lstat_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); if (pcs_lstat_reg & IXGBE_PCS1GLSTA_LINK_OK) { if (pcs_lstat_reg & IXGBE_PCS1GLSTA_AN_COMPLETE) { if (!(pcs_lstat_reg & (IXGBE_PCS1GLSTA_AN_TIMED_OUT))) hw->mac.autoneg_failed = 0; else hw->mac.autoneg_failed = 1; break; } else { hw->mac.autoneg_failed = 1; break; } } } if (hw->mac.autoneg_failed) { /* * AutoNeg failed to achieve a link, so we will turn * flow control off. */ hw->fc.type = ixgbe_fc_none; DEBUGOUT("Flow Control = NONE.\n"); ret_val = ixgbe_setup_fc_82598(hw, 0); goto out; } /* * Read the AN advertisement and LP ability registers and resolve * local flow control settings accordingly */ pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { /* * Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise RX * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.original_type == ixgbe_fc_full) { hw->fc.type = ixgbe_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc.type = ixgbe_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { hw->fc.type = ixgbe_fc_tx_pause; DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { hw->fc.type = ixgbe_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } else { hw->fc.type = ixgbe_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } ret_val = ixgbe_setup_fc_82598(hw, 0); if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); goto out; } out: return ret_val; }
/** * e1000_init_hw_82542 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ static s32 e1000_init_hw_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542; s32 ret_val = E1000_SUCCESS; u32 ctrl; u16 i; DEBUGFUNC("e1000_init_hw_82542"); /* Disabling VLAN filtering */ E1000_WRITE_REG(hw, E1000_VET, 0); mac->ops.clear_vfta(hw); /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ if (hw->revision_id == E1000_REVISION_2) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); e1000_pci_clear_mwi(hw); E1000_WRITE_REG(hw, E1000_RCTL, E1000_RCTL_RST); E1000_WRITE_FLUSH(hw); msec_delay(5); } /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ if (hw->revision_id == E1000_REVISION_2) { E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_FLUSH(hw); msec_delay(1); if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* * Set the PCI priority bit correctly in the CTRL register. This * determines if the adapter gives priority to receives, or if it * gives equal priority to transmits and receives. */ if (dev_spec->dma_fairness) { ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR); } /* Setup link and flow control */ ret_val = e1000_setup_link_82542(hw); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82542(hw); return ret_val; }
/** * ixgbe_reset_hw_rev_0_82598 - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performing a PHY reset, and performing a link (MAC) * reset. **/ int32_t ixgbe_reset_hw_rev_0_82598(struct ixgbe_hw *hw) { int32_t status = IXGBE_SUCCESS; uint32_t ctrl; uint32_t gheccr; uint32_t autoc; uint32_t i; uint32_t resets; /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); /* Reset PHY */ hw->phy.ops.reset(hw); for (resets = 0; resets < 10; resets++) { /* * Prevent the PCI-E bus from from hanging by disabling PCI-E * master access and verify no pending requests before reset */ if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; DEBUGOUT("PCI-E Master disable polling has failed.\n"); } /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is * using it. */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); IXGBE_WRITE_FLUSH(hw); /* * Poll for reset bit to self-clear indicating reset is * complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST)) break; } if (ctrl & IXGBE_CTRL_RST) { status = IXGBE_ERR_RESET_FAILED; DEBUGOUT("Reset polling failed to complete.\n"); } } msec_delay(50); gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* * AUTOC register which stores link settings gets cleared * and reloaded from EEPROM after reset. We need to restore * our stored value from init in case SW changed the attach * type or speed. If this is the first time and link settings * have not been stored, store default settings from AUTOC. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.link_settings_loaded) { autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE); autoc &= ~(IXGBE_AUTOC_LMS_MASK); autoc |= hw->mac.link_attach_type; autoc |= hw->mac.link_mode_select; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } else { hw->mac.link_attach_type = (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK); hw->mac.link_settings_loaded = TRUE; } /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); return status; }
/** * ixgbe_reset_hw_82598 - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performing a PHY reset, and performing a link (MAC) * reset. **/ int32_t ixgbe_reset_hw_82598(struct ixgbe_hw *hw) { int32_t status = IXGBE_SUCCESS; uint32_t ctrl; uint32_t gheccr; uint32_t i; uint32_t autoc; uint8_t analog_val; /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); /* * Power up the Atlas Tx lanes if they are currently powered down. * Atlas Tx lanes are powered down for MAC loopback tests, but * they are not automatically restored on reset. */ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { /* Enable Tx Atlas so packets can be transmitted again */ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); analog_val &= ~ IXGBE_ATLAS_PDN_TX_10G_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); } /* Reset PHY */ if (hw->phy.reset_disable == FALSE) hw->phy.ops.reset(hw); /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; DEBUGOUT("PCI-E Master disable polling has failed.\n"); } /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is using it */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST)) break; } if (ctrl & IXGBE_CTRL_RST) { status = IXGBE_ERR_RESET_FAILED; DEBUGOUT("Reset polling failed to complete.\n"); } msec_delay(50); gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* * AUTOC register which stores link settings gets cleared * and reloaded from EEPROM after reset. We need to restore * our stored value from init in case SW changed the attach * type or speed. If this is the first time and link settings * have not been stored, store default settings from AUTOC. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.link_settings_loaded) { autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE); autoc &= ~(IXGBE_AUTOC_LMS_MASK); autoc |= hw->mac.link_attach_type; autoc |= hw->mac.link_mode_select; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } else { hw->mac.link_attach_type = (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK); hw->mac.link_settings_loaded = TRUE; } /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); return status; }
static int e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) { struct net_device *netdev = adapter->netdev; uint32_t mask, i=0, shared_int = TRUE; uint32_t irq = adapter->pdev->irq; *data = 0; /* Hook up test interrupt handler just for this test */ if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) { shared_int = FALSE; } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)){ *data = 1; return -1; } /* Disable all the interrupts */ E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); msec_delay(10); /* Test each interrupt */ for(; i < 10; i++) { /* Interrupt to test */ mask = 1 << i; if(!shared_int) { /* Disable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; E1000_WRITE_REG(&adapter->hw, IMC, mask); E1000_WRITE_REG(&adapter->hw, ICS, mask); msec_delay(10); if(adapter->test_icr & mask) { *data = 3; break; } } /* Enable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was not posted to the bus, the * test failed. */ adapter->test_icr = 0; E1000_WRITE_REG(&adapter->hw, IMS, mask); E1000_WRITE_REG(&adapter->hw, ICS, mask); msec_delay(10); if(!(adapter->test_icr & mask)) { *data = 4; break; } if(!shared_int) { /* Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; E1000_WRITE_REG(&adapter->hw, IMC, (~mask & 0x00007FFF)); E1000_WRITE_REG(&adapter->hw, ICS, (~mask & 0x00007FFF)); msec_delay(10); if(adapter->test_icr) { *data = 5; break; } } } /* Disable all the interrupts */ E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); msec_delay(10); /* Unhook test interrupt handler */ free_irq(irq, netdev); return *data; }
static int e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) { struct net_device *netdev = adapter->netdev; uint32_t icr, mask, i=0; *data = 0; /* Hook up test interrupt handler just for this test */ if(request_irq (netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) { *data = 1; return -1; } /* Disable all the interrupts */ E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); msec_delay(10); /* Interrupts are disabled, so read interrupt cause * register (icr) twice to verify that there are no interrupts * pending. icr is clear on read. */ icr = E1000_READ_REG(&adapter->hw, ICR); icr = E1000_READ_REG(&adapter->hw, ICR); if(icr != 0) { /* if icr is non-zero, there is no point * running other interrupt tests. */ *data = 2; i = 10; } /* Test each interrupt */ for(; i < 10; i++) { /* Interrupt to test */ mask = 1 << i; /* Disable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; E1000_WRITE_REG(&adapter->hw, IMC, mask); E1000_WRITE_REG(&adapter->hw, ICS, mask); msec_delay(10); if(adapter->test_icr & mask) { *data = 3; break; } /* Enable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was not posted to the bus, the * test failed. */ adapter->test_icr = 0; E1000_WRITE_REG(&adapter->hw, IMS, mask); E1000_WRITE_REG(&adapter->hw, ICS, mask); msec_delay(10); if(!(adapter->test_icr & mask)) { *data = 4; break; } /* Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; E1000_WRITE_REG(&adapter->hw, IMC, ~mask); E1000_WRITE_REG(&adapter->hw, ICS, ~mask); msec_delay(10); if(adapter->test_icr) { *data = 5; break; } } /* Disable all the interrupts */ E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); msec_delay(10); /* Unhook test interrupt handler */ free_irq(netdev->irq, netdev); return *data; }
static int e1000_run_loopback_test(struct e1000_adapter *adapter) { struct e1000_desc_ring *txdr = &adapter->test_tx_ring; struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; struct pci_dev *pdev = adapter->pdev; int i, j, k, l, lc, good_cnt, ret_val=0; unsigned long time; E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); /* Calculate the loop count based on the largest descriptor ring * The idea is to wrap the largest ring a number of times using 64 * send/receive pairs during each loop */ if(rxdr->count <= txdr->count) lc = ((txdr->count / 64) * 2) + 1; else lc = ((rxdr->count / 64) * 2) + 1; k = l = 0; for(j = 0; j <= lc; j++) { /* loop count loop */ for(i = 0; i < 64; i++) { /* send the packets */ e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); pci_dma_sync_single_for_device(pdev, txdr->buffer_info[k].dma, txdr->buffer_info[k].length, PCI_DMA_TODEVICE); if(unlikely(++k == txdr->count)) k = 0; } E1000_WRITE_REG(&adapter->hw, TDT, k); msec_delay(200); time = jiffies; /* set the start time for the receive */ good_cnt = 0; do { /* receive the sent packets */ pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[l].dma, rxdr->buffer_info[l].length, PCI_DMA_FROMDEVICE); ret_val = e1000_check_lbtest_frame( rxdr->buffer_info[l].skb, 1024); if(!ret_val) good_cnt++; if(unlikely(++l == rxdr->count)) l = 0; /* time + 20 msecs (200 msecs on 2.4) is more than * enough time to complete the receives, if it's * exceeded, break and error off */ } while (good_cnt < 64 && jiffies < (time + 20)); if(good_cnt != 64) { ret_val = 13; /* ret_val is the same as mis-compare */ break; } if(jiffies >= (time + 2)) { ret_val = 14; /* error code for time out error */ break; } } /* end loop count loop */ return ret_val; }