ixgbe_common.c revision 185c5677613512bc5a906decb5034a5135f67fb1
/*
* CDDL HEADER START
*
* Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* IntelVersion: 1.206 v2-9-1-1_2009-6-10_NSW1 */
#include "ixgbe_common.h"
#include "ixgbe_api.h"
/*
* ixgbe_init_ops_generic - Inits function ptrs
* @hw: pointer to the hardware structure
*
* Initialize the function pointers.
*/
{
/* EEPROM */
/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
else
/* MAC */
/* LEDs */
/* RAR, Multicast, VLAN */
/* Flow Control */
/* Link */
return (IXGBE_SUCCESS);
}
/*
* @hw: pointer to hardware structure
*
* Starts the hardware by filling the bus info structure and media type, clears
* all on chip counters, initializes receive address registers, multicast
* table, VLAN filter table, calls routine to set up link and flow control
* settings, and leaves transmit and receive units disabled and uninitialized
*/
{
/* Set the media type */
/* PHY ops initialization must be done in reset_hw() */
/* Clear the VLAN filter table */
/* Clear statistics registers */
/* Set No Snoop Disable */
/* Setup flow control */
(void) ixgbe_setup_fc(hw, 0);
/* Clear adapter stopped flag */
hw->adapter_stopped = false;
return (IXGBE_SUCCESS);
}
/*
* ixgbe_init_hw_generic - Generic hardware initialization
* @hw: pointer to hardware structure
*
* Initialize the hardware by resetting the hardware, filling the bus info
* structure and media type, clears all on chip counters, initializes receive
* address registers, multicast table, VLAN filter table, calls routine to set
* up link and flow control settings, and leaves transmit and receive units
* disabled and uninitialized
*/
{
/* Reset the hardware */
if (status == IXGBE_SUCCESS) {
/* Start the HW */
}
return (status);
}
/*
* ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
* @hw: pointer to hardware structure
*
* Clears all hardware statistics counters by reading them from the hardware
* Statistics counters are clear on read.
*/
{
u16 i = 0;
for (i = 0; i < 8; i++)
} else {
}
for (i = 0; i < 8; i++) {
} else {
}
}
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++)
for (i = 0; i < 16; i++) {
} else {
}
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_read_pba_num_generic - Reads part number from EEPROM
* @hw: pointer to hardware structure
* @pba_num: stores the part number from the EEPROM
*
* Reads the part number from the EEPROM.
*/
{
DEBUGFUNC("ixgbe_read_pba_num_generic");
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return (ret_val);
}
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return (ret_val);
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_get_mac_addr_generic - Generic get MAC address
* @hw: pointer to hardware structure
* @mac_addr: Adapter MAC address
*
* Reads the adapter's MAC address from first Receive Address Register (RAR0)
* A reset of the adapter must be performed prior to calling this function
* in order for the MAC address to have been loaded from the EEPROM into RAR0
*/
{
u16 i;
for (i = 0; i < 4; i++)
for (i = 0; i < 2; i++)
return (IXGBE_SUCCESS);
}
/*
* ixgbe_get_bus_info_generic - Generic set PCI bus info
* @hw: pointer to hardware structure
*
* Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
*/
{
/* Get the negotiated link width and speed from PCI config space */
switch (link_status & IXGBE_PCI_LINK_WIDTH) {
case IXGBE_PCI_LINK_WIDTH_1:
break;
case IXGBE_PCI_LINK_WIDTH_2:
break;
case IXGBE_PCI_LINK_WIDTH_4:
break;
case IXGBE_PCI_LINK_WIDTH_8:
break;
default:
break;
}
switch (link_status & IXGBE_PCI_LINK_SPEED) {
break;
break;
default:
break;
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
* @hw: pointer to the HW structure
*
* Determines the LAN function id by reading memory-mapped registers
* and swaps the port value if requested.
*/
void
{
/* check for a port swap */
if (reg & IXGBE_FACTPS_LFS)
}
/*
* @hw: pointer to hardware structure
*
* Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
* disables transmit and receive units. The adapter_stopped flag is used by
* the shared code and drivers to determine if the adapter is in a stopped
* state and should not touch the hardware.
*/
{
u16 i;
/*
* Set the adapter_stopped flag so other driver functions stop touching
* the hardware
*/
hw->adapter_stopped = true;
/* Disable the receive unit */
reg_val &= ~(IXGBE_RXCTRL_RXEN);
msec_delay(2);
/* Clear interrupt mask to stop from interrupts being generated */
/* Clear any pending interrupts */
/* Disable the transmit unit. Each queue must be disabled. */
for (i = 0; i < number_of_queues; i++) {
if (reg_val & IXGBE_TXDCTL_ENABLE) {
}
}
/*
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests
*/
DEBUGOUT("PCI-E Master disable polling has failed.\n");
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_led_on_generic - Turns on the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn on
*/
{
/* To turn on the LED, set mode to ON. */
return (IXGBE_SUCCESS);
}
/*
* ixgbe_led_off_generic - Turns off the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn off
*/
{
/* To turn off the LED, set mode to OFF. */
return (IXGBE_SUCCESS);
}
/*
* ixgbe_init_eeprom_params_generic - Initialize EEPROM params
* @hw: pointer to hardware structure
*
* Initializes the EEPROM parameters ixgbe_eeprom_info within the
* ixgbe_hw struct in order to set up EEPROM access.
*/
{
/*
* Set default semaphore delay to 10ms which is a well
* tested value
*/
/*
* Check for EEPROM present first.
* If not present leave as none
*/
if (eec & IXGBE_EEC_PRES) {
/*
* SPI EEPROM is assumed here. This code would need to
* change if a future EEPROM is not SPI.
*/
}
if (eec & IXGBE_EEC_ADDR_SIZE)
else
DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: "
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
* @hw: pointer to hardware structure
* @offset: offset within the EEPROM to be written to
* @data: 16 bit word to be written to the EEPROM
*
* If ixgbe_eeprom_update_checksum is not called after this function, the
* EEPROM will most likely contain an invalid checksum.
*/
{
goto out;
}
/* Prepare the EEPROM for writing */
if (status == IXGBE_SUCCESS) {
}
}
if (status == IXGBE_SUCCESS) {
/* Send the WRITE ENABLE command (8 bit opcode ) */
/*
* Some SPI eeproms use the 8th address bit embedded in the
* opcode
*/
/* Send the Write command (8-bit opcode + addr) */
/* Send the data */
/* Done with writing - release the EEPROM */
}
out:
return (status);
}
/*
* ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
* @hw: pointer to hardware structure
* @offset: offset within the EEPROM to be read
* @data: read 16 bit value from EEPROM
*
* Reads 16 bit value from EEPROM through bit-bang method
*/
{
goto out;
}
/* Prepare the EEPROM for reading */
if (status == IXGBE_SUCCESS) {
}
}
if (status == IXGBE_SUCCESS) {
/*
* Some SPI eeproms use the 8th address bit embedded in the
* opcode
*/
/* Send the READ command (opcode + addr) */
/* Read the data. */
/* End this read operation */
}
out:
return (status);
}
/*
* ixgbe_read_eeprom_generic - Read EEPROM word using EERD
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
*/
{
goto out;
}
if (status == IXGBE_SUCCESS) {
} else {
DEBUGOUT("Eeprom read timed out\n");
}
out:
return (status);
}
/*
* ixgbe_poll_eeprom_eerd_done - Poll EERD status
* @hw: pointer to hardware structure
*
* Polls the status bit (bit 1) of the EERD to determine when the read is done.
*/
static s32
{
u32 i;
for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) {
if (reg & IXGBE_EEPROM_READ_REG_DONE) {
break;
}
usec_delay(5);
}
return (status);
}
/*
* ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
* @hw: pointer to hardware structure
*
* Prepares EEPROM for access using bit-bang method. This function should
* be called before issuing a command to the EEPROM.
*/
static s32
{
u32 i;
if (status == IXGBE_SUCCESS) {
/* Request EEPROM Access */
eec |= IXGBE_EEC_REQ;
for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
if (eec & IXGBE_EEC_GNT)
break;
usec_delay(5);
}
/* Release if grant not acquired */
if (!(eec & IXGBE_EEC_GNT)) {
eec &= ~IXGBE_EEC_REQ;
DEBUGOUT("Could not acquire EEPROM grant\n");
}
}
if (status == IXGBE_SUCCESS) {
/* Clear CS and SK */
usec_delay(1);
}
return (status);
}
/*
* ixgbe_get_eeprom_semaphore - Get hardware semaphore
* @hw: pointer to hardware structure
*
* Sets the hardware semaphores so EEPROM access can occur for bit-bang method
*/
static s32
{
u32 i;
/* Get SMBI software semaphore between device drivers first */
for (i = 0; i < timeout; i++) {
/*
* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
if (!(swsm & IXGBE_SWSM_SMBI)) {
break;
}
usec_delay(50);
}
if (status == IXGBE_SUCCESS) {
for (i = 0; i < timeout; i++) {
/* Set the SW EEPROM semaphore bit to request access */
/*
* If we set the bit successfully then we got the
* semaphore.
*/
if (swsm & IXGBE_SWSM_SWESMBI)
break;
usec_delay(50);
}
/*
* Release semaphores and return error if SW EEPROM semaphore
* was not granted because we don't have access to the EEPROM
*/
if (i >= timeout) {
DEBUGOUT("SWESMBI Software EEPROM semaphore "
"not granted.\n");
}
} else {
DEBUGOUT("Software semaphore SMBI between device drivers "
"not granted.\n");
}
return (status);
}
/*
* ixgbe_release_eeprom_semaphore - Release hardware semaphore
* @hw: pointer to hardware structure
*
* This function clears hardware semaphore bits.
*/
static void
{
/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
}
/*
* ixgbe_ready_eeprom - Polls for EEPROM ready
* @hw: pointer to hardware structure
*/
static s32
{
u16 i;
/*
* Read "Status Register" repeatedly until the LSB is cleared. The
* EEPROM will signal that the command has been completed by clearing
* bit 0 of the internal status register. If it's not cleared within
* 5 milliseconds, then error out.
*/
for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
break;
usec_delay(5);
};
/*
* On some parts, SPI write time could vary from 0-20mSec on 3.3V
* devices (and only 0-5mSec on 5V devices)
*/
if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
DEBUGOUT("SPI EEPROM Status error\n");
}
return (status);
}
/*
* ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
* @hw: pointer to hardware structure
*/
static void
{
/* Toggle CS to flush commands */
eec |= IXGBE_EEC_CS;
usec_delay(1);
eec &= ~IXGBE_EEC_CS;
usec_delay(1);
}
/*
* ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
* @hw: pointer to hardware structure
* @data: data to send to the EEPROM
* @count: number of bits to shift out
*/
static void
{
u32 i;
/*
* Mask is used to shift "count" bits of "data" out to the EEPROM
* one bit at a time. Determine the starting bit based on count
*/
for (i = 0; i < count; i++) {
/*
* A "1" is shifted out to the EEPROM by setting bit "DI" to a
* "1", and then raising and then lowering the clock (the SK
* bit controls the clock input to the EEPROM). A "0" is
* shifted out to the EEPROM by setting "DI" to "0" and then
* raising and then lowering the clock.
*/
eec |= IXGBE_EEC_DI;
else
eec &= ~IXGBE_EEC_DI;
usec_delay(1);
/*
* Shift mask to signify next bit of data to shift in to the
* EEPROM
*/
};
/* We leave the "DI" bit set to "0" when we leave this routine. */
eec &= ~IXGBE_EEC_DI;
}
/*
* ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
* @hw: pointer to hardware structure
*/
static u16
{
u32 i;
/*
* In order to read a register from the EEPROM, we need to shift
* 'count' bits in from the EEPROM. Bits are "shifted in" by raising
* the clock input to the EEPROM (setting the SK bit), and then reading
* the value of the "DO" bit. During this "shifting in" process the
* "DI" bit should always be clear.
*/
for (i = 0; i < count; i++) {
eec &= ~(IXGBE_EEC_DI);
if (eec & IXGBE_EEC_DO)
data |= 1;
}
return (data);
}
/*
* ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
* @hw: pointer to hardware structure
* @eec: EEC register's current value
*/
static void
{
/*
* Raise the clock input to the EEPROM
* (setting the SK bit), then delay
*/
usec_delay(1);
}
/*
* ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
* @hw: pointer to hardware structure
* @eecd: EECD's current value
*/
static void
{
/*
* Lower the clock input to the EEPROM (clearing the SK bit), then
* delay
*/
usec_delay(1);
}
/*
* ixgbe_release_eeprom - Release EEPROM, release semaphores
* @hw: pointer to hardware structure
*/
static void
{
usec_delay(1);
/* Stop requesting EEPROM access */
eec &= ~IXGBE_EEC_REQ;
/* Delay before attempt to obtain semaphore again to allow FW access */
}
/*
* ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
* @hw: pointer to hardware structure
*/
static u16
{
u16 i;
u16 j;
/* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
DEBUGOUT("EEPROM read failed\n");
break;
}
}
/* Include all data from pointers except for the fw pointer */
for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
/* Make sure the pointer seems valid */
}
}
}
}
return (checksum);
}
/*
* ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
* @hw: pointer to hardware structure
* @checksum_val: calculated checksum
*
* Performs checksum calculation and validates the EEPROM checksum. If the
* caller does not need checksum_val, the value can be NULL.
*/
{
u16 read_checksum = 0;
/*
* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
if (status == IXGBE_SUCCESS) {
/*
* Verify read checksum from EEPROM is the same as
* calculated checksum
*/
if (read_checksum != checksum)
/* If the user cares, return the calculated checksum */
if (checksum_val)
*checksum_val = checksum;
} else {
DEBUGOUT("EEPROM read failed\n");
}
return (status);
}
/*
* ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
* @hw: pointer to hardware structure
*/
{
/*
* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
if (status == IXGBE_SUCCESS) {
checksum);
} else {
DEBUGOUT("EEPROM read failed\n");
}
return (status);
}
/*
* ixgbe_validate_mac_addr - Validate MAC address
* @mac_addr: pointer to MAC address.
*
* Tests a MAC address to ensure it is a valid Individual Address
*/
{
/* Make sure it is not a multicast address */
if (IXGBE_IS_MULTICAST(mac_addr)) {
DEBUGOUT("MAC address is multicast\n");
/* Not a broadcast address */
} else if (IXGBE_IS_BROADCAST(mac_addr)) {
DEBUGOUT("MAC address is broadcast\n");
/* Reject the zero address */
DEBUGOUT("MAC address is all zeros\n");
}
return (status);
}
/*
* ixgbe_set_rar_generic - Set Rx address register
* @hw: pointer to hardware structure
* @index: Receive address register to write
* @addr: Address to put into receive address register
* @vmdq: VMDq "set" or "pool" index
* @enable_addr: set flag that address is active
*
* Puts an ethernet address into a receive address register.
*/
{
/* setup VMDq pool selection before this RAR gets enabled */
/* Make sure we are using a valid rar index range */
if (index < rar_entries) {
/*
* HW expects these in little endian so we reverse the byte
* order from network order (big endian) to little endian
*/
/*
* Some parts put the VMDq setting in the extra RAH bits,
* so save everything except the lower 16 bits that hold part
* of the address and the address valid bit.
*/
if (enable_addr != 0)
rar_high |= IXGBE_RAH_AV;
} else {
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_clear_rar_generic - Remove Rx address register
* @hw: pointer to hardware structure
* @index: Receive address register to write
*
* Clears an ethernet address from a receive address register.
*/
{
/* Make sure we are using a valid rar index range */
if (index < rar_entries) {
/*
* Some parts put the VMDq setting in the extra RAH bits,
* so save everything except the lower 16 bits that hold part
* of the address and the address valid bit.
*/
} else {
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_init_rx_addrs_generic - Initializes receive address filters.
* @hw: pointer to hardware structure
*
* Places the MAC address in receive address register 0 and clears the rest
* of the receive address registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*/
{
u32 i;
/*
* If the current mac address is valid, assume it is a software override
* to the permanent address.
* Otherwise, use the permanent address from the eeprom.
*/
/* Get the MAC address from the RAR0 for later reference */
DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
} else {
/* Setup the receive address. */
DEBUGOUT("Overriding MAC Address in RAR[0]\n");
DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
}
/* Zero out the other receive addresses. */
for (i = 1; i < rar_entries; i++) {
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
(void) ixgbe_init_uta_tables(hw);
return (IXGBE_SUCCESS);
}
/*
* ixgbe_add_uc_addr - Adds a secondary unicast address.
* @hw: pointer to hardware structure
* @addr: new address
*
* Adds it to unused receive address register or goes into promiscuous mode.
*/
void
{
DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
/*
* Place this address in the RAR if there is room,
* else put the controller into promiscuous mode
*/
} else {
}
DEBUGOUT("ixgbe_add_uc_addr Complete\n");
}
/*
* ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
* @hw: pointer to hardware structure
* @addr_list: the list of new addresses
* @addr_count: number of addresses
* @next: iterator function to walk the address list
*
* The given list replaces any existing list. Clears the secondary addrs from
* receive address registers. Uses unused receive address registers for the
* first secondary addresses, and falls back to promiscuous mode as needed.
*
* Drivers using secondary unicast addresses must set user_set_promisc when
* manually putting the device into promiscuous mode.
*/
{
u32 i;
/*
* Clear accounting of old secondary address list,
* don't count RAR[0]
*/
/* Zero out the other receive addresses */
for (i = 1; i <= uc_addr_in_use; i++) {
}
/* Add the new addresses */
for (i = 0; i < addr_count; i++) {
DEBUGOUT(" Adding the secondary addresses:\n");
}
/* enable promisc if not already in overflow or set by user */
DEBUGOUT(" Entering address overflow promisc mode\n");
fctrl |= IXGBE_FCTRL_UPE;
}
} else {
/* only disable if set by overflow, not by user */
DEBUGOUT(" Leaving address overflow promisc mode\n");
fctrl &= ~IXGBE_FCTRL_UPE;
}
}
DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n");
return (IXGBE_SUCCESS);
}
/*
* ixgbe_mta_vector - Determines bit-vector in multicast table to set
* @hw: pointer to hardware structure
* @mc_addr: the multicast address
*
* Extracts the 12 bits, from a multicast address, to determine which
* bit-vector to set in the multicast table. The hardware uses 12 bits, from
* incoming rx multicast addresses, to determine the bit-vector to check in
* the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
* by the MO field of the MCSTCTRL. The MO field is set during initialization
* to mc_filter_type.
*/
static s32
{
case 0: /* use bits [47:36] of the address */
break;
case 1: /* use bits [46:35] of the address */
break;
case 2: /* use bits [45:34] of the address */
break;
case 3: /* use bits [43:32] of the address */
break;
default: /* Invalid mc_filter_type */
DEBUGOUT("MC filter type param set incorrectly\n");
ASSERT(0);
break;
}
/* vector can only be 12-bits or boundary will be exceeded */
vector &= 0xFFF;
return (vector);
}
/*
* ixgbe_set_mta - Set bit-vector in multicast table
* @hw: pointer to hardware structure
* @hash_value: Multicast address hash value
*
* Sets the bit-vector in the multicast table.
*/
void
{
/*
* The MTA is a register array of 128 32-bit registers. It is treated
* like an array of 4096 bits. We want to set bit
* BitArray[vector_value]. So we figure out what register the bit is
* in, read it, OR in the new bit, then write back the new value. The
* register is determined by the upper 7 bits of the vector value and
* the bit within that register are determined by the lower 5 bits of
* the value.
*/
}
/*
* ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
* @hw: pointer to hardware structure
* @mc_addr_list: the list of new multicast addresses
* @mc_addr_count: number of addresses
* @next: iterator function to walk the multicast address list
*
* The given list replaces any existing list. Clears the MC addrs from receive
* address registers and the multicast table. Uses unused receive address
* registers for the first multicast addresses, and hashes the rest into the
* multicast table.
*/
{
u32 i;
/*
* Set the new number of MC addresses that we are being requested to
* use.
*/
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
/* Add the new addresses */
for (i = 0; i < mc_addr_count; i++) {
DEBUGOUT(" Adding the multicast addresses:\n");
}
/* Enable mta */
DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n");
return (IXGBE_SUCCESS);
}
/*
* ixgbe_enable_mc_generic - Enable multicast address in RAR
* @hw: pointer to hardware structure
*
* Enables multicast address in RAR and the use of the multicast hash table.
*/
{
if (a->mta_in_use > 0)
return (IXGBE_SUCCESS);
}
/*
* ixgbe_disable_mc_generic - Disable multicast address in RAR
* @hw: pointer to hardware structure
*
* Disables multicast address in RAR and the use of the multicast hash table.
*/
{
if (a->mta_in_use > 0)
return (IXGBE_SUCCESS);
}
/*
* ixgbe_fc_enable_generic - Enable flow control
* @hw: pointer to hardware structure
* @packetbuf_num: packet buffer number (0-7)
*
* Enable flow control according to the current settings.
*/
{
DEBUGFUNC("ixgbe_fc_enable_generic");
/* Negotiate the fc mode to use */
if (ret_val)
goto out;
/* Disable any previous flow control settings */
/*
* The possible values of fc.current_mode are:
* 0: Flow control is completely disabled
* 1: Rx flow control is enabled (we can receive pause frames,
* but not send pause frames).
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
* other: Invalid.
*/
case ixgbe_fc_none:
/*
* Flow control is disabled by software override or autoneg.
* The code below will actually disable it in the HW.
*/
break;
case ixgbe_fc_rx_pause:
/*
* Rx Flow control is enabled and Tx Flow control is
* disabled by software override. Since there really
* isn't a way to advertise that we are capable of RX
* Pause ONLY, we will advertise that we support both
* symmetric and asymmetric Rx PAUSE. Later, we will
* disable the adapter's ability to send PAUSE frames.
*/
break;
case ixgbe_fc_tx_pause:
/*
* Tx Flow control is enabled, and Rx Flow control is
* disabled by software override.
*/
break;
case ixgbe_fc_full:
/* Flow control (both Rx and Tx) is enabled by SW override. */
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
goto out;
}
/* Set 802.3x based flow control settings. */
/* Thresholds are different for link flow control when in DCB mode */
if (reg & IXGBE_MTQC_RT_ENA) {
/* Always disable XON for LFC when in DCB mode */
reg |= IXGBE_FCRTH_FCEN;
} else {
/*
* enable XON.
*/
} else {
}
}
}
/* Configure pause time (2 TCs per register) */
if ((packetbuf_num & 1) == 0)
else
out:
return (ret_val);
}
/*
* ixgbe_fc_autoneg - Configure flow control
* @hw: pointer to hardware structure
*
* Compares our advertised flow control capabilities to those advertised by
* our link partner, and determines the proper flow control mode to use.
*/
{
bool link_up;
DEBUGFUNC("ixgbe_fc_autoneg");
/*
* AN should have completed when the cable was plugged in.
* Look for reasons to bail out. Bail out if:
* - FC autoneg is disabled, or if
* - we don't have multispeed fiber, or if
* - we're not running at 1G, or if
* - link is not up, or if
* - link is up but AN did not complete, or if
* - link is up and AN completed but timed out
*
* Since we're being called from an LSC, link is already know to be up.
* So use link_up_wait_to_complete=false.
*/
(speed != IXGBE_LINK_SPEED_1GB_FULL) ||
!link_up ||
((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
DEBUGOUT("Autoneg FC was skipped.\n");
goto out;
}
/*
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
if ((pcs_anadv_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.
*/
DEBUGOUT("Flow Control = FULL.\n");
} else {
DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
}
} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
!(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
} else {
DEBUGOUT("Flow Control = NONE.\n");
}
/* Record that current_mode is the result of a successful autoneg */
out:
return (ret_val);
}
/*
* ixgbe_setup_fc - Set up flow control
* @hw: pointer to hardware structure
*
* Called at init time to set up flow control.
*/
{
/* Validate the packetbuf configuration */
DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
" 0-7\n", packetbuf_num);
goto out;
}
/*
* Validate the water mark configuration. Zero water marks are invalid
* because it causes the controller to just blast out fc packets.
*/
DEBUGOUT("Invalid water mark configuration\n");
goto out;
}
/*
* Validate the requested mode. Strict IEEE mode does not allow
* ixgbe_fc_rx_pause because it will cause us to fail at UNH.
*/
DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
goto out;
}
/*
* 10gig parts do not have a word in the EEPROM to determine the
* default flow control setting, so we explicitly set it to full.
*/
/*
* Set up the 1G flow control advertisement registers so the HW will be
* able to do fc autoneg once the cable is plugged in. If we end up
* using 10g instead, this is harmless.
*/
/*
* The possible values of fc.requested_mode are:
* 0: Flow control is completely disabled
* 1: Rx flow control is enabled (we can receive pause frames,
* but not send pause frames).
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
* other: Invalid.
*/
case ixgbe_fc_none:
/* Flow control completely disabled by software override. */
break;
case ixgbe_fc_rx_pause:
/*
* Rx Flow control is enabled and Tx Flow control is
* disabled by software override. Since there really
* isn't a way to advertise that we are capable of RX
* Pause ONLY, we will advertise that we support both
* symmetric and asymmetric Rx PAUSE. Later, we will
* disable the adapter's ability to send PAUSE frames.
*/
break;
case ixgbe_fc_tx_pause:
/*
* Tx Flow control is enabled, and Rx Flow control is
* disabled by software override.
*/
reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
break;
case ixgbe_fc_full:
/* Flow control (both Rx and Tx) is enabled by SW override. */
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
goto out;
}
/* Enable and restart autoneg to inform the link partner */
/* Disable AN timeout */
out:
return (ret_val);
}
/*
* ixgbe_disable_pcie_master - Disable PCI-express master access
* @hw: pointer to hardware structure
*
* Disables PCI-Express master access and verifies there are no pending
* requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
* bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
* is returned signifying master requests disabled.
*/
{
u32 i;
/* Disable the receive unit by stopping each queue */
for (i = 0; i < number_of_queues; i++) {
if (reg_val & IXGBE_RXDCTL_ENABLE) {
}
}
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
break;
}
usec_delay(100);
}
return (status);
}
/*
* ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to acquire
*
* Acquires the SWFW semaphore thought the GSSR register for the specified
* function (CSR, PHY0, PHY1, EEPROM, Flash)
*/
{
while (timeout) {
/*
* SW EEPROM semaphore bit is used for access to all
* SW_FW_SYNC/GSSR bits (not just EEPROM)
*/
if (ixgbe_get_eeprom_semaphore(hw))
return (-IXGBE_ERR_SWFW_SYNC);
break;
/*
* Firmware currently using resource (fwmask) or other software
* thread currently using resource (swmask)
*/
msec_delay(5);
timeout--;
}
if (!timeout) {
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
return (-IXGBE_ERR_SWFW_SYNC);
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_release_swfw_sync - Release SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to release
*
* Releases the SWFW semaphore thought the GSSR register for the specified
* function (CSR, PHY0, PHY1, EEPROM, Flash)
*/
void
{
(void) ixgbe_get_eeprom_semaphore(hw);
}
/*
* ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
* @hw: pointer to hardware structure
* @regval: register value to write to RXCTRL
*
* Enables the Rx DMA unit
*/
{
return (IXGBE_SUCCESS);
}
/*
* ixgbe_blink_led_start_generic - Blink LED based on index.
* @hw: pointer to hardware structure
* @index: led number to blink
*/
{
ixgbe_link_speed speed = 0;
bool link_up = 0;
/*
* Link must be up to auto-blink the LEDs;
* Force it if link is down.
*/
if (!link_up) {
msec_delay(10);
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
* @hw: pointer to hardware structure
* @index: led number to stop blinking
*/
{
autoc_reg &= ~IXGBE_AUTOC_FLU;
return (IXGBE_SUCCESS);
}