Author: erj
Date: Thu May 12 18:19:53 2016
New Revision: 299547
URL: https://svnweb.freebsd.org/changeset/base/299547

Log:
  ixl: Update to 1.4.7-k.
  
  Changes by author:
  
  Helin Zhang           i40e_shared: Fix compilation error - pointer-arith
  Paul M Stillwell Jr   i40e-shared: Replace sprintf with i40e_debug
  Anjali Singhai Jain   i40e-shared: Fix an accidental error with BIT_ULL 
replacement
  Jesse Brandeburg      i40e-shared: remove useless assignments
  Anjali Singhai Jain   i40e-shared: Add a workaround to drop all flow control 
frames
  Anjali Singhai Jain   i40e-shared: Add new response struct from FW for AQ 
command i40e_aqc_lldp_set_local_mib
  Anjali Singhai Jain   i40e-shared: Acquire NVM, before issuing an AQ read nvm 
command
  Eric Joyner           ixl/ixlv: Remove unused MAX_LOOP define.
  Eric Joyner           ixl: Remove extra aq_get_link_info() call in attach().
  Eric Joyner           ixl: Modify a couple error messages in attach() to be 
more informative.
  Eric Joyner           ixl: Add i40e_get_link_status() call to init_locked().
  Eric Joyner           ixl: Move callout_stop() to earlier in ixl_stop().
  Eric Joyner           ixl: Add extra comments around link ITR code.
  Eric Joyner           ixl: Attempt to enhance link event handling.
  Eric Joyner           ixl: Style, spacing, and comment changes.
  Eric Joyner           ixl: Add I40E_NVM_ACCESS definition.
  Eric Joyner           ixl: Add interface for nvmupdate tool ioctl to driver.
  Eric Joyner           ixl: Don't strip out nvm update support from the driver 
anymore.
  Eric Joyner           ixl: Interrupts are now allocated/setup and torn 
down/released on init()/stop().
  
  Differential Revision:  https://reviews.freebsd.org/D6211
  Reviewed by:    sbruno, kmacy, jeffrey.e.pie...@intel.com
  MFC after:      2 weeks
  Sponsored by:   Intel Corporation

Modified:
  head/sys/dev/ixl/i40e_adminq.h
  head/sys/dev/ixl/i40e_adminq_cmd.h
  head/sys/dev/ixl/i40e_common.c
  head/sys/dev/ixl/i40e_nvm.c
  head/sys/dev/ixl/i40e_prototype.h
  head/sys/dev/ixl/i40e_type.h
  head/sys/dev/ixl/if_ixl.c
  head/sys/dev/ixl/ixl.h
  head/sys/dev/ixl/ixl_pf.h

Modified: head/sys/dev/ixl/i40e_adminq.h
==============================================================================
--- head/sys/dev/ixl/i40e_adminq.h      Thu May 12 18:19:31 2016        
(r299546)
+++ head/sys/dev/ixl/i40e_adminq.h      Thu May 12 18:19:53 2016        
(r299547)
@@ -115,6 +115,49 @@ struct i40e_adminq_info {
        enum i40e_admin_queue_err arq_last_status;
 };
 
+/**
+ * i40e_aq_rc_to_posix - convert errors to user-land codes
+ * aq_ret: AdminQ handler error code can override aq_rc
+ * aq_rc: AdminQ firmware error code to convert
+ **/
+static INLINE int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
+{
+       int aq_to_posix[] = {
+               0,           /* I40E_AQ_RC_OK */
+               -EPERM,      /* I40E_AQ_RC_EPERM */
+               -ENOENT,     /* I40E_AQ_RC_ENOENT */
+               -ESRCH,      /* I40E_AQ_RC_ESRCH */
+               -EINTR,      /* I40E_AQ_RC_EINTR */
+               -EIO,        /* I40E_AQ_RC_EIO */
+               -ENXIO,      /* I40E_AQ_RC_ENXIO */
+               -E2BIG,      /* I40E_AQ_RC_E2BIG */
+               -EAGAIN,     /* I40E_AQ_RC_EAGAIN */
+               -ENOMEM,     /* I40E_AQ_RC_ENOMEM */
+               -EACCES,     /* I40E_AQ_RC_EACCES */
+               -EFAULT,     /* I40E_AQ_RC_EFAULT */
+               -EBUSY,      /* I40E_AQ_RC_EBUSY */
+               -EEXIST,     /* I40E_AQ_RC_EEXIST */
+               -EINVAL,     /* I40E_AQ_RC_EINVAL */
+               -ENOTTY,     /* I40E_AQ_RC_ENOTTY */
+               -ENOSPC,     /* I40E_AQ_RC_ENOSPC */
+               -ENOSYS,     /* I40E_AQ_RC_ENOSYS */
+               -ERANGE,     /* I40E_AQ_RC_ERANGE */
+               -EPIPE,      /* I40E_AQ_RC_EFLUSHED */
+               -ESPIPE,     /* I40E_AQ_RC_BAD_ADDR */
+               -EROFS,      /* I40E_AQ_RC_EMODE */
+               -EFBIG,      /* I40E_AQ_RC_EFBIG */
+       };
+
+       /* aq_rc is invalid if AQ timed out */
+       if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
+               return -EAGAIN;
+
+       if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
+               return -ERANGE;
+
+       return aq_to_posix[aq_rc];
+}
+
 /* general information */
 #define I40E_AQ_LARGE_BUF              512
 #define I40E_ASQ_CMD_TIMEOUT           250  /* msecs */

Modified: head/sys/dev/ixl/i40e_adminq_cmd.h
==============================================================================
--- head/sys/dev/ixl/i40e_adminq_cmd.h  Thu May 12 18:19:31 2016        
(r299546)
+++ head/sys/dev/ixl/i40e_adminq_cmd.h  Thu May 12 18:19:53 2016        
(r299547)
@@ -2158,6 +2158,14 @@ struct i40e_aqc_lldp_set_local_mib {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_set_local_mib);
 
+struct i40e_aqc_lldp_set_local_mib_resp {
+#define SET_LOCAL_MIB_RESP_EVENT_TRIGGERED_MASK      0x01
+       u8  status;
+       u8  reserved[15];
+};
+
+I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_lldp_set_local_mib_resp);
+
 /*     Stop/Start LLDP Agent (direct 0x0A09)
  *     Used for stopping/starting specific LLDP agent. e.g. DCBx
  */
@@ -2371,4 +2379,4 @@ struct i40e_aqc_debug_modify_internals {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_internals);
 
-#endif
+#endif /* _I40E_ADMINQ_CMD_H_ */

Modified: head/sys/dev/ixl/i40e_common.c
==============================================================================
--- head/sys/dev/ixl/i40e_common.c      Thu May 12 18:19:31 2016        
(r299546)
+++ head/sys/dev/ixl/i40e_common.c      Thu May 12 18:19:53 2016        
(r299547)
@@ -4906,6 +4906,28 @@ enum i40e_status_code i40e_aq_add_rem_co
 }
 
 /**
+ * i40e_add_filter_to_drop_tx_flow_control_frames- filter to drop flow control
+ * @hw: pointer to the hw struct
+ * @seid: VSI seid to add ethertype filter from
+ **/
+#define I40E_FLOW_CONTROL_ETHTYPE 0x8808
+void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
+                                                   u16 seid)
+{
+       u16 flag = I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC |
+                  I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP |
+                  I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX;
+       u16 ethtype = I40E_FLOW_CONTROL_ETHTYPE;
+       enum i40e_status_code status;
+
+       status = i40e_aq_add_rem_control_packet_filter(hw, NULL, ethtype, flag,
+                                                      seid, 0, TRUE, NULL,
+                                                      NULL);
+       if (status)
+               DEBUGOUT("Ethtype Filter Add failed: Error pruning Tx flow 
control frames\n");
+}
+
+/**
  * i40e_aq_add_cloud_filters
  * @hw: pointer to the hardware structure
  * @seid: VSI seid to add cloud filters from
@@ -5044,8 +5066,6 @@ enum i40e_status_code i40e_aq_alternate_
 
        cmd_resp->address = CPU_TO_LE32(addr);
        cmd_resp->length = CPU_TO_LE32(dw_count);
-       cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buffer));
-       cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer));
 
        status = i40e_asq_send_command(hw, &desc, buffer,
                                       I40E_LO_DWORD(4*dw_count), NULL);
@@ -5127,8 +5147,6 @@ enum i40e_status_code i40e_aq_alternate_
 
        cmd_resp->address = CPU_TO_LE32(addr);
        cmd_resp->length = CPU_TO_LE32(dw_count);
-       cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buffer));
-       cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer));
 
        status = i40e_asq_send_command(hw, &desc, buffer,
                                       I40E_LO_DWORD(4*dw_count), NULL);

Modified: head/sys/dev/ixl/i40e_nvm.c
==============================================================================
--- head/sys/dev/ixl/i40e_nvm.c Thu May 12 18:19:31 2016        (r299546)
+++ head/sys/dev/ixl/i40e_nvm.c Thu May 12 18:19:53 2016        (r299547)
@@ -218,7 +218,10 @@ static enum i40e_status_code i40e_poll_s
 enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
                                         u16 *data)
 {
-       return i40e_read_nvm_word_srctl(hw, offset, data);
+       enum i40e_status_code ret_code = I40E_SUCCESS;
+
+       ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
+       return ret_code;
 }
 
 /**
@@ -306,7 +309,10 @@ enum i40e_status_code i40e_read_nvm_word
 enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
                                           u16 *words, u16 *data)
 {
-       return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
+       enum i40e_status_code ret_code = I40E_SUCCESS;
+
+       ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
+       return ret_code;
 }
 
 /**
@@ -702,3 +708,777 @@ enum i40e_status_code i40e_validate_nvm_
 i40e_validate_nvm_checksum_exit:
        return ret_code;
 }
+
+static enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno);
+static enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno);
+static enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno);
+static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   int *perrno);
+static enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
+                                                  struct i40e_nvm_access *cmd,
+                                                  int *perrno);
+static enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
+                                                  struct i40e_nvm_access *cmd,
+                                                  u8 *bytes, int *perrno);
+static enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
+                                                 struct i40e_nvm_access *cmd,
+                                                 u8 *bytes, int *perrno);
+static enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
+                                                struct i40e_nvm_access *cmd,
+                                                u8 *bytes, int *perrno);
+static enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno);
+static INLINE u8 i40e_nvmupd_get_module(u32 val)
+{
+       return (u8)(val & I40E_NVM_MOD_PNT_MASK);
+}
+static INLINE u8 i40e_nvmupd_get_transaction(u32 val)
+{
+       return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
+}
+
+static const char *i40e_nvm_update_state_str[] = {
+       "I40E_NVMUPD_INVALID",
+       "I40E_NVMUPD_READ_CON",
+       "I40E_NVMUPD_READ_SNT",
+       "I40E_NVMUPD_READ_LCB",
+       "I40E_NVMUPD_READ_SA",
+       "I40E_NVMUPD_WRITE_ERA",
+       "I40E_NVMUPD_WRITE_CON",
+       "I40E_NVMUPD_WRITE_SNT",
+       "I40E_NVMUPD_WRITE_LCB",
+       "I40E_NVMUPD_WRITE_SA",
+       "I40E_NVMUPD_CSUM_CON",
+       "I40E_NVMUPD_CSUM_SA",
+       "I40E_NVMUPD_CSUM_LCB",
+       "I40E_NVMUPD_STATUS",
+       "I40E_NVMUPD_EXEC_AQ",
+       "I40E_NVMUPD_GET_AQ_RESULT",
+};
+
+/**
+ * i40e_nvmupd_command - Process an NVM update command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * Dispatches command depending on what update state is current
+ **/
+enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
+                                         struct i40e_nvm_access *cmd,
+                                         u8 *bytes, int *perrno)
+{
+       enum i40e_status_code status;
+       enum i40e_nvmupd_cmd upd_cmd;
+
+       DEBUGFUNC("i40e_nvmupd_command");
+
+       /* assume success */
+       *perrno = 0;
+
+       /* early check for status command and debug msgs */
+       upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
+
+       i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
+                  i40e_nvm_update_state_str[upd_cmd],
+                  hw->nvmupd_state,
+                  hw->aq.nvm_release_on_done);
+
+       if (upd_cmd == I40E_NVMUPD_INVALID) {
+               *perrno = -EFAULT;
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_validate_command returns %d errno %d\n",
+                          upd_cmd, *perrno);
+       }
+
+       /* a status request returns immediately rather than
+        * going into the state machine
+        */
+       if (upd_cmd == I40E_NVMUPD_STATUS) {
+               bytes[0] = hw->nvmupd_state;
+               return I40E_SUCCESS;
+       }
+
+       switch (hw->nvmupd_state) {
+       case I40E_NVMUPD_STATE_INIT:
+               status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
+               break;
+
+       case I40E_NVMUPD_STATE_READING:
+               status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
+               break;
+
+       case I40E_NVMUPD_STATE_WRITING:
+               status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
+               break;
+
+       case I40E_NVMUPD_STATE_INIT_WAIT:
+       case I40E_NVMUPD_STATE_WRITE_WAIT:
+               status = I40E_ERR_NOT_READY;
+               *perrno = -EBUSY;
+               break;
+
+       default:
+               /* invalid state, should never happen */
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "NVMUPD: no such state %d\n", hw->nvmupd_state);
+               status = I40E_NOT_SUPPORTED;
+               *perrno = -ESRCH;
+               break;
+       }
+       return status;
+}
+
+/**
+ * i40e_nvmupd_state_init - Handle NVM update state Init
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * Process legitimate commands of the Init state and conditionally set next
+ * state. Reject all other commands.
+ **/
+static enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno)
+{
+       enum i40e_status_code status = I40E_SUCCESS;
+       enum i40e_nvmupd_cmd upd_cmd;
+
+       DEBUGFUNC("i40e_nvmupd_state_init");
+
+       upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
+
+       switch (upd_cmd) {
+       case I40E_NVMUPD_READ_SA:
+               status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+               if (status) {
+                       *perrno = i40e_aq_rc_to_posix(status,
+                                                    hw->aq.asq_last_status);
+               } else {
+                       status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
+                       i40e_release_nvm(hw);
+               }
+               break;
+
+       case I40E_NVMUPD_READ_SNT:
+               status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+               if (status) {
+                       *perrno = i40e_aq_rc_to_posix(status,
+                                                    hw->aq.asq_last_status);
+               } else {
+                       status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
+                       if (status)
+                               i40e_release_nvm(hw);
+                       else
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
+               }
+               break;
+
+       case I40E_NVMUPD_WRITE_ERA:
+               status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+               if (status) {
+                       *perrno = i40e_aq_rc_to_posix(status,
+                                                    hw->aq.asq_last_status);
+               } else {
+                       status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
+                       if (status) {
+                               i40e_release_nvm(hw);
+                       } else {
+                               hw->aq.nvm_release_on_done = TRUE;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+                       }
+               }
+               break;
+
+       case I40E_NVMUPD_WRITE_SA:
+               status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+               if (status) {
+                       *perrno = i40e_aq_rc_to_posix(status,
+                                                    hw->aq.asq_last_status);
+               } else {
+                       status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+                       if (status) {
+                               i40e_release_nvm(hw);
+                       } else {
+                               hw->aq.nvm_release_on_done = TRUE;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+                       }
+               }
+               break;
+
+       case I40E_NVMUPD_WRITE_SNT:
+               status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+               if (status) {
+                       *perrno = i40e_aq_rc_to_posix(status,
+                                                    hw->aq.asq_last_status);
+               } else {
+                       status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+                       if (status)
+                               i40e_release_nvm(hw);
+                       else
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
+               }
+               break;
+
+       case I40E_NVMUPD_CSUM_SA:
+               status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+               if (status) {
+                       *perrno = i40e_aq_rc_to_posix(status,
+                                                    hw->aq.asq_last_status);
+               } else {
+                       status = i40e_update_nvm_checksum(hw);
+                       if (status) {
+                               *perrno = hw->aq.asq_last_status ?
+                                  i40e_aq_rc_to_posix(status,
+                                                      hw->aq.asq_last_status) :
+                                  -EIO;
+                               i40e_release_nvm(hw);
+                       } else {
+                               hw->aq.nvm_release_on_done = TRUE;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+                       }
+               }
+               break;
+
+       case I40E_NVMUPD_EXEC_AQ:
+               status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
+               break;
+
+       case I40E_NVMUPD_GET_AQ_RESULT:
+               status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
+               break;
+
+       default:
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "NVMUPD: bad cmd %s in init state\n",
+                          i40e_nvm_update_state_str[upd_cmd]);
+               status = I40E_ERR_NVM;
+               *perrno = -ESRCH;
+               break;
+       }
+       return status;
+}
+
+/**
+ * i40e_nvmupd_state_reading - Handle NVM update state Reading
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * NVM ownership is already held.  Process legitimate commands and set any
+ * change in state; reject all other commands.
+ **/
+static enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno)
+{
+       enum i40e_status_code status = I40E_SUCCESS;
+       enum i40e_nvmupd_cmd upd_cmd;
+
+       DEBUGFUNC("i40e_nvmupd_state_reading");
+
+       upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
+
+       switch (upd_cmd) {
+       case I40E_NVMUPD_READ_SA:
+       case I40E_NVMUPD_READ_CON:
+               status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
+               break;
+
+       case I40E_NVMUPD_READ_LCB:
+               status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
+               i40e_release_nvm(hw);
+               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               break;
+
+       default:
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "NVMUPD: bad cmd %s in reading state.\n",
+                          i40e_nvm_update_state_str[upd_cmd]);
+               status = I40E_NOT_SUPPORTED;
+               *perrno = -ESRCH;
+               break;
+       }
+       return status;
+}
+
+/**
+ * i40e_nvmupd_state_writing - Handle NVM update state Writing
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * NVM ownership is already held.  Process legitimate commands and set any
+ * change in state; reject all other commands
+ **/
+static enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno)
+{
+       enum i40e_status_code status = I40E_SUCCESS;
+       enum i40e_nvmupd_cmd upd_cmd;
+       bool retry_attempt = FALSE;
+
+       DEBUGFUNC("i40e_nvmupd_state_writing");
+
+       upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
+
+retry:
+       switch (upd_cmd) {
+       case I40E_NVMUPD_WRITE_CON:
+               status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+               if (!status)
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
+               break;
+
+       case I40E_NVMUPD_WRITE_LCB:
+               status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+               if (status) {
+                       *perrno = hw->aq.asq_last_status ?
+                                  i40e_aq_rc_to_posix(status,
+                                                      hw->aq.asq_last_status) :
+                                  -EIO;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               } else {
+                       hw->aq.nvm_release_on_done = TRUE;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+               }
+               break;
+
+       case I40E_NVMUPD_CSUM_CON:
+               status = i40e_update_nvm_checksum(hw);
+               if (status) {
+                       *perrno = hw->aq.asq_last_status ?
+                                  i40e_aq_rc_to_posix(status,
+                                                      hw->aq.asq_last_status) :
+                                  -EIO;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               } else {
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
+               }
+               break;
+
+       case I40E_NVMUPD_CSUM_LCB:
+               status = i40e_update_nvm_checksum(hw);
+               if (status) {
+                       *perrno = hw->aq.asq_last_status ?
+                                  i40e_aq_rc_to_posix(status,
+                                                      hw->aq.asq_last_status) :
+                                  -EIO;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               } else {
+                       hw->aq.nvm_release_on_done = TRUE;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+               }
+               break;
+
+       default:
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "NVMUPD: bad cmd %s in writing state.\n",
+                          i40e_nvm_update_state_str[upd_cmd]);
+               status = I40E_NOT_SUPPORTED;
+               *perrno = -ESRCH;
+               break;
+       }
+
+       /* In some circumstances, a multi-write transaction takes longer
+        * than the default 3 minute timeout on the write semaphore.  If
+        * the write failed with an EBUSY status, this is likely the problem,
+        * so here we try to reacquire the semaphore then retry the write.
+        * We only do one retry, then give up.
+        */
+       if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
+           !retry_attempt) {
+               enum i40e_status_code old_status = status;
+               u32 old_asq_status = hw->aq.asq_last_status;
+               u32 gtime;
+
+               gtime = rd32(hw, I40E_GLVFGEN_TIMER);
+               if (gtime >= hw->nvm.hw_semaphore_timeout) {
+                       i40e_debug(hw, I40E_DEBUG_ALL,
+                                  "NVMUPD: write semaphore expired (%d >= 
%lld), retrying\n",
+                                  gtime, hw->nvm.hw_semaphore_timeout);
+                       i40e_release_nvm(hw);
+                       status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+                       if (status) {
+                               i40e_debug(hw, I40E_DEBUG_ALL,
+                                          "NVMUPD: write semaphore reacquire 
failed aq_err = %d\n",
+                                          hw->aq.asq_last_status);
+                               status = old_status;
+                               hw->aq.asq_last_status = old_asq_status;
+                       } else {
+                               retry_attempt = TRUE;
+                               goto retry;
+                       }
+               }
+       }
+
+       return status;
+}
+
+/**
+ * i40e_nvmupd_validate_command - Validate given command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @perrno: pointer to return error code
+ *
+ * Return one of the valid command types or I40E_NVMUPD_INVALID
+ **/
+static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   int *perrno)
+{
+       enum i40e_nvmupd_cmd upd_cmd;
+       u8 module, transaction;
+
+       DEBUGFUNC("i40e_nvmupd_validate_command\n");
+
+       /* anything that doesn't match a recognized case is an error */
+       upd_cmd = I40E_NVMUPD_INVALID;
+
+       transaction = i40e_nvmupd_get_transaction(cmd->config);
+       module = i40e_nvmupd_get_module(cmd->config);
+
+       /* limits on data size */
+       if ((cmd->data_size < 1) ||
+           (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_validate_command data_size %d\n",
+                          cmd->data_size);
+               *perrno = -EFAULT;
+               return I40E_NVMUPD_INVALID;
+       }
+
+       switch (cmd->command) {
+       case I40E_NVM_READ:
+               switch (transaction) {
+               case I40E_NVM_CON:
+                       upd_cmd = I40E_NVMUPD_READ_CON;
+                       break;
+               case I40E_NVM_SNT:
+                       upd_cmd = I40E_NVMUPD_READ_SNT;
+                       break;
+               case I40E_NVM_LCB:
+                       upd_cmd = I40E_NVMUPD_READ_LCB;
+                       break;
+               case I40E_NVM_SA:
+                       upd_cmd = I40E_NVMUPD_READ_SA;
+                       break;
+               case I40E_NVM_EXEC:
+                       if (module == 0xf)
+                               upd_cmd = I40E_NVMUPD_STATUS;
+                       else if (module == 0)
+                               upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
+                       break;
+               }
+               break;
+
+       case I40E_NVM_WRITE:
+               switch (transaction) {
+               case I40E_NVM_CON:
+                       upd_cmd = I40E_NVMUPD_WRITE_CON;
+                       break;
+               case I40E_NVM_SNT:
+                       upd_cmd = I40E_NVMUPD_WRITE_SNT;
+                       break;
+               case I40E_NVM_LCB:
+                       upd_cmd = I40E_NVMUPD_WRITE_LCB;
+                       break;
+               case I40E_NVM_SA:
+                       upd_cmd = I40E_NVMUPD_WRITE_SA;
+                       break;
+               case I40E_NVM_ERA:
+                       upd_cmd = I40E_NVMUPD_WRITE_ERA;
+                       break;
+               case I40E_NVM_CSUM:
+                       upd_cmd = I40E_NVMUPD_CSUM_CON;
+                       break;
+               case (I40E_NVM_CSUM|I40E_NVM_SA):
+                       upd_cmd = I40E_NVMUPD_CSUM_SA;
+                       break;
+               case (I40E_NVM_CSUM|I40E_NVM_LCB):
+                       upd_cmd = I40E_NVMUPD_CSUM_LCB;
+                       break;
+               case I40E_NVM_EXEC:
+                       if (module == 0)
+                               upd_cmd = I40E_NVMUPD_EXEC_AQ;
+                       break;
+               }
+               break;
+       }
+
+       return upd_cmd;
+}
+
+/**
+ * i40e_nvmupd_exec_aq - Run an AQ command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
+                                                struct i40e_nvm_access *cmd,
+                                                u8 *bytes, int *perrno)
+{
+       struct i40e_asq_cmd_details cmd_details;
+       enum i40e_status_code status;
+       struct i40e_aq_desc *aq_desc;
+       u32 buff_size = 0;
+       u8 *buff = NULL;
+       u32 aq_desc_len;
+       u32 aq_data_len;
+
+       i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+       memset(&cmd_details, 0, sizeof(cmd_details));
+       cmd_details.wb_desc = &hw->nvm_wb_desc;
+
+       aq_desc_len = sizeof(struct i40e_aq_desc);
+       memset(&hw->nvm_wb_desc, 0, aq_desc_len);
+
+       /* get the aq descriptor */
+       if (cmd->data_size < aq_desc_len) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "NVMUPD: not enough aq desc bytes for exec, size %d 
< %d\n",
+                          cmd->data_size, aq_desc_len);
+               *perrno = -EINVAL;
+               return I40E_ERR_PARAM;
+       }
+       aq_desc = (struct i40e_aq_desc *)bytes;
+
+       /* if data buffer needed, make sure it's ready */
+       aq_data_len = cmd->data_size - aq_desc_len;
+       buff_size = max(aq_data_len, (u32)LE16_TO_CPU(aq_desc->datalen));
+       if (buff_size) {
+               if (!hw->nvm_buff.va) {
+                       status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
+                                                       hw->aq.asq_buf_size);
+                       if (status)
+                               i40e_debug(hw, I40E_DEBUG_NVM,
+                                          "NVMUPD: i40e_allocate_virt_mem for 
exec buff failed, %d\n",
+                                          status);
+               }
+
+               if (hw->nvm_buff.va) {
+                       buff = hw->nvm_buff.va;
+                       memcpy(buff, &bytes[aq_desc_len], aq_data_len);
+               }
+       }
+
+       /* and away we go! */
+       status = i40e_asq_send_command(hw, aq_desc, buff,
+                                      buff_size, &cmd_details);
+       if (status) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_exec_aq err %s aq_err %s\n",
+                          i40e_stat_str(hw, status),
+                          i40e_aq_str(hw, hw->aq.asq_last_status));
+               *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+       }
+
+       return status;
+}
+
+/**
+ * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno)
+{
+       u32 aq_total_len;
+       u32 aq_desc_len;
+       int remainder;
+       u8 *buff;
+
+       i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+
+       aq_desc_len = sizeof(struct i40e_aq_desc);
+       aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_wb_desc.datalen);
+
+       /* check offset range */
+       if (cmd->offset > aq_total_len) {
+               i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
+                          __func__, cmd->offset, aq_total_len);
+               *perrno = -EINVAL;
+               return I40E_ERR_PARAM;
+       }
+
+       /* check copylength range */
+       if (cmd->data_size > (aq_total_len - cmd->offset)) {
+               int new_len = aq_total_len - cmd->offset;
+
+               i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, 
trimming to %d\n",
+                          __func__, cmd->data_size, new_len);
+               cmd->data_size = new_len;
+       }
+
+       remainder = cmd->data_size;
+       if (cmd->offset < aq_desc_len) {
+               u32 len = aq_desc_len - cmd->offset;
+
+               len = min(len, cmd->data_size);
+               i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
+                          __func__, cmd->offset, cmd->offset + len);
+
+               buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
+               memcpy(bytes, buff, len);
+
+               bytes += len;
+               remainder -= len;
+               buff = hw->nvm_buff.va;
+       } else {
+               buff = (u8 *)hw->nvm_buff.va + (cmd->offset - aq_desc_len);
+       }
+
+       if (remainder > 0) {
+               int start_byte = buff - (u8 *)hw->nvm_buff.va;
+
+               i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
+                          __func__, start_byte, start_byte + remainder);
+               memcpy(bytes, buff, remainder);
+       }
+
+       return I40E_SUCCESS;
+}
+
+/**
+ * i40e_nvmupd_nvm_read - Read NVM
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
+                                                 struct i40e_nvm_access *cmd,
+                                                 u8 *bytes, int *perrno)
+{
+       struct i40e_asq_cmd_details cmd_details;
+       enum i40e_status_code status;
+       u8 module, transaction;
+       bool last;
+
+       transaction = i40e_nvmupd_get_transaction(cmd->config);
+       module = i40e_nvmupd_get_module(cmd->config);
+       last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
+
+       memset(&cmd_details, 0, sizeof(cmd_details));
+       cmd_details.wb_desc = &hw->nvm_wb_desc;
+
+       status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
+                                 bytes, last, &cmd_details);
+       if (status) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_nvm_read mod 0x%x  off 0x%x  len 
0x%x\n",
+                          module, cmd->offset, cmd->data_size);
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_nvm_read status %d aq %d\n",
+                          status, hw->aq.asq_last_status);
+               *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+       }
+
+       return status;
+}
+
+/**
+ * i40e_nvmupd_nvm_erase - Erase an NVM module
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @perrno: pointer to return error code
+ *
+ * module, offset, data_size and data are in cmd structure
+ **/
+static enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
+                                                  struct i40e_nvm_access *cmd,
+                                                  int *perrno)
+{
+       enum i40e_status_code status = I40E_SUCCESS;
+       struct i40e_asq_cmd_details cmd_details;
+       u8 module, transaction;
+       bool last;
+
+       transaction = i40e_nvmupd_get_transaction(cmd->config);
+       module = i40e_nvmupd_get_module(cmd->config);
+       last = (transaction & I40E_NVM_LCB);
+
+       memset(&cmd_details, 0, sizeof(cmd_details));
+       cmd_details.wb_desc = &hw->nvm_wb_desc;
+
+       status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
+                                  last, &cmd_details);
+       if (status) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_nvm_erase mod 0x%x  off 0x%x len 
0x%x\n",
+                          module, cmd->offset, cmd->data_size);
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_nvm_erase status %d aq %d\n",
+                          status, hw->aq.asq_last_status);
+               *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+       }
+
+       return status;
+}
+
+/**
+ * i40e_nvmupd_nvm_write - Write NVM
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * module, offset, data_size and data are in cmd structure
+ **/
+static enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
+                                                  struct i40e_nvm_access *cmd,
+                                                  u8 *bytes, int *perrno)
+{
+       enum i40e_status_code status = I40E_SUCCESS;
+       struct i40e_asq_cmd_details cmd_details;
+       u8 module, transaction;
+       bool last;
+
+       transaction = i40e_nvmupd_get_transaction(cmd->config);
+       module = i40e_nvmupd_get_module(cmd->config);
+       last = (transaction & I40E_NVM_LCB);
+
+       memset(&cmd_details, 0, sizeof(cmd_details));
+       cmd_details.wb_desc = &hw->nvm_wb_desc;
+
+       status = i40e_aq_update_nvm(hw, module, cmd->offset,
+                                   (u16)cmd->data_size, bytes, last,
+                                   &cmd_details);
+       if (status) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
+                          module, cmd->offset, cmd->data_size);
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "i40e_nvmupd_nvm_write status %d aq %d\n",
+                          status, hw->aq.asq_last_status);
+               *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+       }
+
+       return status;
+}

Modified: head/sys/dev/ixl/i40e_prototype.h
==============================================================================
--- head/sys/dev/ixl/i40e_prototype.h   Thu May 12 18:19:31 2016        
(r299546)
+++ head/sys/dev/ixl/i40e_prototype.h   Thu May 12 18:19:53 2016        
(r299547)
@@ -462,4 +462,6 @@ enum i40e_status_code i40e_aq_debug_dump
                                void *buff, u16 *ret_buff_size,
                                u8 *ret_next_table, u32 *ret_next_index,
                                struct i40e_asq_cmd_details *cmd_details);
+void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
+                                                   u16 vsi_seid);
 #endif /* _I40E_PROTOTYPE_H_ */

Modified: head/sys/dev/ixl/i40e_type.h
==============================================================================
--- head/sys/dev/ixl/i40e_type.h        Thu May 12 18:19:31 2016        
(r299546)
+++ head/sys/dev/ixl/i40e_type.h        Thu May 12 18:19:53 2016        
(r299547)
@@ -619,6 +619,9 @@ struct i40e_hw {
        struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
        struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
 
+#define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
+       u64 flags;
+
        /* debug mask */
        u32 debug_mask;
        char err_str[16];

Modified: head/sys/dev/ixl/if_ixl.c
==============================================================================
--- head/sys/dev/ixl/if_ixl.c   Thu May 12 18:19:31 2016        (r299546)
+++ head/sys/dev/ixl/if_ixl.c   Thu May 12 18:19:53 2016        (r299547)
@@ -48,7 +48,7 @@
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixl_driver_version[] = "1.4.6-k";
+char ixl_driver_version[] = "1.4.7-k";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -99,6 +99,7 @@ static int      ixl_ioctl(struct ifnet *
 static void    ixl_init(void *);
 static void    ixl_init_locked(struct ixl_pf *);
 static void     ixl_stop(struct ixl_pf *);
+static void    ixl_stop_locked(struct ixl_pf *);
 static void     ixl_media_status(struct ifnet *, struct ifmediareq *);
 static int      ixl_media_change(struct ifnet *);
 static void     ixl_update_link_status(struct ixl_pf *);
@@ -115,6 +116,7 @@ static void ixl_configure_itr(struct ixl
 static void    ixl_configure_legacy(struct ixl_pf *);
 static void    ixl_init_taskqueues(struct ixl_pf *);
 static void    ixl_free_taskqueues(struct ixl_pf *);
+static void    ixl_free_interrupt_resources(struct ixl_pf *);
 static void    ixl_free_pci_resources(struct ixl_pf *);
 static void    ixl_local_timer(void *);
 static int     ixl_setup_interface(device_t, struct ixl_vsi *);
@@ -191,6 +193,8 @@ static void ixl_stat_update48(struct i40
                    u64 *, u64 *);
 static void    ixl_stat_update32(struct i40e_hw *, u32, bool,
                    u64 *, u64 *);
+/* NVM update */
+static int     ixl_handle_nvmupd_cmd(struct ixl_pf *, struct ifdrv *);
 
 #ifdef IXL_DEBUG_SYSCTL
 static int     ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
@@ -200,6 +204,7 @@ static int  ixl_sysctl_hw_res_alloc(SYSCT
 static int     ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
 #endif
 
+
 #ifdef PCI_IOV
 static int     ixl_adminq_err_to_errno(enum i40e_admin_queue_err err);
 
@@ -634,28 +639,22 @@ ixl_attach(device_t dev)
        /* Initialize mac filter list for VSI */
        SLIST_INIT(&vsi->ftl);
 
-       /* Set up interrupt routing here */
-       if (pf->msix > 1)
-               error = ixl_assign_vsi_msix(pf);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to