ixgbe_common.c revision 19843f01b1bef3453f717c23c8f89fb9313f6749
/*
* CDDL HEADER START
*
* Copyright(c) 2007-2010 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* IntelVersion: 1.227 sol_ixgbe_shared_339b */
#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.
*/
{
DEBUGFUNC("ixgbe_init_ops_generic");
/* 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
*/
{
DEBUGFUNC("ixgbe_start_hw_generic");
/* 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
*/
{
DEBUGFUNC("ixgbe_init_hw_generic");
/* 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;
DEBUGFUNC("ixgbe_clear_hw_cntrs_generic");
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;
DEBUGFUNC("ixgbe_get_mac_addr_generic");
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
*/
{
DEBUGFUNC("ixgbe_get_bus_info_generic");
/* 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
{
DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
/* 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;
DEBUGFUNC("ixgbe_stop_adapter_generic");
/*
* 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
*/
(void) ixgbe_disable_pcie_master(hw);
return (IXGBE_SUCCESS);
}
/*
* ixgbe_led_on_generic - Turns on the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn on
*/
{
DEBUGFUNC("ixgbe_led_on_generic");
/* 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
*/
{
DEBUGFUNC("ixgbe_led_off_generic");
/* 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.
*/
{
DEBUGFUNC("ixgbe_init_eeprom_params_generic");
/*
* 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.
*/
{
DEBUGFUNC("ixgbe_write_eeprom_generic");
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
*/
{
DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
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_eerd_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.
*/
{
DEBUGFUNC("ixgbe_read_eerd_generic");
goto out;
}
if (status == IXGBE_SUCCESS)
else
DEBUGOUT("Eeprom read timed out\n");
out:
return (status);
}
/*
* ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
* @hw: pointer to hardware structure
* @ee_reg: EEPROM flag for polling
*
* Polls the status bit (bit 1) of the EERD or EEWR to determine when the
* read or write is done respectively.
*/
{
u32 i;
DEBUGFUNC("ixgbe_poll_eerd_eewr_done");
for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
if (ee_reg == IXGBE_NVM_POLL_READ)
else
if (reg & IXGBE_EEPROM_RW_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;
DEBUGFUNC("ixgbe_acquire_eeprom");
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;
DEBUGFUNC("ixgbe_get_eeprom_semaphore");
/* 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
{
DEBUGFUNC("ixgbe_release_eeprom_semaphore");
/* 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;
DEBUGFUNC("ixgbe_ready_eeprom");
/*
* 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
{
DEBUGFUNC("ixgbe_standby_eeprom");
/* 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;
DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
/*
* 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;
DEBUGFUNC("ixgbe_shift_in_eeprom_bits");
/*
* 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
{
DEBUGFUNC("ixgbe_raise_eeprom_clk");
/*
* 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
{
DEBUGFUNC("ixgbe_lower_eeprom_clk");
/*
* 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
{
DEBUGFUNC("ixgbe_release_eeprom");
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_generic - Calculates and returns the checksum
* @hw: pointer to hardware structure
*/
{
u16 i;
u16 j;
DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic");
/* 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;
DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
/*
* 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
*/
{
DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
/*
* 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
*/
{
DEBUGFUNC("ixgbe_validate_mac_addr");
/* 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.
*/
{
DEBUGFUNC("ixgbe_set_rar_generic");
/* 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.
*/
{
DEBUGFUNC("ixgbe_clear_rar_generic");
/* 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;
DEBUGFUNC("ixgbe_init_rx_addrs_generic");
/*
* 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
{
DEBUGFUNC("ixgbe_add_uc_addr");
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;
DEBUGFUNC("ixgbe_update_uc_addr_list_generic");
/*
* Clear accounting of old secondary address list,
* don't count RAR[0]
*/
/* Zero out the other receive addresses */
for (i = 0; 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
{
DEBUGFUNC("ixgbe_mta_vector");
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
{
DEBUGFUNC("ixgbe_set_mta");
/*
* 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;
DEBUGFUNC("ixgbe_update_mc_addr_list_generic");
/*
* 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.
*/
{
DEBUGFUNC("ixgbe_enable_mc_generic");
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.
*/
{
DEBUGFUNC("ixgbe_disable_mc_generic");
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
* - link is not up.
*
* Since we're being called from an LSC, link is already known to be up.
* So use link_up_wait_to_complete=false.
*/
goto out;
}
/*
* On backplane, bail out if
* - backplane autoneg was not completed, or if
* - we are 82599 and link partner is not AN enabled
*/
if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
goto out;
}
if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
goto out;
}
}
}
/*
* On multispeed fiber at 1g, bail out if
* - link is up but AN did not complete, or if
* - link is up and AN completed but timed out
*/
if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
goto out;
}
}
/*
* Bail out on
* - copper or CX4 adapters
* - fiber adapters running at 10gig
*/
(speed == IXGBE_LINK_SPEED_10GB_FULL))) {
goto out;
}
/*
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
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");
}
}
/*
* Read the 10g AN autoc and LP ability registers and resolve
* local flow control settings accordingly
*/
if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
(anlp1_reg & IXGBE_ANLP1_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 (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
(autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
(anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
} else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
(autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
!(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
(anlp1_reg & IXGBE_ANLP1_ASM_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.
*/
{
DEBUGFUNC("ixgbe_setup_fc");
/* 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;
}
/* Disable AN timeout */
/*
* Set up the 10G flow control advertisement registers so the HW
* can do fc autoneg once the cable is plugged in. If we end up
* using 1g 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_AUTOC_ASM_PAUSE);
reg &= ~(IXGBE_AUTOC_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;
}
/*
* AUTOC restart handles negotiation of 1G and 10G. There is
* no need to set the PCS1GCTL register.
*/
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;
DEBUGFUNC("ixgbe_disable_pcie_master");
/* Just jump out if bus mastering is already disabled */
goto out;
/* 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++) {
goto out;
usec_delay(100);
}
DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
/*
* The GIO Master Disable bit didn't clear. There are multiple reasons
* for this listed in the datasheet 5.2.5.3.2 Master Disable, and they
* all require a double reset to recover from. Before proceeding, we
* first wait a little more to try to ensure that, at a minimum, the
* PCIe block has no transactions pending.
*/
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
break;
usec_delay(100);
}
if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
DEBUGOUT("PCIe transaction pending bit also did not clear.\n");
/*
* Two consecutive resets are required via CTRL.RST per datasheet
* 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine
* of this need. The first reset prevents new master requests from
* being issued by our device. We then must wait 1usec for any
* remaining completions from the PCIe bus to trickle in, and then reset
* again to clear out any effects they may have had on our device.
*/
out:
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)
*/
{
DEBUGFUNC("ixgbe_acquire_swfw_sync");
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
{
DEBUGFUNC("ixgbe_release_swfw_sync");
(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
*/
{
DEBUGFUNC("ixgbe_enable_rx_dma_generic");
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;
DEBUGFUNC("ixgbe_blink_led_start_generic");
/*
* 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
*/
{
DEBUGFUNC("ixgbe_blink_led_stop_generic");
autoc_reg &= ~IXGBE_AUTOC_FLU;
return (IXGBE_SUCCESS);
}
/*
* ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
* @hw: pointer to hardware structure
* @san_mac_offset: SAN MAC address offset
*
* This function will read the EEPROM location for the SAN MAC address
* pointer, and returns the value at that location. This is used in both
* get and set mac_addr routines.
*/
static s32
{
DEBUGFUNC("ixgbe_get_san_mac_addr_offset");
/*
* First read the EEPROM pointer to see if the MAC addresses are
* available.
*/
return (IXGBE_SUCCESS);
}
/*
* ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
* @hw: pointer to hardware structure
* @san_mac_addr: SAN MAC address
*
* Reads the SAN MAC address from the EEPROM, if it's available. This is
* per-port, so set_lan_id() must be called before reading the addresses.
* set_lan_id() is called by identify_sfp(), but this cannot be relied
* upon for non-SFP connections, so we must call it here.
*/
{
u8 i;
DEBUGFUNC("ixgbe_get_san_mac_addr_generic");
/*
* First read the EEPROM pointer to see if the MAC addresses are
* available. If they're not, no point in calling set_lan_id() here.
*/
/*
* No addresses available in this EEPROM. It's not an
* error though, so just wipe the local address and return.
*/
for (i = 0; i < 6; i++)
san_mac_addr[i] = 0xFF;
goto san_mac_addr_out;
}
/* make sure we know which port we need to program */
/* apply the port offset to the address offset */
for (i = 0; i < 3; i++) {
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM
* @hw: pointer to hardware structure
* @san_mac_addr: SAN MAC address
*
* Write a SAN MAC address to the EEPROM.
*/
{
u8 i;
DEBUGFUNC("ixgbe_set_san_mac_addr_generic");
/* Look for SAN mac address pointer. If not defined, return */
goto san_mac_addr_out;
}
/* Make sure we know which port we need to write */
/* Apply the port offset to the address offset */
for (i = 0; i < 3; i++) {
}
return (status);
}
/*
* ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count
* @hw: pointer to hardware structure
*
* Read PCIe configuration space, and get the MSI-X vector count from
* the capabilities table.
*/
{
DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
/*
* MSI-X count is zero-based in HW, so increment to give
* proper value.
*/
msix_count++;
}
return (msix_count);
}
/*
* ixgbe_insert_mac_addr_generic - Find a RAR for this mac address
* @hw: pointer to hardware structure
* @addr: Address to put into receive address register
* @vmdq: VMDq pool to assign
*
* Puts an ethernet address into a receive address register, or
* finds the rar that it is aleady in; adds to the pool list
*/
{
DEBUGFUNC("ixgbe_insert_mac_addr_generic");
/* swap bytes for HW little endian */
/*
* Either find the mac_id in rar or find the first empty space.
* rar_highwater points to just after the highest currently used
* rar in order to shorten the search. It grows when we add a new
* rar to the top.
*/
if (((IXGBE_RAH_AV & rar_high) == 0) &&
break; /* found it already in the rars */
}
}
/* already there so just add to the pool bits */
} else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
/* stick it into first empty RAR slot we found */
/* add it to the top of the list and inc the highwater mark */
return (IXGBE_ERR_INVALID_MAC_ADDR);
}
/*
* If we found rar[0], make sure the default pool bit (we use pool 0)
* remains cleared to be sure default pool packets will get delivered
*/
if (rar == 0)
return (rar);
}
/*
* ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
* @hw: pointer to hardware struct
* @rar: receive address register index to disassociate
* @vmdq: VMDq pool index to remove from the rar
*/
{
DEBUGFUNC("ixgbe_clear_vmdq_generic");
if (rar < rar_entries) {
goto done;
if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
if (mpsar_lo) {
mpsar_lo = 0;
}
if (mpsar_hi) {
mpsar_hi = 0;
}
} else if (vmdq < 32) {
} else {
}
/* was that the last pool using this rar? */
} else {
}
done:
return (IXGBE_SUCCESS);
}
/*
* ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
* @hw: pointer to hardware struct
* @rar: receive address register index to associate with a VMDq index
* @vmdq: VMDq pool index
*/
{
DEBUGFUNC("ixgbe_set_vmdq_generic");
if (rar < rar_entries) {
if (vmdq < 32) {
} else {
}
} else {
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
* @hw: pointer to hardware structure
*/
{
int i;
DEBUGFUNC("ixgbe_init_uta_tables_generic");
DEBUGOUT(" Clearing UTA\n");
for (i = 0; i < 128; i++)
return (IXGBE_SUCCESS);
}
/*
* ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
* @hw: pointer to hardware structure
* @vlan: VLAN id to write to VLAN filter
*
* return the VLVF index where this VLAN id should be placed
*
*/
{
u32 first_empty_slot = 0;
/* short cut the special case */
if (vlan == 0)
return (0);
/*
* Search for the vlan id in the VLVF entries. Save off the first empty
* slot found along the way
*/
if (!bits && !(first_empty_slot))
break;
}
/*
* If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan
* in the VLVF. Else use the first empty VLVF register for this
* vlan id.
*/
if (regindex >= IXGBE_VLVF_ENTRIES) {
if (first_empty_slot)
else {
DEBUGOUT("No space in VLVF.\n");
}
}
return (regindex);
}
/*
* ixgbe_set_vfta_generic - Set VLAN filter table
* @hw: pointer to hardware structure
* @vlan: VLAN id to write to VLAN filter
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
*
*/
{
bool vfta_changed = false;
DEBUGFUNC("ixgbe_set_vfta_generic");
if (vlan > 4095)
return (IXGBE_ERR_PARAM);
/*
* this is a 2 part operation - first the VFTA, then the
* VLVF and VLVFB if VT Mode is set
* We don't write the VFTA until we know the VLVF part succeeded.
*/
/*
* Part 1
* The VFTA is a bitstring made up of 128 32-bit registers
* that enable the particular VLAN id, much like the MTA:
* bits[11-5]: which register
* bits[4-0]: which bit in the register
*/
if (vlan_on) {
vfta_changed = true;
}
} else {
vfta_changed = true;
}
}
/*
* Part 2
* If VT Mode is set
* Either vlan_on
* make sure the vlan is in VLVF
* set the vind bit in the matching VLVFB
* Or !vlan_on
* clear the pool bit and possibly the vind
*/
if (vt & IXGBE_VT_CTL_VT_ENABLE) {
if (vlvf_index < 0)
return (vlvf_index);
if (vlan_on) {
/* set the pool bit */
if (vind < 32) {
bits);
} else {
bits);
}
} else {
/* clear the pool bit */
if (vind < 32) {
bits);
} else {
bits);
}
}
/*
* If there are still bits set in the VLVFB registers
* for the VLAN ID indicated we need to see if the
* caller is requesting that we clear the VFTA entry bit.
* If the caller has requested that we clear the VFTA
* ID entry then ignore the request. We're not worried
* about the case where we're turning the VFTA VLAN ID
* entry bit on, only when requested to turn it off as
* VLAN ID entry. In that case we cannot clear the
* been cleared. This will be indicated by "bits" being
* zero.
*/
if (bits) {
(IXGBE_VLVF_VIEN | vlan));
if (!vlan_on) {
/*
* someone wants to clear the vfta entry
* Ignore it.
*/
vfta_changed = false;
}
} else {
}
}
if (vfta_changed)
return (IXGBE_SUCCESS);
}
/*
* ixgbe_clear_vfta_generic - Clear VLAN filter table
* @hw: pointer to hardware structure
*
* Clears the VLAN filer table, and the VMDq index associated with the filter
*/
{
DEBUGFUNC("ixgbe_clear_vfta_generic");
}
return (IXGBE_SUCCESS);
}
/*
* ixgbe_check_mac_link_generic - Determine link and speed status
* @hw: pointer to hardware structure
* @speed: pointer to link speed
* @link_up: true when link is up
* @link_up_wait_to_complete: bool used to wait for link up or not
*
* Reads the links register to determine if link is up and the current speed
*/
bool *link_up, bool link_up_wait_to_complete)
{
u32 i;
DEBUGFUNC("ixgbe_check_mac_link_generic");
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);
}
} else {
if (links_reg & IXGBE_LINKS_UP)
*link_up = true;
else
*link_up = false;
}
if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
else
/* if link is down, zero out the current_mode */
if (*link_up == false) {
}
return (IXGBE_SUCCESS);
}
/*
* the EEPROM
* @hw: pointer to hardware structure
* @wwnn_prefix: the alternative WWNN prefix
* @wwpn_prefix: the alternative WWPN prefix
*
* This function will read the EEPROM from the alternative SAN MAC address
*/
{
DEBUGFUNC("ixgbe_get_wwn_prefix_generic");
/* clear output first */
*wwnn_prefix = 0xFFFF;
*wwpn_prefix = 0xFFFF;
/* check if alternative SAN MAC is supported */
if ((alt_san_mac_blk_offset == 0) ||
(alt_san_mac_blk_offset == 0xFFFF))
goto wwn_prefix_out;
/* check capability in alternative san mac address block */
if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
goto wwn_prefix_out;
return (IXGBE_SUCCESS);
}