Print this page
Import some changes from FreeBSD (details later, this is quick-n-dirty for now).
        
*** 1,8 ****
  /******************************************************************************
  
!   Copyright (c) 2001-2012, Intel Corporation 
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without 
    modification, are permitted provided that the following conditions are met:
    
--- 1,8 ----
  /******************************************************************************
  
!   Copyright (c) 2001-2013, Intel Corporation 
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without 
    modification, are permitted provided that the following conditions are met:
    
*** 145,165 ****
   *
   *  There are several phys that do not support autoneg flow control. This
   *  function check the device id to see if the associated phy supports
   *  autoneg flow control.
   **/
! static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
  {
  
          DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
  
          switch (hw->device_id) {
          case IXGBE_DEV_ID_X540T:
-         case IXGBE_DEV_ID_X540T1:
                  return IXGBE_SUCCESS;
-         case IXGBE_DEV_ID_82599_T3_LOM:
-                 return IXGBE_SUCCESS;
          default:
                  return IXGBE_ERR_FC_NOT_SUPPORTED;
          }
  }
  
--- 145,163 ----
   *
   *  There are several phys that do not support autoneg flow control. This
   *  function check the device id to see if the associated phy supports
   *  autoneg flow control.
   **/
! s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
  {
  
          DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
  
          switch (hw->device_id) {
+         case IXGBE_DEV_ID_82599_T3_LOM:
          case IXGBE_DEV_ID_X540T:
                  return IXGBE_SUCCESS;
          default:
                  return IXGBE_ERR_FC_NOT_SUPPORTED;
          }
  }
  
*** 172,181 ****
--- 170,180 ----
  static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
  {
          s32 ret_val = IXGBE_SUCCESS;
          u32 reg = 0, reg_bp = 0;
          u16 reg_cu = 0;
+         bool got_lock = FALSE;
  
          DEBUGFUNC("ixgbe_setup_fc");
  
          /*
           * Validate the requested mode.  Strict IEEE mode does not allow
*** 198,207 ****
--- 197,207 ----
           * Set up the 1G and 10G flow control advertisement registers so the
           * HW will be able to do fc autoneg once the cable is plugged in.  If
           * we link at 10G, the 1G advertisement is harmless and vice versa.
           */
          switch (hw->phy.media_type) {
+         case ixgbe_media_type_fiber_fixed:
          case ixgbe_media_type_fiber:
          case ixgbe_media_type_backplane:
                  reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
                  reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
                  break;
*** 294,304 ****
--- 294,325 ----
           * and copper. There is no need to set the PCS1GCTL register.
           *
           */
          if (hw->phy.media_type == ixgbe_media_type_backplane) {
                  reg_bp |= IXGBE_AUTOC_AN_RESTART;
+                 /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+                  * LESM is on, likewise reset_pipeline requries the lock as
+                  * it also writes AUTOC.
+                  */
+                 if ((hw->mac.type == ixgbe_mac_82599EB) &&
+                     ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                         ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                                         IXGBE_GSSR_MAC_CSR_SM);
+                         if (ret_val != IXGBE_SUCCESS) {
+                                 ret_val = IXGBE_ERR_SWFW_SYNC;
+                                 goto out;
+                         }
+                         got_lock = TRUE;
+                 }
+ 
                  IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+                 if (hw->mac.type == ixgbe_mac_82599EB)
+                         (void) ixgbe_reset_pipeline_82599(hw);
+ 
+                 if (got_lock)
+                         hw->mac.ops.release_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
          } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
                      (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
                  hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
                                        IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
          }
*** 677,686 ****
--- 698,896 ----
  
          return IXGBE_SUCCESS;
  }
  
  /**
+  *  ixgbe_read_pba_raw
+  *  @hw: pointer to the HW structure
+  *  @eeprom_buf: optional pointer to EEPROM image
+  *  @eeprom_buf_size: size of EEPROM image in words
+  *  @max_pba_block_size: PBA block size limit
+  *  @pba: pointer to output PBA structure
+  *
+  *  Reads PBA from EEPROM image when eeprom_buf is not NULL.
+  *  Reads PBA from physical EEPROM device when eeprom_buf is NULL.
+  *
+  **/
+ s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf,
+                        u32 eeprom_buf_size, u16 max_pba_block_size,
+                        struct ixgbe_pba *pba)
+ {
+         s32 ret_val;
+         u16 pba_block_size;
+ 
+         if (pba == NULL)
+                 return IXGBE_ERR_PARAM;
+ 
+         if (eeprom_buf == NULL) {
+                 ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2,
+                                                      &pba->word[0]);
+                 if (ret_val)
+                         return ret_val;
+         } else {
+                 if (eeprom_buf_size > IXGBE_PBANUM1_PTR) {
+                         pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR];
+                         pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR];
+                 } else {
+                         return IXGBE_ERR_PARAM;
+                 }
+         }
+ 
+         if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) {
+                 if (pba->pba_block == NULL)
+                         return IXGBE_ERR_PARAM;
+ 
+                 ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf,
+                                                    eeprom_buf_size,
+                                                    &pba_block_size);
+                 if (ret_val)
+                         return ret_val;
+ 
+                 if (pba_block_size > max_pba_block_size)
+                         return IXGBE_ERR_PARAM;
+ 
+                 if (eeprom_buf == NULL) {
+                         ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1],
+                                                              pba_block_size,
+                                                              pba->pba_block);
+                         if (ret_val)
+                                 return ret_val;
+                 } else {
+                         if (eeprom_buf_size > (u32)(pba->word[1] +
+                                               pba->pba_block[0])) {
+                                 (void) memcpy(pba->pba_block,
+                                        &eeprom_buf[pba->word[1]],
+                                        pba_block_size * sizeof(u16));
+                         } else {
+                                 return IXGBE_ERR_PARAM;
+                         }
+                 }
+         }
+ 
+         return IXGBE_SUCCESS;
+ }
+ 
+ /**
+  *  ixgbe_write_pba_raw
+  *  @hw: pointer to the HW structure
+  *  @eeprom_buf: optional pointer to EEPROM image
+  *  @eeprom_buf_size: size of EEPROM image in words
+  *  @pba: pointer to PBA structure
+  *
+  *  Writes PBA to EEPROM image when eeprom_buf is not NULL.
+  *  Writes PBA to physical EEPROM device when eeprom_buf is NULL.
+  *
+  **/
+ s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf,
+                         u32 eeprom_buf_size, struct ixgbe_pba *pba)
+ {
+         s32 ret_val;
+ 
+         if (pba == NULL)
+                 return IXGBE_ERR_PARAM;
+ 
+         if (eeprom_buf == NULL) {
+                 ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2,
+                                                       &pba->word[0]);
+                 if (ret_val)
+                         return ret_val;
+         } else {
+                 if (eeprom_buf_size > IXGBE_PBANUM1_PTR) {
+                         eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0];
+                         eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1];
+                 } else {
+                         return IXGBE_ERR_PARAM;
+                 }
+         }
+ 
+         if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) {
+                 if (pba->pba_block == NULL)
+                         return IXGBE_ERR_PARAM;
+ 
+                 if (eeprom_buf == NULL) {
+                         ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1],
+                                                               pba->pba_block[0],
+                                                               pba->pba_block);
+                         if (ret_val)
+                                 return ret_val;
+                 } else {
+                         if (eeprom_buf_size > (u32)(pba->word[1] +
+                                               pba->pba_block[0])) {
+                                 (void) memcpy(&eeprom_buf[pba->word[1]],
+                                        pba->pba_block,
+                                        pba->pba_block[0] * sizeof(u16));
+                         } else {
+                                 return IXGBE_ERR_PARAM;
+                         }
+                 }
+         }
+ 
+         return IXGBE_SUCCESS;
+ }
+ 
+ /**
+  *  ixgbe_get_pba_block_size
+  *  @hw: pointer to the HW structure
+  *  @eeprom_buf: optional pointer to EEPROM image
+  *  @eeprom_buf_size: size of EEPROM image in words
+  *  @pba_data_size: pointer to output variable
+  *
+  *  Returns the size of the PBA block in words. Function operates on EEPROM
+  *  image if the eeprom_buf pointer is not NULL otherwise it accesses physical
+  *  EEPROM device.
+  *
+  **/
+ s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf,
+                              u32 eeprom_buf_size, u16 *pba_block_size)
+ {
+         s32 ret_val;
+         u16 pba_word[2];
+         u16 length;
+ 
+         DEBUGFUNC("ixgbe_get_pba_block_size");
+ 
+         if (eeprom_buf == NULL) {
+                 ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2,
+                                                      &pba_word[0]);
+                 if (ret_val)
+                         return ret_val;
+         } else {
+                 if (eeprom_buf_size > IXGBE_PBANUM1_PTR) {
+                         pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR];
+                         pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR];
+                 } else {
+                         return IXGBE_ERR_PARAM;
+                 }
+         }
+ 
+         if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) {
+                 if (eeprom_buf == NULL) {
+                         ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0,
+                                                       &length);
+                         if (ret_val)
+                                 return ret_val;
+                 } else {
+                         if (eeprom_buf_size > pba_word[1])
+                                 length = eeprom_buf[pba_word[1] + 0];
+                         else
+                                 return IXGBE_ERR_PARAM;
+                 }
+ 
+                 if (length == 0xFFFF || length == 0)
+                         return IXGBE_ERR_PBA_SECTION;
+         } else {
+                 /* PBA number in legacy format, there is no PBA Block. */
+                 length = 0;
+         }
+ 
+         if (pba_block_size != NULL)
+                 *pba_block_size = length;
+ 
+         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)
*** 1267,1277 ****
                  status = IXGBE_ERR_EEPROM;
                  goto out;
          }
  
          for (i = 0; i < words; i++) {
!                 eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) +
                         IXGBE_EEPROM_RW_REG_START;
  
                  IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
                  status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
  
--- 1477,1487 ----
                  status = IXGBE_ERR_EEPROM;
                  goto out;
          }
  
          for (i = 0; i < words; i++) {
!                 eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
                         IXGBE_EEPROM_RW_REG_START;
  
                  IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
                  status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
  
*** 2717,2726 ****
--- 2927,2937 ----
          if (!link_up)
                  goto out;
  
          switch (hw->phy.media_type) {
          /* Autoneg flow control on fiber adapters */
+         case ixgbe_media_type_fiber_fixed:
          case ixgbe_media_type_fiber:
                  if (speed == IXGBE_LINK_SPEED_1GB_FULL)
                          ret_val = ixgbe_fc_autoneg_fiber(hw);
                  break;
  
*** 2963,2972 ****
--- 3174,3184 ----
  {
          ixgbe_link_speed speed = 0;
          bool link_up = 0;
          u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
          u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+         s32 ret_val = IXGBE_SUCCESS;
  
          DEBUGFUNC("ixgbe_blink_led_start_generic");
  
          /*
           * Link must be up to auto-blink the LEDs;
*** 2973,2995 ****
           * Force it if link is down.
           */
          hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
  
          if (!link_up) {
                  autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                  autoc_reg |= IXGBE_AUTOC_FLU;
                  IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
                  IXGBE_WRITE_FLUSH(hw);
                  msec_delay(10);
          }
  
          led_reg &= ~IXGBE_LED_MODE_MASK(index);
          led_reg |= IXGBE_LED_BLINK(index);
          IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
          IXGBE_WRITE_FLUSH(hw);
  
!         return IXGBE_SUCCESS;
  }
  
  /**
   *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
   *  @hw: pointer to hardware structure
--- 3185,3227 ----
           * Force it if link is down.
           */
          hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
  
          if (!link_up) {
+                 /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+                  * LESM is on.
+                  */
+                 bool got_lock = FALSE;
+                 if ((hw->mac.type == ixgbe_mac_82599EB) &&
+                     ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                         ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                                         IXGBE_GSSR_MAC_CSR_SM);
+                         if (ret_val != IXGBE_SUCCESS) {
+                                 ret_val = IXGBE_ERR_SWFW_SYNC;
+                                 goto out;
+                         }
+                         got_lock = TRUE;
+                 }
+ 
                  autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                  autoc_reg |= IXGBE_AUTOC_FLU;
                  IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
                  IXGBE_WRITE_FLUSH(hw);
+ 
+                 if (got_lock)
+                         hw->mac.ops.release_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
                  msec_delay(10);
          }
  
          led_reg &= ~IXGBE_LED_MODE_MASK(index);
          led_reg |= IXGBE_LED_BLINK(index);
          IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
          IXGBE_WRITE_FLUSH(hw);
  
! out:
!         return ret_val;
  }
  
  /**
   *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
   *  @hw: pointer to hardware structure
*** 2997,3021 ****
   **/
  s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
  {
          u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
          u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
  
          DEBUGFUNC("ixgbe_blink_led_stop_generic");
  
  
          autoc_reg &= ~IXGBE_AUTOC_FLU;
          autoc_reg |= IXGBE_AUTOC_AN_RESTART;
          IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
  
          led_reg &= ~IXGBE_LED_MODE_MASK(index);
          led_reg &= ~IXGBE_LED_BLINK(index);
          led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
          IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
          IXGBE_WRITE_FLUSH(hw);
  
!         return IXGBE_SUCCESS;
  }
  
  /**
   *  ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
   *  @hw: pointer to hardware structure
--- 3229,3275 ----
   **/
  s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
  {
          u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
          u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+         s32 ret_val = IXGBE_SUCCESS;
+         bool got_lock = FALSE;
  
          DEBUGFUNC("ixgbe_blink_led_stop_generic");
+         /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+          * LESM is on.
+          */
+         if ((hw->mac.type == ixgbe_mac_82599EB) &&
+             ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                 ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                                 IXGBE_GSSR_MAC_CSR_SM);
+                 if (ret_val != IXGBE_SUCCESS) {
+                         ret_val = IXGBE_ERR_SWFW_SYNC;
+                         goto out;
+                 }
+                 got_lock = TRUE;
+         }
  
  
          autoc_reg &= ~IXGBE_AUTOC_FLU;
          autoc_reg |= IXGBE_AUTOC_AN_RESTART;
          IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
  
+         if (hw->mac.type == ixgbe_mac_82599EB)
+                 (void) ixgbe_reset_pipeline_82599(hw);
+ 
+         if (got_lock)
+                 hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+ 
          led_reg &= ~IXGBE_LED_MODE_MASK(index);
          led_reg &= ~IXGBE_LED_BLINK(index);
          led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
          IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
          IXGBE_WRITE_FLUSH(hw);
  
! out:
!         return ret_val;
  }
  
  /**
   *  ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
   *  @hw: pointer to hardware structure
*** 3880,3890 ****
   *  @buffer: pointer to EEPROM
   *  @length: size of EEPROM to calculate a checksum for
   *  Calculates the checksum for some buffer on a specified length.  The
   *  checksum calculated is returned.
   **/
! static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
  {
          u32 i;
          u8 sum = 0;
  
          DEBUGFUNC("ixgbe_calculate_checksum");
--- 4134,4144 ----
   *  @buffer: pointer to EEPROM
   *  @length: size of EEPROM to calculate a checksum for
   *  Calculates the checksum for some buffer on a specified length.  The
   *  checksum calculated is returned.
   **/
! u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
  {
          u32 i;
          u8 sum = 0;
  
          DEBUGFUNC("ixgbe_calculate_checksum");
*** 3906,3916 ****
   *  @length: length of buffer, must be multiple of 4 bytes
   *
   *  Communicates with the manageability block.  On success return IXGBE_SUCCESS
   *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
   **/
! static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                                          u32 length)
  {
          u32 hicr, i, bi;
          u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
          u8 buf_len, dword_len;
--- 4160,4170 ----
   *  @length: length of buffer, must be multiple of 4 bytes
   *
   *  Communicates with the manageability block.  On success return IXGBE_SUCCESS
   *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
   **/
! s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                                   u32 length)
  {
          u32 hicr, i, bi;
          u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
          u8 buf_len, dword_len;