Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/i40e_adminq.c
Show All 38 Lines | |||||
#include "i40e_prototype.h" | #include "i40e_prototype.h" | ||||
/** | /** | ||||
* i40e_is_nvm_update_op - return TRUE if this is an NVM update operation | * i40e_is_nvm_update_op - return TRUE if this is an NVM update operation | ||||
* @desc: API request descriptor | * @desc: API request descriptor | ||||
**/ | **/ | ||||
static INLINE bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc) | static INLINE bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc) | ||||
{ | { | ||||
return (desc->opcode == CPU_TO_LE16(i40e_aqc_opc_nvm_erase) || | return (desc->opcode == CPU_TO_LE16(i40e_aqc_opc_nvm_erase)) || | ||||
desc->opcode == CPU_TO_LE16(i40e_aqc_opc_nvm_update)); | (desc->opcode == CPU_TO_LE16(i40e_aqc_opc_nvm_update)); | ||||
} | } | ||||
/** | /** | ||||
* i40e_adminq_init_regs - Initialize AdminQ registers | * i40e_adminq_init_regs - Initialize AdminQ registers | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* | * | ||||
* This assumes the alloc_asq and alloc_arq functions have already been called | * This assumes the alloc_asq and alloc_arq functions have already been called | ||||
**/ | **/ | ||||
▲ Show 20 Lines • Show All 338 Lines • ▼ Show 20 Lines | enum i40e_status_code i40e_init_asq(struct i40e_hw *hw) | ||||
if ((hw->aq.num_asq_entries == 0) || | if ((hw->aq.num_asq_entries == 0) || | ||||
(hw->aq.asq_buf_size == 0)) { | (hw->aq.asq_buf_size == 0)) { | ||||
ret_code = I40E_ERR_CONFIG; | ret_code = I40E_ERR_CONFIG; | ||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
} | } | ||||
hw->aq.asq.next_to_use = 0; | hw->aq.asq.next_to_use = 0; | ||||
hw->aq.asq.next_to_clean = 0; | hw->aq.asq.next_to_clean = 0; | ||||
hw->aq.asq.count = hw->aq.num_asq_entries; | |||||
/* allocate the ring memory */ | /* allocate the ring memory */ | ||||
ret_code = i40e_alloc_adminq_asq_ring(hw); | ret_code = i40e_alloc_adminq_asq_ring(hw); | ||||
if (ret_code != I40E_SUCCESS) | if (ret_code != I40E_SUCCESS) | ||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
/* allocate buffers in the rings */ | /* allocate buffers in the rings */ | ||||
ret_code = i40e_alloc_asq_bufs(hw); | ret_code = i40e_alloc_asq_bufs(hw); | ||||
if (ret_code != I40E_SUCCESS) | if (ret_code != I40E_SUCCESS) | ||||
goto init_adminq_free_rings; | goto init_adminq_free_rings; | ||||
/* initialize base registers */ | /* initialize base registers */ | ||||
ret_code = i40e_config_asq_regs(hw); | ret_code = i40e_config_asq_regs(hw); | ||||
if (ret_code != I40E_SUCCESS) | if (ret_code != I40E_SUCCESS) | ||||
goto init_adminq_free_rings; | goto init_adminq_free_rings; | ||||
/* success! */ | /* success! */ | ||||
hw->aq.asq.count = hw->aq.num_asq_entries; | |||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
init_adminq_free_rings: | init_adminq_free_rings: | ||||
i40e_free_adminq_asq(hw); | i40e_free_adminq_asq(hw); | ||||
init_adminq_exit: | init_adminq_exit: | ||||
return ret_code; | return ret_code; | ||||
} | } | ||||
Show All 25 Lines | enum i40e_status_code i40e_init_arq(struct i40e_hw *hw) | ||||
if ((hw->aq.num_arq_entries == 0) || | if ((hw->aq.num_arq_entries == 0) || | ||||
(hw->aq.arq_buf_size == 0)) { | (hw->aq.arq_buf_size == 0)) { | ||||
ret_code = I40E_ERR_CONFIG; | ret_code = I40E_ERR_CONFIG; | ||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
} | } | ||||
hw->aq.arq.next_to_use = 0; | hw->aq.arq.next_to_use = 0; | ||||
hw->aq.arq.next_to_clean = 0; | hw->aq.arq.next_to_clean = 0; | ||||
hw->aq.arq.count = hw->aq.num_arq_entries; | |||||
/* allocate the ring memory */ | /* allocate the ring memory */ | ||||
ret_code = i40e_alloc_adminq_arq_ring(hw); | ret_code = i40e_alloc_adminq_arq_ring(hw); | ||||
if (ret_code != I40E_SUCCESS) | if (ret_code != I40E_SUCCESS) | ||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
/* allocate buffers in the rings */ | /* allocate buffers in the rings */ | ||||
ret_code = i40e_alloc_arq_bufs(hw); | ret_code = i40e_alloc_arq_bufs(hw); | ||||
if (ret_code != I40E_SUCCESS) | if (ret_code != I40E_SUCCESS) | ||||
goto init_adminq_free_rings; | goto init_adminq_free_rings; | ||||
/* initialize base registers */ | /* initialize base registers */ | ||||
ret_code = i40e_config_arq_regs(hw); | ret_code = i40e_config_arq_regs(hw); | ||||
if (ret_code != I40E_SUCCESS) | if (ret_code != I40E_SUCCESS) | ||||
goto init_adminq_free_rings; | goto init_adminq_free_rings; | ||||
/* success! */ | /* success! */ | ||||
hw->aq.arq.count = hw->aq.num_arq_entries; | |||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
init_adminq_free_rings: | init_adminq_free_rings: | ||||
i40e_free_adminq_arq(hw); | i40e_free_adminq_arq(hw); | ||||
init_adminq_exit: | init_adminq_exit: | ||||
return ret_code; | return ret_code; | ||||
} | } | ||||
/** | /** | ||||
* i40e_shutdown_asq - shutdown the ASQ | * i40e_shutdown_asq - shutdown the ASQ | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* | * | ||||
* The main shutdown routine for the Admin Send Queue | * The main shutdown routine for the Admin Send Queue | ||||
**/ | **/ | ||||
enum i40e_status_code i40e_shutdown_asq(struct i40e_hw *hw) | enum i40e_status_code i40e_shutdown_asq(struct i40e_hw *hw) | ||||
{ | { | ||||
enum i40e_status_code ret_code = I40E_SUCCESS; | enum i40e_status_code ret_code = I40E_SUCCESS; | ||||
if (hw->aq.asq.count == 0) | i40e_acquire_spinlock(&hw->aq.asq_spinlock); | ||||
return I40E_ERR_NOT_READY; | |||||
if (hw->aq.asq.count == 0) { | |||||
ret_code = I40E_ERR_NOT_READY; | |||||
goto shutdown_asq_out; | |||||
} | |||||
/* Stop firmware AdminQ processing */ | /* Stop firmware AdminQ processing */ | ||||
wr32(hw, hw->aq.asq.head, 0); | wr32(hw, hw->aq.asq.head, 0); | ||||
wr32(hw, hw->aq.asq.tail, 0); | wr32(hw, hw->aq.asq.tail, 0); | ||||
wr32(hw, hw->aq.asq.len, 0); | wr32(hw, hw->aq.asq.len, 0); | ||||
wr32(hw, hw->aq.asq.bal, 0); | wr32(hw, hw->aq.asq.bal, 0); | ||||
wr32(hw, hw->aq.asq.bah, 0); | wr32(hw, hw->aq.asq.bah, 0); | ||||
/* make sure spinlock is available */ | |||||
i40e_acquire_spinlock(&hw->aq.asq_spinlock); | |||||
hw->aq.asq.count = 0; /* to indicate uninitialized queue */ | hw->aq.asq.count = 0; /* to indicate uninitialized queue */ | ||||
/* free ring buffers */ | /* free ring buffers */ | ||||
i40e_free_asq_bufs(hw); | i40e_free_asq_bufs(hw); | ||||
shutdown_asq_out: | |||||
i40e_release_spinlock(&hw->aq.asq_spinlock); | i40e_release_spinlock(&hw->aq.asq_spinlock); | ||||
return ret_code; | return ret_code; | ||||
} | } | ||||
/** | /** | ||||
* i40e_shutdown_arq - shutdown ARQ | * i40e_shutdown_arq - shutdown ARQ | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* | * | ||||
* The main shutdown routine for the Admin Receive Queue | * The main shutdown routine for the Admin Receive Queue | ||||
**/ | **/ | ||||
enum i40e_status_code i40e_shutdown_arq(struct i40e_hw *hw) | enum i40e_status_code i40e_shutdown_arq(struct i40e_hw *hw) | ||||
{ | { | ||||
enum i40e_status_code ret_code = I40E_SUCCESS; | enum i40e_status_code ret_code = I40E_SUCCESS; | ||||
if (hw->aq.arq.count == 0) | i40e_acquire_spinlock(&hw->aq.arq_spinlock); | ||||
return I40E_ERR_NOT_READY; | |||||
if (hw->aq.arq.count == 0) { | |||||
ret_code = I40E_ERR_NOT_READY; | |||||
goto shutdown_arq_out; | |||||
} | |||||
/* Stop firmware AdminQ processing */ | /* Stop firmware AdminQ processing */ | ||||
wr32(hw, hw->aq.arq.head, 0); | wr32(hw, hw->aq.arq.head, 0); | ||||
wr32(hw, hw->aq.arq.tail, 0); | wr32(hw, hw->aq.arq.tail, 0); | ||||
wr32(hw, hw->aq.arq.len, 0); | wr32(hw, hw->aq.arq.len, 0); | ||||
wr32(hw, hw->aq.arq.bal, 0); | wr32(hw, hw->aq.arq.bal, 0); | ||||
wr32(hw, hw->aq.arq.bah, 0); | wr32(hw, hw->aq.arq.bah, 0); | ||||
/* make sure spinlock is available */ | |||||
i40e_acquire_spinlock(&hw->aq.arq_spinlock); | |||||
hw->aq.arq.count = 0; /* to indicate uninitialized queue */ | hw->aq.arq.count = 0; /* to indicate uninitialized queue */ | ||||
/* free ring buffers */ | /* free ring buffers */ | ||||
i40e_free_arq_bufs(hw); | i40e_free_arq_bufs(hw); | ||||
shutdown_arq_out: | |||||
i40e_release_spinlock(&hw->aq.arq_spinlock); | i40e_release_spinlock(&hw->aq.arq_spinlock); | ||||
return ret_code; | return ret_code; | ||||
} | } | ||||
/** | /** | ||||
* i40e_resume_aq - resume AQ processing from 0 | |||||
* @hw: pointer to the hardware structure | |||||
**/ | |||||
static void i40e_resume_aq(struct i40e_hw *hw) | |||||
{ | |||||
/* Registers are reset after PF reset */ | |||||
hw->aq.asq.next_to_use = 0; | |||||
hw->aq.asq.next_to_clean = 0; | |||||
i40e_config_asq_regs(hw); | |||||
hw->aq.arq.next_to_use = 0; | |||||
hw->aq.arq.next_to_clean = 0; | |||||
i40e_config_arq_regs(hw); | |||||
} | |||||
/** | |||||
* i40e_init_adminq - main initialization routine for Admin Queue | * i40e_init_adminq - main initialization routine for Admin Queue | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* | * | ||||
* Prior to calling this function, drivers *MUST* set the following fields | * Prior to calling this function, drivers *MUST* set the following fields | ||||
* in the hw->aq structure: | * in the hw->aq structure: | ||||
* - hw->aq.num_asq_entries | * - hw->aq.num_asq_entries | ||||
* - hw->aq.num_arq_entries | * - hw->aq.num_arq_entries | ||||
* - hw->aq.arq_buf_size | * - hw->aq.arq_buf_size | ||||
* - hw->aq.asq_buf_size | * - hw->aq.asq_buf_size | ||||
**/ | **/ | ||||
enum i40e_status_code i40e_init_adminq(struct i40e_hw *hw) | enum i40e_status_code i40e_init_adminq(struct i40e_hw *hw) | ||||
{ | { | ||||
enum i40e_status_code ret_code; | |||||
u16 eetrack_lo, eetrack_hi; | |||||
u16 cfg_ptr, oem_hi, oem_lo; | u16 cfg_ptr, oem_hi, oem_lo; | ||||
u16 eetrack_lo, eetrack_hi; | |||||
enum i40e_status_code ret_code; | |||||
int retry = 0; | int retry = 0; | ||||
/* verify input for valid configuration */ | /* verify input for valid configuration */ | ||||
if ((hw->aq.num_arq_entries == 0) || | if ((hw->aq.num_arq_entries == 0) || | ||||
(hw->aq.num_asq_entries == 0) || | (hw->aq.num_asq_entries == 0) || | ||||
(hw->aq.arq_buf_size == 0) || | (hw->aq.arq_buf_size == 0) || | ||||
(hw->aq.asq_buf_size == 0)) { | (hw->aq.asq_buf_size == 0)) { | ||||
ret_code = I40E_ERR_CONFIG; | ret_code = I40E_ERR_CONFIG; | ||||
goto init_adminq_exit; | goto init_adminq_exit; | ||||
} | } | ||||
/* initialize spin locks */ | |||||
i40e_init_spinlock(&hw->aq.asq_spinlock); | i40e_init_spinlock(&hw->aq.asq_spinlock); | ||||
i40e_init_spinlock(&hw->aq.arq_spinlock); | i40e_init_spinlock(&hw->aq.arq_spinlock); | ||||
/* Set up register offsets */ | /* Set up register offsets */ | ||||
i40e_adminq_init_regs(hw); | i40e_adminq_init_regs(hw); | ||||
/* setup ASQ command write back timeout */ | /* setup ASQ command write back timeout */ | ||||
hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT; | hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT; | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
enum i40e_status_code ret_code = I40E_SUCCESS; | enum i40e_status_code ret_code = I40E_SUCCESS; | ||||
if (i40e_check_asq_alive(hw)) | if (i40e_check_asq_alive(hw)) | ||||
i40e_aq_queue_shutdown(hw, TRUE); | i40e_aq_queue_shutdown(hw, TRUE); | ||||
i40e_shutdown_asq(hw); | i40e_shutdown_asq(hw); | ||||
i40e_shutdown_arq(hw); | i40e_shutdown_arq(hw); | ||||
/* destroy the spinlocks */ | |||||
i40e_destroy_spinlock(&hw->aq.asq_spinlock); | i40e_destroy_spinlock(&hw->aq.asq_spinlock); | ||||
i40e_destroy_spinlock(&hw->aq.arq_spinlock); | i40e_destroy_spinlock(&hw->aq.arq_spinlock); | ||||
if (hw->nvm_buff.va) | if (hw->nvm_buff.va) | ||||
i40e_free_virt_mem(hw, &hw->nvm_buff); | i40e_free_virt_mem(hw, &hw->nvm_buff); | ||||
return ret_code; | return ret_code; | ||||
} | } | ||||
Show All 9 Lines | u16 i40e_clean_asq(struct i40e_hw *hw) | ||||
struct i40e_adminq_ring *asq = &(hw->aq.asq); | struct i40e_adminq_ring *asq = &(hw->aq.asq); | ||||
struct i40e_asq_cmd_details *details; | struct i40e_asq_cmd_details *details; | ||||
u16 ntc = asq->next_to_clean; | u16 ntc = asq->next_to_clean; | ||||
struct i40e_aq_desc desc_cb; | struct i40e_aq_desc desc_cb; | ||||
struct i40e_aq_desc *desc; | struct i40e_aq_desc *desc; | ||||
desc = I40E_ADMINQ_DESC(*asq, ntc); | desc = I40E_ADMINQ_DESC(*asq, ntc); | ||||
details = I40E_ADMINQ_DETAILS(*asq, ntc); | details = I40E_ADMINQ_DETAILS(*asq, ntc); | ||||
while (rd32(hw, hw->aq.asq.head) != ntc) { | while (rd32(hw, hw->aq.asq.head) != ntc) { | ||||
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | ||||
"ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head)); | "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head)); | ||||
if (details->callback) { | if (details->callback) { | ||||
I40E_ADMINQ_CALLBACK cb_func = | I40E_ADMINQ_CALLBACK cb_func = | ||||
(I40E_ADMINQ_CALLBACK)details->callback; | (I40E_ADMINQ_CALLBACK)details->callback; | ||||
i40e_memcpy(&desc_cb, desc, sizeof(struct i40e_aq_desc), | i40e_memcpy(&desc_cb, desc, sizeof(struct i40e_aq_desc), | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | enum i40e_status_code i40e_asq_send_command(struct i40e_hw *hw, | ||||
enum i40e_status_code status = I40E_SUCCESS; | enum i40e_status_code status = I40E_SUCCESS; | ||||
struct i40e_dma_mem *dma_buff = NULL; | struct i40e_dma_mem *dma_buff = NULL; | ||||
struct i40e_asq_cmd_details *details; | struct i40e_asq_cmd_details *details; | ||||
struct i40e_aq_desc *desc_on_ring; | struct i40e_aq_desc *desc_on_ring; | ||||
bool cmd_completed = FALSE; | bool cmd_completed = FALSE; | ||||
u16 retval = 0; | u16 retval = 0; | ||||
u32 val = 0; | u32 val = 0; | ||||
i40e_acquire_spinlock(&hw->aq.asq_spinlock); | |||||
hw->aq.asq_last_status = I40E_AQ_RC_OK; | hw->aq.asq_last_status = I40E_AQ_RC_OK; | ||||
val = rd32(hw, hw->aq.asq.head); | if (hw->aq.asq.count == 0) { | ||||
if (val >= hw->aq.num_asq_entries) { | |||||
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | ||||
"AQTX: head overrun at %d\n", val); | "AQTX: Admin queue not initialized.\n"); | ||||
status = I40E_ERR_QUEUE_EMPTY; | status = I40E_ERR_QUEUE_EMPTY; | ||||
goto asq_send_command_exit; | goto asq_send_command_error; | ||||
} | } | ||||
if (hw->aq.asq.count == 0) { | val = rd32(hw, hw->aq.asq.head); | ||||
if (val >= hw->aq.num_asq_entries) { | |||||
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | ||||
"AQTX: Admin queue not initialized.\n"); | "AQTX: head overrun at %d\n", val); | ||||
status = I40E_ERR_QUEUE_EMPTY; | status = I40E_ERR_QUEUE_EMPTY; | ||||
goto asq_send_command_exit; | goto asq_send_command_error; | ||||
} | } | ||||
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); | details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); | ||||
if (cmd_details) { | if (cmd_details) { | ||||
i40e_memcpy(details, | i40e_memcpy(details, | ||||
cmd_details, | cmd_details, | ||||
sizeof(struct i40e_asq_cmd_details), | sizeof(struct i40e_asq_cmd_details), | ||||
I40E_NONDMA_TO_NONDMA); | I40E_NONDMA_TO_NONDMA); | ||||
Show All 13 Lines | i40e_memset(details, 0, | ||||
sizeof(struct i40e_asq_cmd_details), | sizeof(struct i40e_asq_cmd_details), | ||||
I40E_NONDMA_MEM); | I40E_NONDMA_MEM); | ||||
} | } | ||||
/* clear requested flags and then set additional flags if defined */ | /* clear requested flags and then set additional flags if defined */ | ||||
desc->flags &= ~CPU_TO_LE16(details->flags_dis); | desc->flags &= ~CPU_TO_LE16(details->flags_dis); | ||||
desc->flags |= CPU_TO_LE16(details->flags_ena); | desc->flags |= CPU_TO_LE16(details->flags_ena); | ||||
i40e_acquire_spinlock(&hw->aq.asq_spinlock); | |||||
if (buff_size > hw->aq.asq_buf_size) { | if (buff_size > hw->aq.asq_buf_size) { | ||||
i40e_debug(hw, | i40e_debug(hw, | ||||
I40E_DEBUG_AQ_MESSAGE, | I40E_DEBUG_AQ_MESSAGE, | ||||
"AQTX: Invalid buffer size: %d.\n", | "AQTX: Invalid buffer size: %d.\n", | ||||
buff_size); | buff_size); | ||||
status = I40E_ERR_INVALID_SIZE; | status = I40E_ERR_INVALID_SIZE; | ||||
goto asq_send_command_error; | goto asq_send_command_error; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | if (!details->async && !details->postpone) { | ||||
u32 total_delay = 0; | u32 total_delay = 0; | ||||
do { | do { | ||||
/* AQ designers suggest use of head for better | /* AQ designers suggest use of head for better | ||||
* timing reliability than DD bit | * timing reliability than DD bit | ||||
*/ | */ | ||||
if (i40e_asq_done(hw)) | if (i40e_asq_done(hw)) | ||||
break; | break; | ||||
/* ugh! delay while spin_lock */ | |||||
i40e_msec_delay(1); | i40e_msec_delay(1); | ||||
total_delay++; | total_delay++; | ||||
} while (total_delay < hw->aq.asq_cmd_timeout); | } while (total_delay < hw->aq.asq_cmd_timeout); | ||||
} | } | ||||
/* if ready, copy the desc back to temp */ | /* if ready, copy the desc back to temp */ | ||||
if (i40e_asq_done(hw)) { | if (i40e_asq_done(hw)) { | ||||
i40e_memcpy(desc, desc_on_ring, sizeof(struct i40e_aq_desc), | i40e_memcpy(desc, desc_on_ring, sizeof(struct i40e_aq_desc), | ||||
Show All 34 Lines | if ((!cmd_completed) && | ||||
i40e_debug(hw, | i40e_debug(hw, | ||||
I40E_DEBUG_AQ_MESSAGE, | I40E_DEBUG_AQ_MESSAGE, | ||||
"AQTX: Writeback timeout.\n"); | "AQTX: Writeback timeout.\n"); | ||||
status = I40E_ERR_ADMIN_QUEUE_TIMEOUT; | status = I40E_ERR_ADMIN_QUEUE_TIMEOUT; | ||||
} | } | ||||
asq_send_command_error: | asq_send_command_error: | ||||
i40e_release_spinlock(&hw->aq.asq_spinlock); | i40e_release_spinlock(&hw->aq.asq_spinlock); | ||||
asq_send_command_exit: | |||||
return status; | return status; | ||||
} | } | ||||
/** | /** | ||||
* i40e_fill_default_direct_cmd_desc - AQ descriptor helper function | * i40e_fill_default_direct_cmd_desc - AQ descriptor helper function | ||||
* @desc: pointer to the temp descriptor (non DMA mem) | * @desc: pointer to the temp descriptor (non DMA mem) | ||||
* @opcode: the opcode can be used to decide which flags to turn off or on | * @opcode: the opcode can be used to decide which flags to turn off or on | ||||
* | * | ||||
Show All 27 Lines | enum i40e_status_code i40e_clean_arq_element(struct i40e_hw *hw, | ||||
u16 ntc = hw->aq.arq.next_to_clean; | u16 ntc = hw->aq.arq.next_to_clean; | ||||
struct i40e_aq_desc *desc; | struct i40e_aq_desc *desc; | ||||
struct i40e_dma_mem *bi; | struct i40e_dma_mem *bi; | ||||
u16 desc_idx; | u16 desc_idx; | ||||
u16 datalen; | u16 datalen; | ||||
u16 flags; | u16 flags; | ||||
u16 ntu; | u16 ntu; | ||||
/* pre-clean the event info */ | |||||
i40e_memset(&e->desc, 0, sizeof(e->desc), I40E_NONDMA_MEM); | |||||
/* take the lock before we start messing with the ring */ | /* take the lock before we start messing with the ring */ | ||||
i40e_acquire_spinlock(&hw->aq.arq_spinlock); | i40e_acquire_spinlock(&hw->aq.arq_spinlock); | ||||
if (hw->aq.arq.count == 0) { | |||||
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, | |||||
"AQRX: Admin queue not initialized.\n"); | |||||
ret_code = I40E_ERR_QUEUE_EMPTY; | |||||
goto clean_arq_element_err; | |||||
} | |||||
/* set next_to_use to head */ | /* set next_to_use to head */ | ||||
if (!i40e_is_vf(hw)) | if (!i40e_is_vf(hw)) | ||||
ntu = (rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK); | ntu = (rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK); | ||||
if (i40e_is_vf(hw)) | if (i40e_is_vf(hw)) | ||||
ntu = (rd32(hw, hw->aq.arq.head) & I40E_VF_ARQH1_ARQH_MASK); | ntu = (rd32(hw, hw->aq.arq.head) & I40E_VF_ARQH1_ARQH_MASK); | ||||
if (ntu == ntc) { | if (ntu == ntc) { | ||||
/* nothing to do - shouldn't need to update ring's values */ | /* nothing to do - shouldn't need to update ring's values */ | ||||
ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK; | ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | enum i40e_status_code i40e_clean_arq_element(struct i40e_hw *hw, | ||||
wr32(hw, hw->aq.arq.tail, ntc); | wr32(hw, hw->aq.arq.tail, ntc); | ||||
/* ntc is updated to tail + 1 */ | /* ntc is updated to tail + 1 */ | ||||
ntc++; | ntc++; | ||||
if (ntc == hw->aq.num_arq_entries) | if (ntc == hw->aq.num_arq_entries) | ||||
ntc = 0; | ntc = 0; | ||||
hw->aq.arq.next_to_clean = ntc; | hw->aq.arq.next_to_clean = ntc; | ||||
hw->aq.arq.next_to_use = ntu; | hw->aq.arq.next_to_use = ntu; | ||||
clean_arq_element_out: | |||||
/* Set pending if needed, unlock and return */ | |||||
if (pending != NULL) | |||||
*pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc); | |||||
i40e_release_spinlock(&hw->aq.arq_spinlock); | |||||
if (i40e_is_nvm_update_op(&e->desc)) { | if (i40e_is_nvm_update_op(&e->desc)) { | ||||
if (hw->aq.nvm_release_on_done) { | if (hw->aq.nvm_release_on_done) { | ||||
i40e_release_nvm(hw); | i40e_release_nvm(hw); | ||||
hw->aq.nvm_release_on_done = FALSE; | hw->aq.nvm_release_on_done = FALSE; | ||||
} | } | ||||
switch (hw->nvmupd_state) { | switch (hw->nvmupd_state) { | ||||
case I40E_NVMUPD_STATE_INIT_WAIT: | case I40E_NVMUPD_STATE_INIT_WAIT: | ||||
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; | hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; | ||||
break; | break; | ||||
case I40E_NVMUPD_STATE_WRITE_WAIT: | case I40E_NVMUPD_STATE_WRITE_WAIT: | ||||
hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; | hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
clean_arq_element_out: | |||||
/* Set pending if needed, unlock and return */ | |||||
if (pending != NULL) | |||||
*pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc); | |||||
clean_arq_element_err: | |||||
i40e_release_spinlock(&hw->aq.arq_spinlock); | |||||
return ret_code; | return ret_code; | ||||
} | } | ||||
void i40e_resume_aq(struct i40e_hw *hw) | |||||
{ | |||||
/* Registers are reset after PF reset */ | |||||
hw->aq.asq.next_to_use = 0; | |||||
hw->aq.asq.next_to_clean = 0; | |||||
i40e_config_asq_regs(hw); | |||||
hw->aq.arq.next_to_use = 0; | |||||
hw->aq.arq.next_to_clean = 0; | |||||
i40e_config_arq_regs(hw); | |||||
} |