Refactor ice_sq_send_cmd() and ice_shutdown_sq() to be able to use a simpler locking, e.g. for new methods, which depend on the control queue.
Reviewed-by: Milena Olech <[email protected]> Signed-off-by: Karol Kolacinski <[email protected]> --- drivers/net/ethernet/intel/ice/ice_controlq.c | 155 ++++++++---------- 1 file changed, 72 insertions(+), 83 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c index 5fb3a8441beb..fb7e1218797c 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.c +++ b/drivers/net/ethernet/intel/ice/ice_controlq.c @@ -456,35 +456,34 @@ static int ice_init_rq(struct ice_hw *hw, struct ice_ctl_q_info *cq) * @hw: pointer to the hardware structure * @cq: pointer to the specific Control queue * - * The main shutdown routine for the Control Transmit Queue + * The main shutdown routine for the Control Transmit Queue. + * + * Return: + * * %0 - success + * * %-EBUSY - no send queue descriptors */ static int ice_shutdown_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq) { - int ret_code = 0; + if (!cq->sq.count) + return -EBUSY; mutex_lock(&cq->sq_lock); - if (!cq->sq.count) { - ret_code = -EBUSY; - goto shutdown_sq_out; - } - /* Stop processing of the control queue */ wr32(hw, cq->sq.head, 0); wr32(hw, cq->sq.tail, 0); wr32(hw, cq->sq.len, 0); wr32(hw, cq->sq.bal, 0); wr32(hw, cq->sq.bah, 0); - cq->sq.count = 0; /* to indicate uninitialized queue */ + mutex_unlock(&cq->sq_lock); + /* free ring buffers and the ring itself */ ICE_FREE_CQ_BUFS(hw, cq, sq); ice_free_cq_ring(hw, &cq->sq); -shutdown_sq_out: - mutex_unlock(&cq->sq_lock); - return ret_code; + return 0; } /** @@ -990,56 +989,55 @@ static bool ice_sq_done(struct ice_hw *hw, struct ice_ctl_q_info *cq) * Main command for the transmit side of a control queue. It puts the command * on the queue, bumps the tail, waits for processing of the command, captures * command status and results, etc. + * + * Return: + * * %0 - success + * * %-EIO - incorrect control send queue state, timeout or FW error + * * %-EINVAL - incorrect arguments + * * %-ENOSPC - control send queue is full */ -int -ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, - struct libie_aq_desc *desc, void *buf, u16 buf_size, - struct ice_sq_cd *cd) +int ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, + struct libie_aq_desc *desc, void *buf, u16 buf_size, + struct ice_sq_cd *cd) { - struct ice_dma_mem *dma_buf = NULL; struct libie_aq_desc *desc_on_ring; - bool cmd_completed = false; - int status = 0; - u16 retval = 0; - u32 val = 0; - - /* if reset is in progress return a soft error */ + struct ice_dma_mem *dma_buf; + int err = 0; + u32 val; + /* If reset is in progress return a soft error. */ if (hw->reset_ongoing) return -EBUSY; - mutex_lock(&cq->sq_lock); + if (!buf && buf_size) + return -EINVAL; + + mutex_lock(&cq->sq_lock); cq->sq_last_status = LIBIE_AQ_RC_OK; if (!cq->sq.count) { ice_debug(hw, ICE_DBG_AQ_MSG, "Control Send queue not initialized.\n"); - status = -EIO; - goto sq_send_command_error; - } - - if ((buf && !buf_size) || (!buf && buf_size)) { - status = -EINVAL; - goto sq_send_command_error; + err = -EIO; + goto err; } if (buf) { - if (buf_size > cq->sq_buf_size) { + if (!buf_size || buf_size > cq->sq_buf_size) { ice_debug(hw, ICE_DBG_AQ_MSG, "Invalid buffer size for Control Send queue: %d.\n", buf_size); - status = -EINVAL; - goto sq_send_command_error; + err = -EINVAL; + goto err; } desc->flags |= cpu_to_le16(LIBIE_AQ_FLAG_BUF); if (buf_size > LIBIE_AQ_LG_BUF) desc->flags |= cpu_to_le16(LIBIE_AQ_FLAG_LB); } - val = rd32(hw, cq->sq.head); if (val >= cq->num_sq_entries) { ice_debug(hw, ICE_DBG_AQ_MSG, "head overrun at %d in the Control Send Queue ring\n", val); - status = -EIO; - goto sq_send_command_error; + err = -EIO; + goto err; } /* Call clean and check queue available function to reclaim the @@ -1049,25 +1047,23 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, */ if (ice_clean_sq(hw, cq) == 0) { ice_debug(hw, ICE_DBG_AQ_MSG, "Error: Control Send Queue is full.\n"); - status = -ENOSPC; - goto sq_send_command_error; + err = -ENOSPC; + goto err; } - /* initialize the temp desc pointer with the right desc */ + /* Initialize the desc_on_ring with the right descriptor. */ desc_on_ring = ICE_CTL_Q_DESC(cq->sq, cq->sq.next_to_use); - - /* if the desc is available copy the temp desc to the right place */ memcpy(desc_on_ring, desc, sizeof(*desc_on_ring)); - /* if buf is not NULL assume indirect command */ + /* If buf is not NULL, assume indirect command. */ if (buf) { dma_buf = &cq->sq.r.sq_bi[cq->sq.next_to_use]; - /* copy the user buf into the respective DMA buf */ + /* Copy the user buf into the respective DMA buf. */ memcpy(dma_buf->va, buf, buf_size); desc_on_ring->datalen = cpu_to_le16(buf_size); - /* Update the address values in the desc with the pa value - * for respective buffer + /* Update the address values in the desc with the pa value for + * respective buffer. */ desc_on_ring->params.generic.addr_high = cpu_to_le32(upper_32_bits(dma_buf->pa)); @@ -1075,9 +1071,7 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, cpu_to_le32(lower_32_bits(dma_buf->pa)); } - /* Debug desc and buffer */ ice_debug(hw, ICE_DBG_AQ_DESC, "ATQ: Control Send queue desc and buffer:\n"); - ice_debug_cq(hw, cq, (void *)desc_on_ring, buf, buf_size, false); (cq->sq.next_to_use)++; @@ -1086,65 +1080,60 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, wr32(hw, cq->sq.tail, cq->sq.next_to_use); ice_flush(hw); - /* If the message is posted, don't wait for completion. */ - if (cd && cd->postpone) - goto sq_send_command_error; - - /* Wait for the command to complete. If it finishes within the - * timeout, copy the descriptor back to temp. - */ - if (ice_sq_done(hw, cq)) { + if (cd && cd->postpone) { + /* If the message is postponed, don't wait for completion. */ + ice_debug(hw, ICE_DBG_AQ_MSG, "ATQ: Skipping completion\n"); + } else if (ice_sq_done(hw, cq)) { + /* Wait for the command to complete. If it finishes within + * the timeout, copy the descriptor back to temp. + */ memcpy(desc, desc_on_ring, sizeof(*desc)); if (buf) { - /* get returned length to copy */ + /* Get returned length to copy. */ u16 copy_size = le16_to_cpu(desc->datalen); if (copy_size > buf_size) { ice_debug(hw, ICE_DBG_AQ_MSG, "Return len %d > than buf len %d\n", copy_size, buf_size); - status = -EIO; + err = -EIO; } else { memcpy(buf, dma_buf->va, copy_size); } } - retval = le16_to_cpu(desc->retval); - if (retval) { + + /* Strip off FW internal code. */ + cq->sq_last_status = + (enum libie_aq_err)(le16_to_cpu(desc->retval) & 0xFF); + if (cq->sq_last_status) { ice_debug(hw, ICE_DBG_AQ_MSG, "Control Send Queue command 0x%04X completed with error 0x%X\n", le16_to_cpu(desc->opcode), - retval); - - /* strip off FW internal code */ - retval &= 0xff; + cq->sq_last_status); + err = -EIO; } - cmd_completed = true; - if (!status && retval != LIBIE_AQ_RC_OK) - status = -EIO; - cq->sq_last_status = (enum libie_aq_err)retval; - } - - ice_debug(hw, ICE_DBG_AQ_MSG, "ATQ: desc and buffer writeback:\n"); - ice_debug_cq(hw, cq, (void *)desc, buf, buf_size, true); + if (err) + goto err; - /* save writeback AQ if requested */ - if (cd && cd->wb_desc) - memcpy(cd->wb_desc, desc_on_ring, sizeof(*cd->wb_desc)); + ice_debug(hw, ICE_DBG_AQ_MSG, "ATQ: desc and buffer writeback:\n"); + ice_debug_cq(hw, cq, (void *)desc, buf, buf_size, true); - /* update the error if time out occurred */ - if (!cmd_completed) { + /* Save writeback AQ if requested. */ + if (cd && cd->wb_desc) + memcpy(cd->wb_desc, desc_on_ring, sizeof(*cd->wb_desc)); + } else { + /* Update the error if timeout occurred. */ if (rd32(hw, cq->rq.len) & cq->rq.len_crit_mask || - rd32(hw, cq->sq.len) & cq->sq.len_crit_mask) { + rd32(hw, cq->sq.len) & cq->sq.len_crit_mask) ice_debug(hw, ICE_DBG_AQ_MSG, "Critical FW error.\n"); - status = -EIO; - } else { + else ice_debug(hw, ICE_DBG_AQ_MSG, "Control Send Queue Writeback timeout.\n"); - status = -EIO; - } + + err = -EIO; } -sq_send_command_error: +err: mutex_unlock(&cq->sq_lock); - return status; + return err; } /** -- 2.49.0
