src/dpdk/drivers/common/iavf/iavf_adminq.c
enum iavf_status iavf_asq_send_command(struct iavf_hw *hw,
				struct iavf_aq_desc *desc,
				void *buff, /* can be NULL */
				u16  buff_size,
				struct iavf_asq_cmd_details *cmd_details)
{
	enum iavf_status status = IAVF_SUCCESS;
	struct iavf_dma_mem *dma_buff = NULL;
	struct iavf_asq_cmd_details *details;
	struct iavf_aq_desc *desc_on_ring;
	bool cmd_completed = false;
	u16  retval = 0;
	u32  val = 0;

	iavf_acquire_spinlock(&hw->aq.asq_spinlock);

	hw->aq.asq_last_status = IAVF_AQ_RC_OK;

	if (hw->aq.asq.count == 0) {
		iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Admin queue not initialized.\n");
		status = IAVF_ERR_QUEUE_EMPTY;
		goto asq_send_command_error;
	}

	val = rd32(hw, hw->aq.asq.head);
	if (val >= hw->aq.num_asq_entries) {
		iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: head overrun at %d\n", val);
		status = IAVF_ERR_QUEUE_EMPTY;
		goto asq_send_command_error;
	}

	details = IAVF_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
	if (cmd_details) {
		iavf_memcpy(details,
			    cmd_details,
			    sizeof(struct iavf_asq_cmd_details),
			    IAVF_NONDMA_TO_NONDMA);

		/* If the cmd_details are defined copy the cookie.  The
		 * CPU_TO_LE32 is not needed here because the data is ignored
		 * by the FW, only used by the driver
		 */
		if (details->cookie) {
			desc->cookie_high =
				CPU_TO_LE32(IAVF_HI_DWORD(details->cookie));
			desc->cookie_low =
				CPU_TO_LE32(IAVF_LO_DWORD(details->cookie));
		}
	} else {
		iavf_memset(details, 0,
			    sizeof(struct iavf_asq_cmd_details),
			    IAVF_NONDMA_MEM);
	}

	/* 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_ena);

	if (buff_size > hw->aq.asq_buf_size) {
		iavf_debug(hw,
			   IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Invalid buffer size: %d.\n",
			   buff_size);
		status = IAVF_ERR_INVALID_SIZE;
		goto asq_send_command_error;
	}

	if (details->postpone && !details->async) {
		iavf_debug(hw,
			   IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Async flag not set along with postpone flag");
		status = IAVF_ERR_PARAM;
		goto asq_send_command_error;
	}

	/* call clean and check queue available function to reclaim the
	 * descriptors that were processed by FW, the function returns the
	 * number of desc available
	 */
	/* the clean function called here could be called in a separate thread
	 * in case of asynchronous completions
	 */
	if (iavf_clean_asq(hw) == 0) {
		iavf_debug(hw,
			   IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Error queue is full.\n");
		status = IAVF_ERR_ADMIN_QUEUE_FULL;
		goto asq_send_command_error;
	}

	/* initialize the temp desc pointer with the right desc */
	desc_on_ring = IAVF_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);

	/* if the desc is available copy the temp desc to the right place */
	iavf_memcpy(desc_on_ring, desc, sizeof(struct iavf_aq_desc),
		    IAVF_NONDMA_TO_DMA);

	/* if buff is not NULL assume indirect command */
	if (buff != NULL) {
		dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
		/* copy the user buff into the respective DMA buff */
		iavf_memcpy(dma_buff->va, buff, buff_size,
			    IAVF_NONDMA_TO_DMA);
		desc_on_ring->datalen = CPU_TO_LE16(buff_size);

		/* Update the address values in the desc with the pa value
		 * for respective buffer
		 */
		desc_on_ring->params.external.addr_high =
				CPU_TO_LE32(IAVF_HI_DWORD(dma_buff->pa));
		desc_on_ring->params.external.addr_low =
				CPU_TO_LE32(IAVF_LO_DWORD(dma_buff->pa));
	}

	/* bump the tail */
	iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
	iavf_debug_aq(hw, IAVF_DEBUG_AQ_COMMAND, (void *)desc_on_ring,
		      buff, buff_size);
	(hw->aq.asq.next_to_use)++;
	if (hw->aq.asq.next_to_use == hw->aq.asq.count)
		hw->aq.asq.next_to_use = 0;
	if (!details->postpone)
		wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);

	/* if cmd_details are not defined or async flag is not set,
	 * we need to wait for desc write back
	 */
	if (!details->async && !details->postpone) {
		u32 total_delay = 0;

		do {
			/* AQ designers suggest use of head for better
			 * timing reliability than DD bit
			 */
			if (iavf_asq_done(hw))
				break;
			iavf_usec_delay(50);
			total_delay += 50;
		} while (total_delay < hw->aq.asq_cmd_timeout);
	}

	/* if ready, copy the desc back to temp */
	if (iavf_asq_done(hw)) {
		iavf_memcpy(desc, desc_on_ring, sizeof(struct iavf_aq_desc),
			    IAVF_DMA_TO_NONDMA);
		if (buff != NULL)
			iavf_memcpy(buff, dma_buff->va, buff_size,
				    IAVF_DMA_TO_NONDMA);
		retval = LE16_TO_CPU(desc->retval);
		if (retval != 0) {
			iavf_debug(hw,
				   IAVF_DEBUG_AQ_MESSAGE,
				   "AQTX: Command completed with error 0x%X.\n",
				   retval);

			/* strip off FW internal code */
			retval &= 0xff;
		}
		cmd_completed = true;
		if ((enum iavf_admin_queue_err)retval == IAVF_AQ_RC_OK)
			status = IAVF_SUCCESS;
		else if ((enum iavf_admin_queue_err)retval == IAVF_AQ_RC_EBUSY)
			status = IAVF_ERR_NOT_READY;
		else
			status = IAVF_ERR_ADMIN_QUEUE_ERROR;
		hw->aq.asq_last_status = (enum iavf_admin_queue_err)retval;
	}

	iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
		   "AQTX: desc and buffer writeback:\n");
	iavf_debug_aq(hw, IAVF_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size);

	/* save writeback aq if requested */
	if (details->wb_desc)
		iavf_memcpy(details->wb_desc, desc_on_ring,
			    sizeof(struct iavf_aq_desc), IAVF_DMA_TO_NONDMA);

	/* update the error if time out occurred */
	if ((!cmd_completed) &&
	    (!details->async && !details->postpone)) {
		if (rd32(hw, hw->aq.asq.len) & IAVF_VF_ATQLEN1_ATQCRIT_MASK) {
			iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
				   "AQTX: AQ Critical error.\n");
			status = IAVF_ERR_ADMIN_QUEUE_CRITICAL_ERROR;
		} else {
			iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
				   "AQTX: Writeback timeout.\n");
			status = IAVF_ERR_ADMIN_QUEUE_TIMEOUT;
		}
	}

asq_send_command_error:
	iavf_release_spinlock(&hw->aq.asq_spinlock);
	return status;
}
/**
 *  iavf_asq_send_command - send command to Admin Queue
 *  @hw: pointer to the hw struct
 *  @desc: prefilled descriptor describing the command (non DMA mem)
 *  @buff: buffer to use for indirect commands
 *  @buff_size: size of buffer for indirect commands
 *  @cmd_details: pointer to command details structure
 *
 *  This is the main send command driver routine for the Admin Queue send
 *  queue.  It runs the queue, cleans the queue, etc
 **/


This is the main send command driver routine for the Admin Queue send
queue.  It runs the queue, cleans the queue, etc
This is the main send command driver routine for the Admin Queue send queue . It runs the queue cleans the queue etc
enum iavf_status iavf_asq_send_command(struct iavf_hw *hw,
				struct iavf_aq_desc *desc,
				void *buff, 
				u16  buff_size,
				struct iavf_asq_cmd_details *cmd_details)
{
	enum iavf_status status = IAVF_SUCCESS;
	struct iavf_dma_mem *dma_buff = NULL;
	struct iavf_asq_cmd_details *details;
	struct iavf_aq_desc *desc_on_ring;
	bool cmd_completed = false;
	u16  retval = 0;
	u32  val = 0;
	iavf_acquire_spinlock(&hw->aq.asq_spinlock);
	hw->aq.asq_last_status = IAVF_AQ_RC_OK;
	if (hw->aq.asq.count == 0) {
		iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Admin queue not initialized.\n");
		status = IAVF_ERR_QUEUE_EMPTY;
		goto asq_send_command_error;
	}
	val = rd32(hw, hw->aq.asq.head);
	if (val >= hw->aq.num_asq_entries) {
		iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: head overrun at %d\n", val);
		status = IAVF_ERR_QUEUE_EMPTY;
		goto asq_send_command_error;
	}
	details = IAVF_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
	if (cmd_details) {
		iavf_memcpy(details,
			    cmd_details,
			    sizeof(struct iavf_asq_cmd_details),
			    IAVF_NONDMA_TO_NONDMA);
		if (details->cookie) {
			desc->cookie_high =
				CPU_TO_LE32(IAVF_HI_DWORD(details->cookie));
			desc->cookie_low =
				CPU_TO_LE32(IAVF_LO_DWORD(details->cookie));
		}
	} else {
		iavf_memset(details, 0,
			    sizeof(struct iavf_asq_cmd_details),
			    IAVF_NONDMA_MEM);
	}
	desc->flags &= ~CPU_TO_LE16(details->flags_dis);
	desc->flags |= CPU_TO_LE16(details->flags_ena);
	if (buff_size > hw->aq.asq_buf_size) {
		iavf_debug(hw,
			   IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Invalid buffer size: %d.\n",
			   buff_size);
		status = IAVF_ERR_INVALID_SIZE;
		goto asq_send_command_error;
	}
	if (details->postpone && !details->async) {
		iavf_debug(hw,
			   IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Async flag not set along with postpone flag");
		status = IAVF_ERR_PARAM;
		goto asq_send_command_error;
	}
	if (iavf_clean_asq(hw) == 0) {
		iavf_debug(hw,
			   IAVF_DEBUG_AQ_MESSAGE,
			   "AQTX: Error queue is full.\n");
		status = IAVF_ERR_ADMIN_QUEUE_FULL;
		goto asq_send_command_error;
	}
	desc_on_ring = IAVF_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
	iavf_memcpy(desc_on_ring, desc, sizeof(struct iavf_aq_desc),
		    IAVF_NONDMA_TO_DMA);
	if (buff != NULL) {
		dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
		iavf_memcpy(dma_buff->va, buff, buff_size,
			    IAVF_NONDMA_TO_DMA);
		desc_on_ring->datalen = CPU_TO_LE16(buff_size);
		desc_on_ring->params.external.addr_high =
				CPU_TO_LE32(IAVF_HI_DWORD(dma_buff->pa));
		desc_on_ring->params.external.addr_low =
				CPU_TO_LE32(IAVF_LO_DWORD(dma_buff->pa));
	}
	iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
	iavf_debug_aq(hw, IAVF_DEBUG_AQ_COMMAND, (void *)desc_on_ring,
		      buff, buff_size);
	(hw->aq.asq.next_to_use)++;
	if (hw->aq.asq.next_to_use == hw->aq.asq.count)
		hw->aq.asq.next_to_use = 0;
	if (!details->postpone)
		wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);
	if (!details->async && !details->postpone) {
		u32 total_delay = 0;
		do {
			if (iavf_asq_done(hw))
				break;
			iavf_usec_delay(50);
			total_delay += 50;
		} while (total_delay < hw->aq.asq_cmd_timeout);
	}
	if (iavf_asq_done(hw)) {
		iavf_memcpy(desc, desc_on_ring, sizeof(struct iavf_aq_desc),
			    IAVF_DMA_TO_NONDMA);
		if (buff != NULL)
			iavf_memcpy(buff, dma_buff->va, buff_size,
				    IAVF_DMA_TO_NONDMA);
		retval = LE16_TO_CPU(desc->retval);
		if (retval != 0) {
			iavf_debug(hw,
				   IAVF_DEBUG_AQ_MESSAGE,
				   "AQTX: Command completed with error 0x%X.\n",
				   retval);
			retval &= 0xff;
		}
		cmd_completed = true;
		if ((enum iavf_admin_queue_err)retval == IAVF_AQ_RC_OK)
			status = IAVF_SUCCESS;
		else if ((enum iavf_admin_queue_err)retval == IAVF_AQ_RC_EBUSY)
			status = IAVF_ERR_NOT_READY;
		else
			status = IAVF_ERR_ADMIN_QUEUE_ERROR;
		hw->aq.asq_last_status = (enum iavf_admin_queue_err)retval;
	}
	iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
		   "AQTX: desc and buffer writeback:\n");
	iavf_debug_aq(hw, IAVF_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size);
	if (details->wb_desc)
		iavf_memcpy(details->wb_desc, desc_on_ring,
			    sizeof(struct iavf_aq_desc), IAVF_DMA_TO_NONDMA);
	if ((!cmd_completed) &&
	    (!details->async && !details->postpone)) {
		if (rd32(hw, hw->aq.asq.len) & IAVF_VF_ATQLEN1_ATQCRIT_MASK) {
			iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
				   "AQTX: AQ Critical error.\n");
			status = IAVF_ERR_ADMIN_QUEUE_CRITICAL_ERROR;
		} else {
			iavf_debug(hw, IAVF_DEBUG_AQ_MESSAGE,
				   "AQTX: Writeback timeout.\n");
			status = IAVF_ERR_ADMIN_QUEUE_TIMEOUT;
		}
	}
asq_send_command_error:
	iavf_release_spinlock(&hw->aq.asq_spinlock);
	return status;
}
enum iavf_status iavf_asq_send_command ( struct iavf_hw * hw , struct iavf_aq_desc * desc , void * buff , u16 buff_size , struct iavf_asq_cmd_details * cmd_details ) { enum iavf_status status = IAVF_SUCCESS ; struct iavf_dma_mem * dma_buff = NULL ; struct iavf_asq_cmd_details * details ; struct iavf_aq_desc * desc_on_ring ; bool cmd_completed = false ; u16 retval = 0 ; u32 val = 0 ; iavf_acquire_spinlock ( & hw -> aq . asq_spinlock ) ; hw -> aq . asq_last_status = IAVF_AQ_RC_OK ; if ( hw -> aq . asq . count == 0 ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " ) ; status = IAVF_ERR_QUEUE_EMPTY ; goto asq_send_command_error ; } val = rd32 ( hw , hw -> aq . asq . head ) ; if ( val >= hw -> aq . num_asq_entries ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " , val ) ; status = IAVF_ERR_QUEUE_EMPTY ; goto asq_send_command_error ; } details = IAVF_ADMINQ_DETAILS ( hw -> aq . asq , hw -> aq . asq . next_to_use ) ; if ( cmd_details ) { iavf_memcpy ( details , cmd_details , sizeof ( struct iavf_asq_cmd_details ) , IAVF_NONDMA_TO_NONDMA ) ; if ( details -> cookie ) { desc -> cookie_high = CPU_TO_LE32 ( IAVF_HI_DWORD ( details -> cookie ) ) ; desc -> cookie_low = CPU_TO_LE32 ( IAVF_LO_DWORD ( details -> cookie ) ) ; } } else { iavf_memset ( details , 0 , sizeof ( struct iavf_asq_cmd_details ) , IAVF_NONDMA_MEM ) ; } desc -> flags &= ~ CPU_TO_LE16 ( details -> flags_dis ) ; desc -> flags |= CPU_TO_LE16 ( details -> flags_ena ) ; if ( buff_size > hw -> aq . asq_buf_size ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " , buff_size ) ; status = IAVF_ERR_INVALID_SIZE ; goto asq_send_command_error ; } if ( details -> postpone && ! details -> async ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " " ) ; status = IAVF_ERR_PARAM ; goto asq_send_command_error ; } if ( iavf_clean_asq ( hw ) == 0 ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " ) ; status = IAVF_ERR_ADMIN_QUEUE_FULL ; goto asq_send_command_error ; } desc_on_ring = IAVF_ADMINQ_DESC ( hw -> aq . asq , hw -> aq . asq . next_to_use ) ; iavf_memcpy ( desc_on_ring , desc , sizeof ( struct iavf_aq_desc ) , IAVF_NONDMA_TO_DMA ) ; if ( buff != NULL ) { dma_buff = & ( hw -> aq . asq . r . asq_bi [ hw -> aq . asq . next_to_use ] ) ; iavf_memcpy ( dma_buff -> va , buff , buff_size , IAVF_NONDMA_TO_DMA ) ; desc_on_ring -> datalen = CPU_TO_LE16 ( buff_size ) ; desc_on_ring -> params . external . addr_high = CPU_TO_LE32 ( IAVF_HI_DWORD ( dma_buff -> pa ) ) ; desc_on_ring -> params . external . addr_low = CPU_TO_LE32 ( IAVF_LO_DWORD ( dma_buff -> pa ) ) ; } iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " ) ; iavf_debug_aq ( hw , IAVF_DEBUG_AQ_COMMAND , ( void * ) desc_on_ring , buff , buff_size ) ; ( hw -> aq . asq . next_to_use ) ++ ; if ( hw -> aq . asq . next_to_use == hw -> aq . asq . count ) hw -> aq . asq . next_to_use = 0 ; if ( ! details -> postpone ) wr32 ( hw , hw -> aq . asq . tail , hw -> aq . asq . next_to_use ) ; if ( ! details -> async && ! details -> postpone ) { u32 total_delay = 0 ; do { if ( iavf_asq_done ( hw ) ) break ; iavf_usec_delay ( 50 ) ; total_delay += 50 ; } while ( total_delay < hw -> aq . asq_cmd_timeout ) ; } if ( iavf_asq_done ( hw ) ) { iavf_memcpy ( desc , desc_on_ring , sizeof ( struct iavf_aq_desc ) , IAVF_DMA_TO_NONDMA ) ; if ( buff != NULL ) iavf_memcpy ( buff , dma_buff -> va , buff_size , IAVF_DMA_TO_NONDMA ) ; retval = LE16_TO_CPU ( desc -> retval ) ; if ( retval != 0 ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " , retval ) ; retval &= 0xff ; } cmd_completed = true ; if ( ( enum iavf_admin_queue_err ) retval == IAVF_AQ_RC_OK ) status = IAVF_SUCCESS ; else if ( ( enum iavf_admin_queue_err ) retval == IAVF_AQ_RC_EBUSY ) status = IAVF_ERR_NOT_READY ; else status = IAVF_ERR_ADMIN_QUEUE_ERROR ; hw -> aq . asq_last_status = ( enum iavf_admin_queue_err ) retval ; } iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " ) ; iavf_debug_aq ( hw , IAVF_DEBUG_AQ_COMMAND , ( void * ) desc , buff , buff_size ) ; if ( details -> wb_desc ) iavf_memcpy ( details -> wb_desc , desc_on_ring , sizeof ( struct iavf_aq_desc ) , IAVF_DMA_TO_NONDMA ) ; if ( ( ! cmd_completed ) && ( ! details -> async && ! details -> postpone ) ) { if ( rd32 ( hw , hw -> aq . asq . len ) & IAVF_VF_ATQLEN1_ATQCRIT_MASK ) { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " ) ; status = IAVF_ERR_ADMIN_QUEUE_CRITICAL_ERROR ; } else { iavf_debug ( hw , IAVF_DEBUG_AQ_MESSAGE , " \n " ) ; status = IAVF_ERR_ADMIN_QUEUE_TIMEOUT ; } } asq_send_command_error : iavf_release_spinlock ( & hw -> aq . asq_spinlock ) ; return status ; }
iavf_asq_send_command - send command to Admin Queue
  @hw: pointer to the hw struct
  @desc: prefilled descriptor describing the command (non DMA mem)
  @buff: buffer to use for indirect commands
  @buff_size: size of buffer for indirect commands
  @cmd_details: pointer to command details structure
iavf_asq_send_command - send command to Admin Queue @hw : pointer to the hw struct @desc : prefilled descriptor describing the command ( non DMA mem ) @buff : buffer to use for indirect commands @buff_size : size of buffer for indirect commands @cmd_details : pointer to command details structure
/* can be NULL */ /* If the cmd_details are defined copy the cookie.  The
		 * CPU_TO_LE32 is not needed here because the data is ignored
		 * by the FW, only used by the driver
		 */ /* clear requested flags and then set additional flags if defined */ /* call clean and check queue available function to reclaim the
	 * descriptors that were processed by FW, the function returns the
	 * number of desc available
	 */ /* the clean function called here could be called in a separate thread
	 * in case of asynchronous completions
	 */ /* initialize the temp desc pointer with the right desc */ /* if the desc is available copy the temp desc to the right place */ /* if buff is not NULL assume indirect command */ /* copy the user buff into the respective DMA buff */ /* Update the address values in the desc with the pa value
		 * for respective buffer
		 */ /* bump the tail */ /* if cmd_details are not defined or async flag is not set,
	 * we need to wait for desc write back
	 */ /* AQ designers suggest use of head for better
			 * timing reliability than DD bit
			 */ /* if ready, copy the desc back to temp */ /* strip off FW internal code */ /* save writeback aq if requested */ /* update the error if time out occurred */