/*******************************************************************************
*
* Copyright (c) 2015-2016 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenFabrics.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "i40iw_osdep.h"
#include "i40iw_status.h"
#include "i40iw_d.h"
#include "i40iw_user.h"
#include "i40iw_register.h"
static u32 nop_signature = 0x55550000;
/**
* i40iw_nop_1 - insert a nop wqe and move head. no post work
* @qp: hw qp ptr
*/
static enum i40iw_status_code i40iw_nop_1(struct i40iw_qp_uk *qp)
{
u64 header, *wqe;
u64 *wqe_0 = NULL;
u32 wqe_idx, peek_head;
bool signaled = false;
if (!qp->sq_ring.head)
return I40IW_ERR_PARAM;
wqe_idx = I40IW_RING_GETCURRENT_HEAD(qp->sq_ring);
wqe = qp->sq_base[wqe_idx].elem;
qp->sq_wrtrk_array[wqe_idx].wqe_size = I40IW_QP_WQE_MIN_SIZE;
peek_head = (qp->sq_ring.head + 1) % qp->sq_ring.size;
wqe_0 = qp->sq_base[peek_head].elem;
if (peek_head)
wqe_0[3] = LS_64(!qp->swqe_polarity, I40IWQPSQ_VALID);
else
wqe_0[3] = LS_64(qp->swqe_polarity, I40IWQPSQ_VALID);
set_64bit_val(wqe, 0, 0);
set_64bit_val(wqe, 8, 0);
set_64bit_val(wqe, 16, 0);
header = LS_64(I40IWQP_OP_NOP, I40IWQPSQ_OPCODE) |
LS_64(signaled, I40IWQPSQ_SIGCOMPL) |
LS_64(qp->swqe_polarity, I40IWQPSQ_VALID) | nop_signature++;
wmb(); /* Memory barrier to ensure data is written before valid bit is set */
set_64bit_val(wqe, 24, header);
return 0;
}
/**
* i40iw_qp_post_wr - post wr to hrdware
* @qp: hw qp ptr
*/
void i40iw_qp_post_wr(struct i40iw_qp_uk *qp)
{
u64 temp;
u32 hw_sq_tail;
u32 sw_sq_head;
mb(); /* valid bit is written and loads completed before reading shadow */
/* read the doorbell shadow area */
get_64bit_val(qp->shadow_area, 0, &temp);
hw_sq_tail = (u32)RS_64(temp, I40IW_QP_DBSA_HW_SQ_TAIL);
sw_sq_head = I40IW_RING_GETCURRENT_HEAD(qp->sq_ring);
if (sw_sq_head != hw_sq_tail) {
if (sw_sq_head > qp->initial_ring.head) {
if ((hw_sq_tail >= qp->initial_ring.head) &&
(hw_sq_tail < sw_sq_head)) {
writel(qp->qp_id, qp->wqe_alloc_reg);
}
} else if (sw_sq_head != qp->initial_ring.head) {