// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */
#include "ice_common.h"
#define ICE_CQ_INIT_REGS(qinfo, prefix) \
do { \
(qinfo)->sq.head = prefix##_ATQH; \
(qinfo)->sq.tail = prefix##_ATQT; \
(qinfo)->sq.len = prefix##_ATQLEN; \
(qinfo)->sq.bah = prefix##_ATQBAH; \
(qinfo)->sq.bal = prefix##_ATQBAL; \
(qinfo)->sq.len_mask = prefix##_ATQLEN_ATQLEN_M; \
(qinfo)->sq.len_ena_mask = prefix##_ATQLEN_ATQENABLE_M; \
(qinfo)->sq.head_mask = prefix##_ATQH_ATQH_M; \
(qinfo)->rq.head = prefix##_ARQH; \
(qinfo)->rq.tail = prefix##_ARQT; \
(qinfo)->rq.len = prefix##_ARQLEN; \
(qinfo)->rq.bah = prefix##_ARQBAH; \
(qinfo)->rq.bal = prefix##_ARQBAL; \
(qinfo)->rq.len_mask = prefix##_ARQLEN_ARQLEN_M; \
(qinfo)->rq.len_ena_mask = prefix##_ARQLEN_ARQENABLE_M; \
(qinfo)->rq.head_mask = prefix##_ARQH_ARQH_M; \
} while (0)
/**
* 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;
ICE_CQ_INIT_REGS(cq, PF_FW);
}
/**
* ice_mailbox_init_regs - Initialize Mailbox registers
* @hw: pointer to the hardware structure
*
* This assumes the alloc_sq and alloc_rq functions have already been called
*/
static void ice_mailbox_init_regs(struct ice_hw *hw)
{
struct ice_ctl_q_info *cq = &hw->mailboxq;
ICE_CQ_INIT_REGS(cq, PF_MBX);
}
/**
* 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_cq_ring - Free control queue ring
* @hw: pointer to the hardware structure
* @ring: pointer to the specific control queue ring
*
* This assumes the posted buffers have already been cleaned
* and de-allocated
*/
static void ice_free_cq_ring(struct ice_hw *hw, struct ice_ctl_q_ring *ring)
{
dmam_free_coherent(ice_hw_to_dev(hw), ring->desc_buf.size,
ring->desc_buf.va, ring->desc_buf.pa);
ring->desc_buf.va = NULL;
ring->desc_buf.pa = 0;
ring->desc_buf.size = 0;
}
/**
* ice_alloc_rq_bufs - Allocate pre-posted buffers for the ARQ
* @hw: pointer to t