// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */
#include "ice_common.h"
/**
* ice_adminq_init_regs - Initialize AdminQ registers
* @hw: pointer to the hardware structure
*
* This assumes the alloc_sq and alloc_rq functions have already been called
*/
static void ice_adminq_init_regs(struct ice_hw *hw)
{
struct ice_ctl_q_info *cq = &hw->adminq;
cq->sq.head = PF_FW_ATQH;
cq->sq.tail = PF_FW_ATQT;
cq->sq.len = PF_FW_ATQLEN;
cq->sq.bah = PF_FW_ATQBAH;
cq->sq.bal = PF_FW_ATQBAL;
cq->sq.len_mask = PF_FW_ATQLEN_ATQLEN_M;
cq->sq.len_ena_mask = PF_FW_ATQLEN_ATQENABLE_M;
cq->sq.head_mask = PF_FW_ATQH_ATQH_M;
cq->rq.head = PF_FW_ARQH;
cq->rq.tail = PF_FW_ARQT;
cq->rq.len = PF_FW_ARQLEN;
cq->rq.bah = PF_FW_ARQBAH;
cq->rq.bal = PF_FW_ARQBAL;
cq->rq.len_mask = PF_FW_ARQLEN_ARQLEN_M;
cq->rq.len_ena_mask = PF_FW_ARQLEN_ARQENABLE_M;
cq->rq.head_mask = PF_FW_ARQH_ARQH_M;
}
/**
* ice_check_sq_alive
* @hw: pointer to the hw struct
* @cq: pointer to the specific Control queue
*
* Returns true if Queue is enabled else false.
*/
bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
/* check both queue-length and queue-enable fields */
if (cq->sq.len && cq->sq.len_mask && cq->sq.len_ena_mask)
return (rd32(hw, cq->sq.len) & (cq->sq.len_mask |
cq->sq.len_ena_mask)) ==
(cq->num_sq_entries | cq->sq.len_ena_mask);
return false;
}
/**
* ice_alloc_ctrlq_sq_ring - Allocate Control Transmit Queue (ATQ) rings
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*/
static enum ice_status
ice_alloc_ctrlq_sq_ring(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
size_t size = cq->num_sq_entries * sizeof(struct ice_aq_desc);
cq->sq.desc_buf.va = dmam_alloc_coherent(ice_hw_to_dev(hw), size,
&cq->sq.desc_buf.pa,
GFP_KERNEL | __GFP_ZERO);
if (!cq->sq.desc_buf.va)
return ICE_ERR_NO_MEMORY;
cq->sq.desc_buf.size = size;
cq->sq.cmd_buf = devm_kcalloc(ice_hw_to_dev(hw), cq->num_sq_entries,
sizeof(struct ice_sq_cd), GFP_KERNEL);
if (!cq->sq.cmd_buf) {
dmam_free_coherent(ice_hw_to_dev(hw), cq->sq.desc_buf.size,
cq->sq.desc_buf.va, cq->sq.desc_buf.pa);
cq->sq.desc_buf.va = NULL;
cq->sq.desc_buf.pa = 0;
cq->sq.desc_buf.size = 0;
return ICE_ERR_NO_MEMORY;
}
return 0;
}
/**
* ice_alloc_ctrlq_rq_ring - Allocate Control Receive Queue (ARQ) rings
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*/
static enum ice_status
ice_alloc_ctrlq_rq_ring(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
size_t size = cq->num_rq_entries * sizeof(struct ice_aq_desc);
cq->rq.desc_buf.va = dmam_alloc_coherent(ice_hw_to_dev(hw), size,
&cq->rq.desc_buf.pa,
GFP_KERNEL | __GFP_ZERO);
if (!cq->rq.desc_buf.va)
return ICE_ERR_NO_MEMORY;
cq->rq.desc_buf.size = size;
return 0;
}
/**
* ice_free_ctrlq_sq_ring - Free Control Transmit Queue (ATQ) rings
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*
* This assumes the posted send buffers have already been cleaned
* and de-allocated
*/
static void ice_free_ctrlq_sq_ring(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
dmam_free_coherent(ice_hw_to_dev(hw), cq->sq.desc_buf.size,
cq->sq.desc_buf.va, cq->sq.desc_buf.pa);
cq->sq.desc_buf.va = NULL;
cq->sq.desc_buf.pa = 0;
cq->sq.desc_buf.size = 0;
}
/**
* ice_free_ctrlq_rq_ring - Free Control Receive Queue (ARQ) rings
* @hw: pointer to the hardware structure
* @cq: pointer to the specific Control queue
*
* This assumes the posted receive buffers have already been cleaned
* and de-allocated
*/
static void ice_free_ctrlq_rq_ring(struct ice_hw *hw, struct ice_ctl_q_info *cq)
{
dmam_free_coherent(ice_hw_to_dev(hw), cq->rq.desc_buf.size,
cq->rq.desc_buf.va, cq->rq.desc_buf.pa);
cq->rq.desc_buf.va = NULL;
cq->