/** * ixgbe_poll_for_ack - Wait for message acknowledgement * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message acknowledgement **/ STATIC s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("ixgbe_poll_for_ack"); if (!countdown || !mbx->ops.check_for_ack) goto out; while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } if (countdown == 0) ERROR_REPORT2(IXGBE_ERROR_POLLING, "Polling for VF%d mailbox ack timedout", mbx_id); out: return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; }
/****************************************************************************** * Waits for the EEPROM to finish the current command. * * hw - Struct containing variables accessed by shared code * * The command is done when the EEPROM's data out pin goes high. * * Returns: * TRUE: EEPROM data pin is high before timeout. * FALSE: Time expired. *****************************************************************************/ static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw) { uint32_t eecd_reg; uint32_t i; /* Toggle the CS line. This in effect tells to EEPROM to actually * execute the command in question. */ ixgb_standby_eeprom(hw); /* Now read DO repeatedly until is high (equal to '1'). The EEEPROM * will signal that the command has been completed by raising the DO * signal. If DO does not go high in 10 milliseconds, then error out. */ for(i = 0; i < 200; i++) { eecd_reg = IXGB_READ_REG(hw, EECD); if(eecd_reg & IXGB_EECD_DO) return (TRUE); usec_delay(50); } ASSERT(0); return (FALSE); }
/** * 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; }
/** * e1000_get_hw_semaphore_i210 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) { u32 swsm; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_i210"); /* Get the SW semaphore */ while (i < timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); i++; } if (i == timeout) { /* In rare circumstances, the SW semaphore may already be held * unintentionally. Clear the semaphore once before giving up. */ if (hw->dev_spec._82575.clear_semaphore_once) { hw->dev_spec._82575.clear_semaphore_once = FALSE; e1000_put_hw_semaphore_generic(hw); for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); } } /* If we do not have the semaphore here, we have to give up. */ if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_NVM; } } /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) break; usec_delay(50); } if (i == timeout) { /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; }
void AtherosL1Ethernet::at_clean_rx_irq(at_adapter *adapter) { mbuf_t skb = NULL; u32 packet_size; int i, count; u16 length, rrd_next_to_clean; struct at_rfd_ring *rfd_ring = &adapter->rfd_ring; struct at_rrd_ring *rrd_ring = &adapter->rrd_ring; struct at_buffer * buffer_info; rx_return_desc_t* rrd; count = 0; rrd_next_to_clean = (u16)atomic_read(&rrd_ring->next_to_clean); DEBUGOUT1("at_clean_rx_irq() rrd_next_to_clean=%d\n", rrd_next_to_clean); while (1) { rrd = AT_RRD_DESC(rrd_ring, rrd_next_to_clean); i = 1; if (rrd->xsz.valid) { // packet valid chk_rrd: // check rrd status if (rrd->num_buf != 1) { DEBUGOUT1("RRD NumRfd %d\n", rrd->num_buf); DEBUGOUT1("packet length = %d\n", rrd->xsz.xsum_sz.pkt_size); } else { goto rrd_ok; } // rrd seems to be bad if (i-- > 0) { // rrd may not be DMAed completely DEBUGOUT("RRD may not be DMAed completely\n"); usec_delay(1); goto chk_rrd; } // bad rrd AT_ERR("BAD RRD\n"); // see if update RFD index if (rrd->num_buf > 1) { u16 num_buf; num_buf = (rrd->xsz.xsum_sz.pkt_size+adapter->rx_buffer_len - 1)/ adapter->rx_buffer_len; DEBUGOUT1("RRD.buf_index (%d)\n", rrd->buf_indx); if (rrd->num_buf == num_buf) { // clean alloc flag for bad rrd while (rfd_ring->next_to_clean != (rrd->buf_indx + num_buf) ) { DEBUGOUT1("clear index (%d)\n", rfd_ring->next_to_clean); rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; if (++rfd_ring->next_to_clean == rfd_ring->count) { rfd_ring->next_to_clean = 0; } } // end while } // end if (rrd->num_buf == ...) } // update rrd rrd->xsz.valid = 0; if (++rrd_next_to_clean == rrd_ring->count) rrd_next_to_clean = 0; count++; continue; } else { // current rrd still not be updated break; } rrd_ok: // clean alloc flag for bad rrd while (rfd_ring->next_to_clean != rrd->buf_indx) { rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; if (++rfd_ring->next_to_clean == rfd_ring->count) { rfd_ring->next_to_clean = 0; } } buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; if (++rfd_ring->next_to_clean == rfd_ring->count) { rfd_ring->next_to_clean = 0; } // update rrd next to clean if (++rrd_next_to_clean == rrd_ring->count) rrd_next_to_clean = 0; count++; if (rrd->pkt_flg&PACKET_FLAG_ERR) { if (rrd->err_flg& (ERR_FLAG_CRC|ERR_FLAG_TRUNC|ERR_FLAG_CODE|ERR_FLAG_OV)) { /* packet error , don't need upstream */ buffer_info->alloced = 0; rrd->xsz.valid = 0; DEBUGOUT1("rrd error flag %x\n", rrd->err_flg); continue; } } /* Good Receive */ length = OSSwapLittleToHostInt16(rrd->xsz.xsum_sz.pkt_size); packet_size = length - 4; // CRC // alloc new buffer skb = allocatePacket(packet_size + 2); if (NULL == skb) { DbgPrint("Memory squeeze, deferring packet.\n"); break; } DEBUGOUT1("pktsize=%d\n", packet_size); // copy packet to user buffer if (buffer_info->memDesc) { memcpy( mbuf_data(skb),buffer_info->memDesc->getBytesNoCopy(), packet_size); } //TO-DO: Add network stack notification netIface_->inputPacket(skb, packet_size, IONetworkInterface::kInputOptionQueuePacket); netIface_->flushInputQueue(); /* DEBUGOUT1("pkt:%02x %02x %02x %02x %02x %02x-%02x\n", skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5], skb->data[12]); */ // let protocol layer free skb buffer_info->alloced = 0; rrd->xsz.valid = 0; } atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); at_alloc_rx_buffers(adapter); // update mailbox ? if (0 != count) { at_update_mailbox(adapter); } }
/** * 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; }
/** * 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; }