diff options
author | jfv <jfv@FreeBSD.org> | 2008-05-16 18:46:30 +0000 |
---|---|---|
committer | jfv <jfv@FreeBSD.org> | 2008-05-16 18:46:30 +0000 |
commit | 57de9f8139222232fe979e551a156428ea474d04 (patch) | |
tree | 9aec21727f8b2a5d35e54cb6951c970d9052ca50 /sys/dev/ixgbe/ixgbe_common.c | |
parent | 14ceaad756cfa75128f72cd64bc54463ac22a11e (diff) | |
download | FreeBSD-src-57de9f8139222232fe979e551a156428ea474d04.zip FreeBSD-src-57de9f8139222232fe979e551a156428ea474d04.tar.gz |
This is driver version 1.4.4 of the Intel ixgbe driver.
-It has new hardware support
-It uses a new method of TX cleanup called Head Write Back
-It includes the provisional generic TCP LRO feature contributed
by Myricom and made general purpose by me. This should move into
the stack upon approval but for this driver drop its in here.
-Also bug fixes and etc...
MFC in a week if no serious issues arise.
Diffstat (limited to 'sys/dev/ixgbe/ixgbe_common.c')
-rw-r--r-- | sys/dev/ixgbe/ixgbe_common.c | 681 |
1 files changed, 399 insertions, 282 deletions
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index f9cc69c..191cefd 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -1,6 +1,6 @@ -/******************************************************************************* +/****************************************************************************** - Copyright (c) 2001-2007, Intel Corporation + Copyright (c) 2001-2008, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,9 +29,8 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************/ -/* $FreeBSD$ */ - +******************************************************************************/ +/*$FreeBSD$*/ #include "ixgbe_common.h" #include "ixgbe_api.h" @@ -43,7 +42,7 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, - u16 count); + u16 count); static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); @@ -54,51 +53,75 @@ static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); +void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); /** - * ixgbe_assign_func_pointers_generic - Set generic func ptrs - * @hw: pointer to hardware structure + * ixgbe_init_ops_generic - Inits function ptrs + * @hw: pointer to the hardware structure * - * Assigns generic function pointers. Adapter-specific functions can - * override the assignment of generic function pointers by assigning - * their own adapter-specific function pointers. + * Initialize the function pointers. **/ -s32 ixgbe_assign_func_pointers_generic(struct ixgbe_hw *hw) +s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) { - struct ixgbe_functions *f = &hw->func; - - f->ixgbe_func_init_hw = &ixgbe_init_hw_generic; - f->ixgbe_func_start_hw = &ixgbe_start_hw_generic; - f->ixgbe_func_clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; - f->ixgbe_func_get_mac_addr = &ixgbe_get_mac_addr_generic; - f->ixgbe_func_stop_adapter = &ixgbe_stop_adapter_generic; - f->ixgbe_func_get_bus_info = &ixgbe_get_bus_info_generic; - /* LED */ - f->ixgbe_func_led_on = &ixgbe_led_on_generic; - f->ixgbe_func_led_off = &ixgbe_led_off_generic; + struct ixgbe_eeprom_info *eeprom = &hw->eeprom; + struct ixgbe_mac_info *mac = &hw->mac; + u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); + /* EEPROM */ - f->ixgbe_func_init_eeprom_params = &ixgbe_init_eeprom_params_generic; - f->ixgbe_func_read_eeprom = &ixgbe_read_eeprom_bit_bang_generic; - f->ixgbe_func_write_eeprom = &ixgbe_write_eeprom_generic; - f->ixgbe_func_validate_eeprom_checksum = - &ixgbe_validate_eeprom_checksum_generic; - f->ixgbe_func_update_eeprom_checksum = - &ixgbe_update_eeprom_checksum_generic; + eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; + /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ + if (eec & (1 << 8)) + eeprom->ops.read = &ixgbe_read_eeprom_generic; + else + eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; + eeprom->ops.write = &ixgbe_write_eeprom_generic; + eeprom->ops.validate_checksum = + &ixgbe_validate_eeprom_checksum_generic; + eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; + + /* MAC */ + mac->ops.init_hw = &ixgbe_init_hw_generic; + mac->ops.reset_hw = NULL; + mac->ops.start_hw = &ixgbe_start_hw_generic; + mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; + mac->ops.get_media_type = NULL; + mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic; + mac->ops.stop_adapter = &ixgbe_stop_adapter_generic; + mac->ops.get_bus_info = &ixgbe_get_bus_info_generic; + mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_generic; + mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_generic; + + /* LEDs */ + mac->ops.led_on = &ixgbe_led_on_generic; + mac->ops.led_off = &ixgbe_led_off_generic; + mac->ops.blink_led_start = NULL; + mac->ops.blink_led_stop = NULL; + /* RAR, Multicast, VLAN */ - f->ixgbe_func_set_rar = &ixgbe_set_rar_generic; - f->ixgbe_func_init_rx_addrs = &ixgbe_init_rx_addrs_generic; - f->ixgbe_func_update_mc_addr_list = &ixgbe_update_mc_addr_list_generic; - f->ixgbe_func_enable_mc = &ixgbe_enable_mc_generic; - f->ixgbe_func_disable_mc = &ixgbe_disable_mc_generic; - f->ixgbe_func_clear_vfta = &ixgbe_clear_vfta_generic; - f->ixgbe_func_set_vfta = &ixgbe_set_vfta_generic; - f->ixgbe_func_setup_fc = &ixgbe_setup_fc_generic; + mac->ops.set_rar = &ixgbe_set_rar_generic; + mac->ops.set_vmdq = NULL; + mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic; + mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic; + mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic; + mac->ops.enable_mc = &ixgbe_enable_mc_generic; + mac->ops.disable_mc = &ixgbe_disable_mc_generic; + mac->ops.clear_vfta = &ixgbe_clear_vfta_generic; + mac->ops.set_vfta = &ixgbe_set_vfta_generic; + + /* Flow Control */ + mac->ops.setup_fc = NULL; + + /* Link */ + mac->ops.get_link_capabilities = NULL; + mac->ops.setup_link = NULL; + mac->ops.setup_link_speed = NULL; + mac->ops.check_link = NULL; return IXGBE_SUCCESS; } /** - * ixgbe_start_hw_generic - Prepare hardware for TX/RX + * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears @@ -111,33 +134,34 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) u32 ctrl_ext; /* Set the media type */ - hw->phy.media_type = ixgbe_get_media_type(hw); + hw->phy.media_type = hw->mac.ops.get_media_type(hw); /* Set bus info */ - ixgbe_get_bus_info(hw); + hw->mac.ops.get_bus_info(hw); /* Identify the PHY */ - ixgbe_identify_phy(hw); + hw->phy.ops.identify(hw); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table */ - ixgbe_init_rx_addrs(hw); + hw->mac.ops.init_rx_addrs(hw); /* Clear the VLAN filter table */ - ixgbe_clear_vfta(hw); + hw->mac.ops.clear_vfta(hw); /* Set up link */ - ixgbe_setup_link(hw); + hw->mac.ops.setup_link(hw); /* Clear statistics registers */ - ixgbe_clear_hw_cntrs(hw); + hw->mac.ops.clear_hw_cntrs(hw); /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); + IXGBE_WRITE_FLUSH(hw); /* Clear adapter stopped flag */ hw->adapter_stopped = FALSE; @@ -149,7 +173,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) * ixgbe_init_hw_generic - Generic hardware initialization * @hw: pointer to hardware structure * - * Initialize the hardware by reseting the hardware, filling the bus info + * 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 @@ -158,10 +182,10 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) { /* Reset the hardware */ - ixgbe_reset_hw(hw); + hw->mac.ops.reset_hw(hw); /* Start the HW */ - ixgbe_start_hw(hw); + hw->mac.ops.start_hw(hw); return IXGBE_SUCCESS; } @@ -245,6 +269,37 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) } /** + * ixgbe_read_pba_num - 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. + **/ +s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) +{ + s32 ret_val; + u16 data; + + DEBUGFUNC("ixgbe_read_pba_num_generic"); + + ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + return ret_val; + } + *pba_num = (u32)(data << 16); + + ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + return ret_val; + } + *pba_num |= data; + + return IXGBE_SUCCESS; +} + +/** * ixgbe_get_mac_addr_generic - Generic get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address @@ -320,7 +375,7 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) } /** - * ixgbe_stop_adapter_generic - Generic stop TX/RX units + * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, @@ -344,6 +399,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL); reg_val &= ~(IXGBE_RXCTRL_RXEN); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); + IXGBE_WRITE_FLUSH(hw); msec_delay(2); /* Clear interrupt mask to stop from interrupts being generated */ @@ -353,7 +409,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) IXGBE_READ_REG(hw, IXGBE_EICR); /* Disable the transmit unit. Each queue must be disabled. */ - number_of_queues = ixgbe_get_num_of_tx_queues(hw); + number_of_queues = hw->mac.max_tx_queues; for (i = 0; i < number_of_queues; i++) { reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); if (reg_val & IXGBE_TXDCTL_ENABLE) { @@ -362,6 +418,14 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) } } + /* + * Prevent the PCI-E bus from from hanging by disabling PCI-E master + * access and verify no pending requests + */ + if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) { + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + } + return IXGBE_SUCCESS; } @@ -378,6 +442,7 @@ s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); + IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } @@ -395,37 +460,7 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); - - return IXGBE_SUCCESS; -} - - -/** - * ixgbe_blink_led_start_generic - Blink LED based on index. - * @hw: pointer to hardware structure - * @index: led number to blink - **/ -s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) -{ - u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); - - led_reg |= IXGBE_LED_BLINK(index); - IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); - - 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 - **/ -s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) -{ - u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); - - led_reg &= ~IXGBE_LED_BLINK(index); - IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); + IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } @@ -490,6 +525,13 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) s32 status; u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + /* Prepare the EEPROM for writing */ status = ixgbe_acquire_eeprom(hw); @@ -505,7 +547,7 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) /* Send the WRITE ENABLE command (8 bit opcode ) */ ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, - IXGBE_EEPROM_OPCODE_BITS); + IXGBE_EEPROM_OPCODE_BITS); ixgbe_standby_eeprom(hw); @@ -518,9 +560,9 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) /* Send the Write command (8-bit opcode + addr) */ ixgbe_shift_out_eeprom_bits(hw, write_opcode, - IXGBE_EEPROM_OPCODE_BITS); + IXGBE_EEPROM_OPCODE_BITS); ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), - hw->eeprom.address_bits); + hw->eeprom.address_bits); /* Send the data */ data = (data >> 8) | (data << 8); @@ -533,6 +575,7 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) ixgbe_release_eeprom(hw); } +out: return status; } @@ -545,12 +588,19 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) * Reads 16 bit value from EEPROM through bit-bang method **/ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, - u16 *data) + u16 *data) { s32 status; u16 word_in; u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + /* Prepare the EEPROM for reading */ status = ixgbe_acquire_eeprom(hw); @@ -573,9 +623,9 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, /* Send the READ command (opcode + addr) */ ixgbe_shift_out_eeprom_bits(hw, read_opcode, - IXGBE_EEPROM_OPCODE_BITS); + IXGBE_EEPROM_OPCODE_BITS); ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), - hw->eeprom.address_bits); + hw->eeprom.address_bits); /* Read the data. */ word_in = ixgbe_shift_in_eeprom_bits(hw, 16); @@ -585,6 +635,7 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, ixgbe_release_eeprom(hw); } +out: return status; } @@ -601,6 +652,13 @@ s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) u32 eerd; s32 status; + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + IXGBE_EEPROM_READ_REG_START; @@ -609,10 +667,11 @@ s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) if (status == IXGBE_SUCCESS) *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> - IXGBE_EEPROM_READ_REG_DATA); + IXGBE_EEPROM_READ_REG_DATA); else DEBUGOUT("Eeprom read timed out\n"); +out: return status; } @@ -669,7 +728,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) usec_delay(5); } - /* Release if grant not aquired */ + /* Release if grant not acquired */ if (!(eec & IXGBE_EEC_GNT)) { eec &= ~IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); @@ -747,7 +806,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) */ if (i >= timeout) { DEBUGOUT("Driver can't access the Eeprom - Semaphore " - "not granted.\n"); + "not granted.\n"); ixgbe_release_eeprom_semaphore(hw); status = IXGBE_ERR_EEPROM; } @@ -771,6 +830,7 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); + IXGBE_WRITE_FLUSH(hw); } /** @@ -791,7 +851,7 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) */ for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, - IXGBE_EEPROM_OPCODE_BITS); + IXGBE_EEPROM_OPCODE_BITS); spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) break; @@ -840,7 +900,7 @@ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) * @count: number of bits to shift out **/ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, - u16 count) + u16 count) { u32 eec; u32 mask; @@ -999,7 +1059,7 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { - if (ixgbe_read_eeprom(hw, i, &word) != IXGBE_SUCCESS) { + if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { DEBUGOUT("EEPROM read failed\n"); break; } @@ -1008,15 +1068,15 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) /* Include all data from pointers except for the fw pointer */ for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { - ixgbe_read_eeprom(hw, i, &pointer); + hw->eeprom.ops.read(hw, i, &pointer); /* Make sure the pointer seems valid */ if (pointer != 0xFFFF && pointer != 0) { - ixgbe_read_eeprom(hw, pointer, &length); + hw->eeprom.ops.read(hw, pointer, &length); if (length != 0xFFFF && length != 0) { for (j = pointer+1; j <= pointer+length; j++) { - ixgbe_read_eeprom(hw, j, &word); + hw->eeprom.ops.read(hw, j, &word); checksum += word; } } @@ -1037,7 +1097,7 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) * caller does not need checksum_val, the value can be NULL. **/ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, - u16 *checksum_val) + u16 *checksum_val) { s32 status; u16 checksum; @@ -1048,25 +1108,23 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, * not continue or we could be in for a very long wait while every * EEPROM read fails */ - status = ixgbe_read_eeprom(hw, 0, &checksum); + status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == IXGBE_SUCCESS) { checksum = ixgbe_calc_eeprom_checksum(hw); - ixgbe_read_eeprom(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); + hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); /* * Verify read checksum from EEPROM is the same as * calculated checksum */ - if (read_checksum != checksum) { + if (read_checksum != checksum) status = IXGBE_ERR_EEPROM_CHECKSUM; - } /* If the user cares, return the calculated checksum */ - if (checksum_val) { + if (checksum_val) *checksum_val = checksum; - } } else { DEBUGOUT("EEPROM read failed\n"); } @@ -1075,7 +1133,7 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, } /** - * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksm + * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum * @hw: pointer to hardware structure **/ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) @@ -1088,12 +1146,12 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) * not continue or we could be in for a very long wait while every * EEPROM read fails */ - status = ixgbe_read_eeprom(hw, 0, &checksum); + status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == IXGBE_SUCCESS) { checksum = ixgbe_calc_eeprom_checksum(hw); - status = ixgbe_write_eeprom(hw, IXGBE_EEPROM_CHECKSUM, - checksum); + status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, + checksum); } else { DEBUGOUT("EEPROM read failed\n"); } @@ -1121,7 +1179,7 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr) status = IXGBE_ERR_INVALID_MAC_ADDR; /* Reject the zero address */ } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && - mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { + mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { DEBUGOUT("MAC address is all zeros\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; } @@ -1129,44 +1187,57 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr) } /** - * ixgbe_set_rar_generic - Set RX address register + * ixgbe_set_rar_generic - Set Rx address register * @hw: pointer to hardware structure - * @addr: Address to put into receive address register * @index: Receive address register to write - * @vind: Vind to set RAR to + * @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. **/ -s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind, - u32 enable_addr) +s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr) { u32 rar_low, rar_high; + u32 rar_entries = hw->mac.num_rar_entries; - /* - * HW expects these in little endian so we reverse the byte order from - * network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | - ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | - ((u32)addr[3] << 24)); + /* setup VMDq pool selection before this RAR gets enabled */ + hw->mac.ops.set_vmdq(hw, index, vmdq); - rar_high = ((u32)addr[4] | - ((u32)addr[5] << 8) | - ((vind << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK)); + /* 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 + */ + rar_low = ((u32)addr[0] | + ((u32)addr[1] << 8) | + ((u32)addr[2] << 16) | + ((u32)addr[3] << 24)); + /* + * 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. + */ + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); + rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); + rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); - if (enable_addr != 0) - rar_high |= IXGBE_RAH_AV; + if (enable_addr != 0) + rar_high |= IXGBE_RAH_AV; - IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); - IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + } else { + DEBUGOUT("Current RAR index is out of range."); + } return IXGBE_SUCCESS; } /** - * ixgbe_enable_rar - Enable RX address register + * ixgbe_enable_rar - Enable Rx address register * @hw: pointer to hardware structure * @index: index into the RAR table * @@ -1182,7 +1253,7 @@ static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index) } /** - * ixgbe_disable_rar - Disable RX address register + * ixgbe_disable_rar - Disable Rx address register * @hw: pointer to hardware structure * @index: index into the RAR table * @@ -1202,13 +1273,13 @@ static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index) * @hw: pointer to hardware structure * * Places the MAC address in receive address register 0 and clears the rest - * of the receive addresss registers. Clears the multicast table. Assumes + * of the receive address registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. **/ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) { u32 i; - u32 rar_entries = ixgbe_get_num_rx_addrs(hw); + u32 rar_entries = hw->mac.num_rar_entries; /* * If the current mac address is valid, assume it is a software override @@ -1218,29 +1289,30 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) if (ixgbe_validate_mac_addr(hw->mac.addr) == IXGBE_ERR_INVALID_MAC_ADDR) { /* Get the MAC address from the RAR0 for later reference */ - ixgbe_get_mac_addr(hw, hw->mac.addr); + hw->mac.ops.get_mac_addr(hw, hw->mac.addr); DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", - hw->mac.addr[0], hw->mac.addr[1], - hw->mac.addr[2]); + hw->mac.addr[0], hw->mac.addr[1], + hw->mac.addr[2]); DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], - hw->mac.addr[4], hw->mac.addr[5]); + hw->mac.addr[4], hw->mac.addr[5]); } else { /* Setup the receive address. */ DEBUGOUT("Overriding MAC Address in RAR[0]\n"); DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", - hw->mac.addr[0], hw->mac.addr[1], - hw->mac.addr[2]); + hw->mac.addr[0], hw->mac.addr[1], + hw->mac.addr[2]); DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], - hw->mac.addr[4], hw->mac.addr[5]); + hw->mac.addr[4], hw->mac.addr[5]); - ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); } + hw->addr_ctrl.overflow_promisc = 0; hw->addr_ctrl.rar_used_count = 1; /* Zero out the other receive addresses. */ - DEBUGOUT("Clearing RAR[1-15]\n"); + DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); for (i = 1; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); @@ -1252,13 +1324,114 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); DEBUGOUT(" Clearing MTA\n"); - for (i = 0; i < IXGBE_MC_TBL_SIZE; i++) + for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 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 ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) +{ + u32 rar_entries = hw->mac.num_rar_entries; + u32 rar; + + DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + /* + * Place this address in the RAR if there is room, + * else put the controller into promiscuous mode + */ + if (hw->addr_ctrl.rar_used_count < rar_entries) { + rar = hw->addr_ctrl.rar_used_count - + hw->addr_ctrl.mc_addr_in_rar_count; + hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); + DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); + hw->addr_ctrl.rar_used_count++; + } else { + hw->addr_ctrl.overflow_promisc++; + } + + 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. + **/ +s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, + u32 addr_count, ixgbe_mc_addr_itr next) +{ + u8 *addr; + u32 i; + u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; + u32 uc_addr_in_use; + u32 fctrl; + u32 vmdq; + + /* + * Clear accounting of old secondary address list, + * don't count RAR[0] + */ + uc_addr_in_use = hw->addr_ctrl.rar_used_count - + hw->addr_ctrl.mc_addr_in_rar_count - 1; + hw->addr_ctrl.rar_used_count -= uc_addr_in_use; + hw->addr_ctrl.overflow_promisc = 0; + + /* Zero out the other receive addresses */ + DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use); + for (i = 1; i <= uc_addr_in_use; i++) { + IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); + IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); + } + + /* Add the new addresses */ + for (i = 0; i < addr_count; i++) { + DEBUGOUT(" Adding the secondary addresses:\n"); + addr = next(hw, &addr_list, &vmdq); + ixgbe_add_uc_addr(hw, addr, vmdq); + } + + if (hw->addr_ctrl.overflow_promisc) { + /* enable promisc if not already in overflow or set by user */ + if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { + DEBUGOUT( " Entering address overflow promisc mode\n"); + fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + fctrl |= IXGBE_FCTRL_UPE; + IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); + } + } else { + /* only disable if set by overflow, not by user */ + if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { + DEBUGOUT(" Leaving address overflow promisc mode\n"); + fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + fctrl &= ~IXGBE_FCTRL_UPE; + IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); + } + } + + 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 @@ -1267,7 +1440,7 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) * 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 initalization + * by the MO field of the MCSTCTRL. The MO field is set during initialization * to mc_filter_type. **/ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) @@ -1275,19 +1448,19 @@ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) u32 vector = 0; switch (hw->mac.mc_filter_type) { - case 0: /* use bits [47:36] of the address */ + case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); break; - case 1: /* use bits [46:35] of the address */ + case 1: /* use bits [46:35] of the address */ vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); break; - case 2: /* use bits [45:34] of the address */ + case 2: /* use bits [45:34] of the address */ vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); break; - case 3: /* use bits [43:32] of the address */ + case 3: /* use bits [43:32] of the address */ vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); break; - default: /* Invalid mc_filter_type */ + default: /* Invalid mc_filter_type */ DEBUGOUT("MC filter type param set incorrectly\n"); ASSERT(0); break; @@ -1342,21 +1515,22 @@ void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) **/ void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) { - u32 rar_entries = ixgbe_get_num_rx_addrs(hw); + u32 rar_entries = hw->mac.num_rar_entries; + u32 rar; DEBUGOUT6(" MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", - mc_addr[0], mc_addr[1], mc_addr[2], - mc_addr[3], mc_addr[4], mc_addr[5]); + mc_addr[0], mc_addr[1], mc_addr[2], + mc_addr[3], mc_addr[4], mc_addr[5]); /* * Place this multicast address in the RAR if there is room, * else put it in the MTA */ if (hw->addr_ctrl.rar_used_count < rar_entries) { - ixgbe_set_rar(hw, hw->addr_ctrl.rar_used_count, - mc_addr, 0, IXGBE_RAH_AV); - DEBUGOUT1("Added a multicast address to RAR[%d]\n", - hw->addr_ctrl.rar_used_count); + /* use RAR from the end up for multicast */ + rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; + hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); + DEBUGOUT1("Added a multicast address to RAR[%d]\n", rar); hw->addr_ctrl.rar_used_count++; hw->addr_ctrl.mc_addr_in_rar_count++; } else { @@ -1371,18 +1545,19 @@ void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses - * @pad: number of bytes between addresses in the list + * @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 unsed receive address + * address registers and the multicast table. Uses unused receive address * registers for the first multicast addresses, and hashes the rest into the * multicast table. **/ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count, u32 pad) + u32 mc_addr_count, ixgbe_mc_addr_itr next) { u32 i; - u32 rar_entries = ixgbe_get_num_rx_addrs(hw); + u32 rar_entries = hw->mac.num_rar_entries; + u32 vmdq; /* * Set the new number of MC addresses that we are being requested to @@ -1394,7 +1569,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, hw->addr_ctrl.mta_in_use = 0; /* Zero out the other receive addresses. */ - DEBUGOUT("Clearing RAR[1-15]\n"); + DEBUGOUT2("Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count, + rar_entries - 1); for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); @@ -1402,20 +1578,19 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, /* Clear the MTA */ DEBUGOUT(" Clearing MTA\n"); - for (i = 0; i < IXGBE_MC_TBL_SIZE; i++) + for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); /* Add the new addresses */ for (i = 0; i < mc_addr_count; i++) { DEBUGOUT(" Adding the multicast addresses:\n"); - ixgbe_add_mc_addr(hw, mc_addr_list + - (i * (IXGBE_ETH_LENGTH_OF_ADDRESS + pad))); + ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq)); } /* Enable mta */ if (hw->addr_ctrl.mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, - IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); + IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); return IXGBE_SUCCESS; @@ -1430,22 +1605,23 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) { u32 i; + u32 rar_entries = hw->mac.num_rar_entries; struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; if (a->mc_addr_in_rar_count > 0) - for (i = (a->rar_used_count - a->mc_addr_in_rar_count); - i < a->rar_used_count; i++) + for (i = (rar_entries - a->mc_addr_in_rar_count); + i < rar_entries; i++) ixgbe_enable_rar(hw, i); if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | - hw->mac.mc_filter_type); + hw->mac.mc_filter_type); return IXGBE_SUCCESS; } /** - * ixgbe_disable_mc_generic - Disable mutlicast address in RAR + * 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. @@ -1453,11 +1629,12 @@ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) { u32 i; + u32 rar_entries = hw->mac.num_rar_entries; struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; if (a->mc_addr_in_rar_count > 0) - for (i = (a->rar_used_count - a->mc_addr_in_rar_count); - i < a->rar_used_count; i++) + for (i = (rar_entries - a->mc_addr_in_rar_count); + i < rar_entries; i++) ixgbe_disable_rar(hw, i); if (a->mta_in_use > 0) @@ -1477,13 +1654,13 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) u32 offset; u32 vlanbyte; - for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++) + for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) - for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++) + for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), - 0); + 0); return IXGBE_SUCCESS; } @@ -1498,7 +1675,7 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, - bool vlan_on) + bool vlan_on) { u32 VftaIndex; u32 BitOffset; @@ -1519,7 +1696,7 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg); /* Determine the location of the bit for this VLAN id */ - BitOffset = vlan & 0x1F; /* lower five bits */ + BitOffset = vlan & 0x1F; /* lower five bits */ VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex)); if (vlan_on) @@ -1534,107 +1711,6 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, } /** - * ixgbe_setup_fc_generic - Configure flow control settings - * @hw: pointer to hardware structure - * @packetbuf_num: packet buffer number (0-7) - * - * Configures the flow control settings based on SW configuration. - * This function is used for 802.3x flow control configuration only. - **/ -s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num) -{ - u32 frctl_reg; - u32 rmcs_reg; - - if (packetbuf_num < 0 || packetbuf_num > 7) { - DEBUGOUT1("Invalid packet buffer number [%d], expected range is" - " 0-7\n", packetbuf_num); - ASSERT(0); - } - - frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); - frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); - - rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); - rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); - - /* - * 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.type = hw->fc.original_type; - - /* - * The possible values of the "flow_control" parameter 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. - */ - switch (hw->fc.type) { - case ixgbe_fc_none: - break; - case ixgbe_fc_rx_pause: - /* - * RX Flow control is enabled, - * and TX Flow control is disabled. - */ - frctl_reg |= IXGBE_FCTRL_RFCE; - break; - case ixgbe_fc_tx_pause: - /* - * TX Flow control is enabled, and RX Flow control is disabled, - * by a software over-ride. - */ - rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; - break; - case ixgbe_fc_full: - /* - * Flow control (both RX and TX) is enabled by a software - * over-ride. - */ - frctl_reg |= IXGBE_FCTRL_RFCE; - rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; - break; - default: - /* We should never get here. The value should be 0-3. */ - DEBUGOUT("Flow control param set incorrectly\n"); - ASSERT(0); - break; - } - - /* Enable 802.3x based flow control settings. */ - IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg); - IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); - - /* - * We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - if (hw->fc.type & ixgbe_fc_tx_pause) { - if (hw->fc.send_xon) { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - (hw->fc.low_water | IXGBE_FCRTL_XONE)); - } else { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - hw->fc.low_water); - } - IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), - (hw->fc.high_water)|IXGBE_FCRTH_FCEN); - } - - IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time); - IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); - - return IXGBE_SUCCESS; -} - -/** * ixgbe_disable_pcie_master - Disable PCI-express master access * @hw: pointer to hardware structure * @@ -1666,11 +1742,11 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) /** - * ixgbe_acquire_swfw_sync - Aquire SWFW semaphore + * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore * @hw: pointer to hardware structure - * @mask: Mask to specify wich semaphore to acquire + * @mask: Mask to specify which semaphore to acquire * - * Aquires the SWFW semaphore throught the GSSR register for the specified + * Acquires the SWFW semaphore thought the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) @@ -1712,9 +1788,9 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) /** * ixgbe_release_swfw_sync - Release SWFW semaphore * @hw: pointer to hardware structure - * @mask: Mask to specify wich semaphore to release + * @mask: Mask to specify which semaphore to release * - * Releases the SWFW semaphore throught the GSSR register for the specified + * Releases the SWFW semaphore thought the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) @@ -1731,3 +1807,44 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) ixgbe_release_eeprom_semaphore(hw); } +/** + * ixgbe_read_analog_reg8_generic - Reads 8 bit Atlas analog register + * @hw: pointer to hardware structure + * @reg: analog register to read + * @val: read value + * + * Performs read operation to Atlas analog register specified. + **/ +s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val) +{ + u32 atlas_ctl; + + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); + IXGBE_WRITE_FLUSH(hw); + usec_delay(10); + atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); + *val = (u8)atlas_ctl; + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_write_analog_reg8_generic - Writes 8 bit Atlas analog register + * @hw: pointer to hardware structure + * @reg: atlas register to write + * @val: value to write + * + * Performs write operation to Atlas analog register specified. + **/ +s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val) +{ + u32 atlas_ctl; + + atlas_ctl = (reg << 8) | val; + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); + IXGBE_WRITE_FLUSH(hw); + usec_delay(10); + + return IXGBE_SUCCESS; +} + |