aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/qlnx/qlnxe/ecore_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/qlnx/qlnxe/ecore_hw.c')
-rw-r--r--sys/dev/qlnx/qlnxe/ecore_hw.c225
1 files changed, 181 insertions, 44 deletions
diff --git a/sys/dev/qlnx/qlnxe/ecore_hw.c b/sys/dev/qlnx/qlnxe/ecore_hw.c
index 46293cddf0bb..c93161775a1e 100644
--- a/sys/dev/qlnx/qlnxe/ecore_hw.c
+++ b/sys/dev/qlnx/qlnxe/ecore_hw.c
@@ -40,6 +40,13 @@ __FBSDID("$FreeBSD$");
#include "ecore_utils.h"
#include "ecore_iov_api.h"
+#ifdef _NTDDK_
+#pragma warning(push)
+#pragma warning(disable : 28167)
+#pragma warning(disable : 28123)
+#pragma warning(disable : 28121)
+#endif
+
#ifndef ASIC_ONLY
#define ECORE_EMUL_FACTOR 2000
#define ECORE_FPGA_FACTOR 200
@@ -63,6 +70,12 @@ struct ecore_ptt_pool {
struct ecore_ptt ptts[PXP_EXTERNAL_BAR_PF_WINDOW_NUM];
};
+static void __ecore_ptt_pool_free(struct ecore_hwfn *p_hwfn)
+{
+ OSAL_FREE(p_hwfn->p_dev, p_hwfn->p_ptt_pool);
+ p_hwfn->p_ptt_pool = OSAL_NULL;
+}
+
enum _ecore_status_t ecore_ptt_pool_alloc(struct ecore_hwfn *p_hwfn)
{
struct ecore_ptt_pool *p_pool = OSAL_ALLOC(p_hwfn->p_dev,
@@ -90,10 +103,12 @@ enum _ecore_status_t ecore_ptt_pool_alloc(struct ecore_hwfn *p_hwfn)
p_hwfn->p_ptt_pool = p_pool;
#ifdef CONFIG_ECORE_LOCK_ALLOC
- OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_pool->lock);
+ if (OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_pool->lock)) {
+ __ecore_ptt_pool_free(p_hwfn);
+ return ECORE_NOMEM;
+ }
#endif
OSAL_SPIN_LOCK_INIT(&p_pool->lock);
-
return ECORE_SUCCESS;
}
@@ -114,11 +129,10 @@ void ecore_ptt_pool_free(struct ecore_hwfn *p_hwfn)
if (p_hwfn->p_ptt_pool)
OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->p_ptt_pool->lock);
#endif
- OSAL_FREE(p_hwfn->p_dev, p_hwfn->p_ptt_pool);
- p_hwfn->p_ptt_pool = OSAL_NULL;
+ __ecore_ptt_pool_free(p_hwfn);
}
-struct ecore_ptt *ecore_ptt_acquire(struct ecore_hwfn *p_hwfn)
+struct ecore_ptt *ecore_ptt_acquire(struct ecore_hwfn *p_hwfn)
{
struct ecore_ptt *p_ptt;
unsigned int i;
@@ -159,7 +173,7 @@ void ecore_ptt_release(struct ecore_hwfn *p_hwfn,
OSAL_SPIN_UNLOCK(&p_hwfn->p_ptt_pool->lock);
}
-u32 ecore_ptt_get_hw_addr(struct ecore_ptt *p_ptt)
+static u32 ecore_ptt_get_hw_addr(struct ecore_ptt *p_ptt)
{
/* The HW is using DWORDS and we need to translate it to Bytes */
return OSAL_LE32_TO_CPU(p_ptt->pxp.offset) << 2;
@@ -226,8 +240,8 @@ static u32 ecore_set_ptt(struct ecore_hwfn *p_hwfn,
return ecore_ptt_get_bar_addr(p_ptt) + offset;
}
-struct ecore_ptt *ecore_get_reserved_ptt(struct ecore_hwfn *p_hwfn,
- enum reserved_ptts ptt_idx)
+struct ecore_ptt *ecore_get_reserved_ptt(struct ecore_hwfn *p_hwfn,
+ enum reserved_ptts ptt_idx)
{
if (ptt_idx >= RESERVED_PTT_MAX) {
DP_NOTICE(p_hwfn, true,
@@ -538,11 +552,16 @@ enum _ecore_status_t ecore_hw_unlock(struct ecore_hwfn *p_hwfn,
#endif /* HW locks logic */
/* DMAE */
+
+#define ECORE_DMAE_FLAGS_IS_SET(params, flag) \
+ ((params) != OSAL_NULL && ((params)->flags & ECORE_DMAE_FLAG_##flag))
+
static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
const u8 is_src_type_grc,
const u8 is_dst_type_grc,
struct ecore_dmae_params *p_params)
{
+ u8 src_pfid, dst_pfid, port_id;
u16 opcode_b = 0;
u32 opcode = 0;
@@ -553,17 +572,21 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
opcode |= (is_src_type_grc ? DMAE_CMD_SRC_MASK_GRC
: DMAE_CMD_SRC_MASK_PCIE) <<
DMAE_CMD_SRC_SHIFT;
- opcode |= (p_hwfn->rel_pf_id & DMAE_CMD_SRC_PF_ID_MASK) <<
+ src_pfid = ECORE_DMAE_FLAGS_IS_SET(p_params, PF_SRC) ?
+ p_params->src_pfid : p_hwfn->rel_pf_id;
+ opcode |= (src_pfid & DMAE_CMD_SRC_PF_ID_MASK) <<
DMAE_CMD_SRC_PF_ID_SHIFT;
/* The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */
opcode |= (is_dst_type_grc ? DMAE_CMD_DST_MASK_GRC
: DMAE_CMD_DST_MASK_PCIE) <<
DMAE_CMD_DST_SHIFT;
- opcode |= (p_hwfn->rel_pf_id & DMAE_CMD_DST_PF_ID_MASK) <<
+ dst_pfid = ECORE_DMAE_FLAGS_IS_SET(p_params, PF_DST) ?
+ p_params->dst_pfid : p_hwfn->rel_pf_id;
+ opcode |= (dst_pfid & DMAE_CMD_DST_PF_ID_MASK) <<
DMAE_CMD_DST_PF_ID_SHIFT;
- /* DMAE_E4_TODO need to check which value to specifiy here. */
+ /* DMAE_E4_TODO need to check which value to specify here. */
/* opcode |= (!b_complete_to_host)<< DMAE_CMD_C_DST_SHIFT;*/
/* Whether to write a completion word to the completion destination:
@@ -574,7 +597,7 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
opcode |= DMAE_CMD_SRC_ADDR_RESET_MASK <<
DMAE_CMD_SRC_ADDR_RESET_SHIFT;
- if (p_params->flags & ECORE_DMAE_FLAG_COMPLETION_DST)
+ if (ECORE_DMAE_FLAGS_IS_SET(p_params, COMPLETION_DST))
opcode |= 1 << DMAE_CMD_COMP_FUNC_SHIFT;
/* swapping mode 3 - big endian there should be a define ifdefed in
@@ -582,7 +605,9 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
*/
opcode |= DMAE_CMD_ENDIANITY << DMAE_CMD_ENDIANITY_MODE_SHIFT;
- opcode |= p_hwfn->port_id << DMAE_CMD_PORT_ID_SHIFT;
+ port_id = (ECORE_DMAE_FLAGS_IS_SET(p_params, PORT)) ?
+ p_params->port_id : p_hwfn->port_id;
+ opcode |= port_id << DMAE_CMD_PORT_ID_SHIFT;
/* reset source address in next go */
opcode |= DMAE_CMD_SRC_ADDR_RESET_MASK <<
@@ -593,14 +618,14 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
DMAE_CMD_DST_ADDR_RESET_SHIFT;
/* SRC/DST VFID: all 1's - pf, otherwise VF id */
- if (p_params->flags & ECORE_DMAE_FLAG_VF_SRC) {
+ if (ECORE_DMAE_FLAGS_IS_SET(p_params, VF_SRC)) {
opcode |= (1 << DMAE_CMD_SRC_VF_ID_VALID_SHIFT);
opcode_b |= (p_params->src_vfid << DMAE_CMD_SRC_VF_ID_SHIFT);
} else {
opcode_b |= (DMAE_CMD_SRC_VF_ID_MASK <<
DMAE_CMD_SRC_VF_ID_SHIFT);
}
- if (p_params->flags & ECORE_DMAE_FLAG_VF_DST) {
+ if (ECORE_DMAE_FLAGS_IS_SET(p_params, VF_DST)) {
opcode |= 1 << DMAE_CMD_DST_VF_ID_VALID_SHIFT;
opcode_b |= p_params->dst_vfid << DMAE_CMD_DST_VF_ID_SHIFT;
} else {
@@ -690,7 +715,7 @@ enum _ecore_status_t ecore_dmae_info_alloc(struct ecore_hwfn *p_hwfn)
*p_comp = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev, p_addr, sizeof(u32));
if (*p_comp == OSAL_NULL) {
- DP_NOTICE(p_hwfn, true,
+ DP_NOTICE(p_hwfn, false,
"Failed to allocate `p_completion_word'\n");
goto err;
}
@@ -699,7 +724,7 @@ enum _ecore_status_t ecore_dmae_info_alloc(struct ecore_hwfn *p_hwfn)
*p_cmd = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev, p_addr,
sizeof(struct dmae_cmd));
if (*p_cmd == OSAL_NULL) {
- DP_NOTICE(p_hwfn, true,
+ DP_NOTICE(p_hwfn, false,
"Failed to allocate `struct dmae_cmd'\n");
goto err;
}
@@ -708,12 +733,13 @@ enum _ecore_status_t ecore_dmae_info_alloc(struct ecore_hwfn *p_hwfn)
*p_buff = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev, p_addr,
sizeof(u32) * DMAE_MAX_RW_SIZE);
if (*p_buff == OSAL_NULL) {
- DP_NOTICE(p_hwfn, true,
+ DP_NOTICE(p_hwfn, false,
"Failed to allocate `intermediate_buffer'\n");
goto err;
}
- p_hwfn->dmae_info.channel = p_hwfn->rel_pf_id;
+ p_hwfn->dmae_info.channel = p_hwfn->rel_pf_id;
+ p_hwfn->dmae_info.b_mem_ready = true;
return ECORE_SUCCESS;
err:
@@ -725,8 +751,9 @@ void ecore_dmae_info_free(struct ecore_hwfn *p_hwfn)
{
dma_addr_t p_phys;
- /* Just make sure no one is in the middle */
- OSAL_MUTEX_ACQUIRE(&p_hwfn->dmae_info.mutex);
+ OSAL_SPIN_LOCK(&p_hwfn->dmae_info.lock);
+ p_hwfn->dmae_info.b_mem_ready = false;
+ OSAL_SPIN_UNLOCK(&p_hwfn->dmae_info.lock);
if (p_hwfn->dmae_info.p_completion_word != OSAL_NULL) {
p_phys = p_hwfn->dmae_info.completion_word_phys_addr;
@@ -751,8 +778,6 @@ void ecore_dmae_info_free(struct ecore_hwfn *p_hwfn)
p_phys, sizeof(u32) * DMAE_MAX_RW_SIZE);
p_hwfn->dmae_info.p_intermediate_buffer = OSAL_NULL;
}
-
- OSAL_MUTEX_RELEASE(&p_hwfn->dmae_info.mutex);
}
static enum _ecore_status_t
@@ -844,17 +869,20 @@ static enum _ecore_status_t ecore_dmae_execute_sub_operation(struct ecore_hwfn *
}
cmd->length_dw = OSAL_CPU_TO_LE16((u16)length_dw);
+#ifndef __EXTRACT__LINUX__
if (src_type == ECORE_DMAE_ADDRESS_HOST_VIRT ||
src_type == ECORE_DMAE_ADDRESS_HOST_PHYS)
OSAL_DMA_SYNC(p_hwfn->p_dev,
(void *)HILO_U64(cmd->src_addr_hi,
cmd->src_addr_lo),
length_dw * sizeof(u32), false);
+#endif
ecore_dmae_post_command(p_hwfn, p_ptt);
ecore_status = ecore_dmae_operation_wait(p_hwfn);
+#ifndef __EXTRACT__LINUX__
/* TODO - is it true ? */
if (src_type == ECORE_DMAE_ADDRESS_HOST_VIRT ||
src_type == ECORE_DMAE_ADDRESS_HOST_PHYS)
@@ -862,12 +890,12 @@ static enum _ecore_status_t ecore_dmae_execute_sub_operation(struct ecore_hwfn *
(void *)HILO_U64(cmd->src_addr_hi,
cmd->src_addr_lo),
length_dw * sizeof(u32), true);
+#endif
if (ecore_status != ECORE_SUCCESS) {
DP_NOTICE(p_hwfn, ECORE_MSG_HW,
"Wait Failed. source_addr 0x%llx, grc_addr 0x%llx, size_in_dwords 0x%x, intermediate buffer 0x%llx.\n",
- (unsigned long long)src_addr,
- (unsigned long long)dst_addr, length_dw,
+ (unsigned long long)src_addr, (unsigned long long)dst_addr, length_dw,
(unsigned long long)p_hwfn->dmae_info.intermediate_buffer_phys_addr);
return ecore_status;
}
@@ -895,6 +923,14 @@ static enum _ecore_status_t ecore_dmae_execute_command(struct ecore_hwfn *p_hwfn
enum _ecore_status_t ecore_status = ECORE_SUCCESS;
u32 offset = 0;
+ if (!p_hwfn->dmae_info.b_mem_ready) {
+ DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
+ "No buffers allocated. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n",
+ (unsigned long long)src_addr, src_type, (unsigned long long)dst_addr, dst_type,
+ size_in_dwords);
+ return ECORE_NOMEM;
+ }
+
if (p_hwfn->p_dev->recov_in_prog) {
DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
"Recovery is in progress. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n",
@@ -906,6 +942,13 @@ static enum _ecore_status_t ecore_dmae_execute_command(struct ecore_hwfn *p_hwfn
return ECORE_SUCCESS;
}
+ if (!cmd) {
+ DP_NOTICE(p_hwfn, true,
+ "ecore_dmae_execute_sub_operation failed. Invalid state. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n",
+ (unsigned long long)src_addr, (unsigned long long)dst_addr, length_cur);
+ return ECORE_INVAL;
+ }
+
ecore_dmae_opcode(p_hwfn,
(src_type == ECORE_DMAE_ADDRESS_GRC),
(dst_type == ECORE_DMAE_ADDRESS_GRC),
@@ -925,7 +968,7 @@ static enum _ecore_status_t ecore_dmae_execute_command(struct ecore_hwfn *p_hwfn
for (i = 0; i <= cnt_split; i++) {
offset = length_limit * i;
- if (!(p_params->flags & ECORE_DMAE_FLAG_RW_REPL_SRC)) {
+ if (!ECORE_DMAE_FLAGS_IS_SET(p_params, RW_REPL_SRC)) {
if (src_type == ECORE_DMAE_ADDRESS_GRC)
src_addr_split = src_addr + offset;
else
@@ -968,24 +1011,20 @@ enum _ecore_status_t ecore_dmae_host2grc(struct ecore_hwfn *p_hwfn,
u64 source_addr,
u32 grc_addr,
u32 size_in_dwords,
- u32 flags)
+ struct ecore_dmae_params *p_params)
{
u32 grc_addr_in_dw = grc_addr / sizeof(u32);
- struct ecore_dmae_params params;
enum _ecore_status_t rc;
- OSAL_MEMSET(&params, 0, sizeof(struct ecore_dmae_params));
- params.flags = flags;
-
- OSAL_MUTEX_ACQUIRE(&p_hwfn->dmae_info.mutex);
+ OSAL_SPIN_LOCK(&p_hwfn->dmae_info.lock);
rc = ecore_dmae_execute_command(p_hwfn, p_ptt, source_addr,
grc_addr_in_dw,
ECORE_DMAE_ADDRESS_HOST_VIRT,
ECORE_DMAE_ADDRESS_GRC,
- size_in_dwords, &params);
+ size_in_dwords, p_params);
- OSAL_MUTEX_RELEASE(&p_hwfn->dmae_info.mutex);
+ OSAL_SPIN_UNLOCK(&p_hwfn->dmae_info.lock);
return rc;
}
@@ -995,23 +1034,19 @@ enum _ecore_status_t ecore_dmae_grc2host(struct ecore_hwfn *p_hwfn,
u32 grc_addr,
dma_addr_t dest_addr,
u32 size_in_dwords,
- u32 flags)
+ struct ecore_dmae_params *p_params)
{
u32 grc_addr_in_dw = grc_addr / sizeof(u32);
- struct ecore_dmae_params params;
enum _ecore_status_t rc;
- OSAL_MEMSET(&params, 0, sizeof(struct ecore_dmae_params));
- params.flags = flags;
-
- OSAL_MUTEX_ACQUIRE(&(p_hwfn->dmae_info.mutex));
+ OSAL_SPIN_LOCK(&(p_hwfn->dmae_info.lock));
rc = ecore_dmae_execute_command(p_hwfn, p_ptt, grc_addr_in_dw,
dest_addr, ECORE_DMAE_ADDRESS_GRC,
ECORE_DMAE_ADDRESS_HOST_VIRT,
- size_in_dwords, &params);
+ size_in_dwords, p_params);
- OSAL_MUTEX_RELEASE(&(p_hwfn->dmae_info.mutex));
+ OSAL_SPIN_UNLOCK(&(p_hwfn->dmae_info.lock));
return rc;
}
@@ -1025,7 +1060,7 @@ enum _ecore_status_t ecore_dmae_host2host(struct ecore_hwfn *p_hwfn,
{
enum _ecore_status_t rc;
- OSAL_MUTEX_ACQUIRE(&p_hwfn->dmae_info.mutex);
+ OSAL_SPIN_LOCK(&p_hwfn->dmae_info.lock);
rc = ecore_dmae_execute_command(p_hwfn, p_ptt, source_addr,
dest_addr,
@@ -1034,7 +1069,7 @@ enum _ecore_status_t ecore_dmae_host2host(struct ecore_hwfn *p_hwfn,
size_in_dwords,
p_params);
- OSAL_MUTEX_RELEASE(&p_hwfn->dmae_info.mutex);
+ OSAL_SPIN_UNLOCK(&p_hwfn->dmae_info.lock);
return rc;
}
@@ -1052,3 +1087,105 @@ void ecore_hw_err_notify(struct ecore_hwfn *p_hwfn,
OSAL_HW_ERROR_OCCURRED(p_hwfn, err_type);
}
+
+enum _ecore_status_t ecore_dmae_sanity(struct ecore_hwfn *p_hwfn,
+ struct ecore_ptt *p_ptt,
+ const char *phase)
+{
+ u32 size = OSAL_PAGE_SIZE / 2, val;
+ enum _ecore_status_t rc = ECORE_SUCCESS;
+ dma_addr_t p_phys;
+ void *p_virt;
+ u32 *p_tmp;
+
+ p_virt = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev, &p_phys, 2 * size);
+ if (!p_virt) {
+ DP_NOTICE(p_hwfn, false,
+ "DMAE sanity [%s]: failed to allocate memory\n",
+ phase);
+ return ECORE_NOMEM;
+ }
+
+ /* Fill the bottom half of the allocated memory with a known pattern */
+ for (p_tmp = (u32 *)p_virt;
+ p_tmp < (u32 *)((u8 *)p_virt + size);
+ p_tmp++) {
+ /* Save the address itself as the value */
+ val = (u32)(osal_uintptr_t)p_tmp;
+ *p_tmp = val;
+ }
+
+ /* Zero the top half of the allocated memory */
+ OSAL_MEM_ZERO((u8 *)p_virt + size, size);
+
+ DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
+ "DMAE sanity [%s]: src_addr={phys 0x%llx, virt %p}, dst_addr={phys 0x%llx, virt %p}, size 0x%x\n",
+ phase, (unsigned long long)p_phys, p_virt,
+ (unsigned long long)(p_phys + size), (u8 *)p_virt + size,
+ size);
+
+ rc = ecore_dmae_host2host(p_hwfn, p_ptt, p_phys, p_phys + size,
+ size / 4 /* size_in_dwords */,
+ OSAL_NULL /* default parameters */);
+ if (rc != ECORE_SUCCESS) {
+ DP_NOTICE(p_hwfn, false,
+ "DMAE sanity [%s]: ecore_dmae_host2host() failed. rc = %d.\n",
+ phase, rc);
+ goto out;
+ }
+
+ /* Verify that the top half of the allocated memory has the pattern */
+ for (p_tmp = (u32 *)((u8 *)p_virt + size);
+ p_tmp < (u32 *)((u8 *)p_virt + (2 * size));
+ p_tmp++) {
+ /* The corresponding address in the bottom half */
+ val = (u32)(osal_uintptr_t)p_tmp - size;
+
+ if (*p_tmp != val) {
+ DP_NOTICE(p_hwfn, false,
+ "DMAE sanity [%s]: addr={phys 0x%llx, virt %p}, read_val 0x%08x, expected_val 0x%08x\n",
+ phase,
+ (unsigned long long)(p_phys + (u32)((u8 *)p_tmp - (u8 *)p_virt)),
+ p_tmp, *p_tmp, val);
+ rc = ECORE_UNKNOWN_ERROR;
+ goto out;
+ }
+ }
+
+out:
+ OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev, p_virt, p_phys, 2 * size);
+ return rc;
+}
+
+void ecore_ppfid_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+ u8 abs_ppfid, u32 hw_addr, u32 val)
+{
+ u8 pfid = ECORE_PFID_BY_PPFID(p_hwfn, abs_ppfid);
+
+ ecore_fid_pretend(p_hwfn, p_ptt,
+ pfid << PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+ ecore_wr(p_hwfn, p_ptt, hw_addr, val);
+ ecore_fid_pretend(p_hwfn, p_ptt,
+ p_hwfn->rel_pf_id <<
+ PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+}
+
+u32 ecore_ppfid_rd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+ u8 abs_ppfid, u32 hw_addr)
+{
+ u8 pfid = ECORE_PFID_BY_PPFID(p_hwfn, abs_ppfid);
+ u32 val;
+
+ ecore_fid_pretend(p_hwfn, p_ptt,
+ pfid << PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+ val = ecore_rd(p_hwfn, p_ptt, hw_addr);
+ ecore_fid_pretend(p_hwfn, p_ptt,
+ p_hwfn->rel_pf_id <<
+ PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+
+ return val;
+}
+
+#ifdef _NTDDK_
+#pragma warning(pop)
+#endif