1325618Ssbruno/* 2325618Ssbruno * BSD LICENSE 3325618Ssbruno * 4325618Ssbruno * Copyright(c) 2017 Cavium, Inc.. All rights reserved. 5325618Ssbruno * All rights reserved. 6325618Ssbruno * 7325618Ssbruno * Redistribution and use in source and binary forms, with or without 8325618Ssbruno * modification, are permitted provided that the following conditions 9325618Ssbruno * are met: 10325618Ssbruno * 11325618Ssbruno * * Redistributions of source code must retain the above copyright 12325618Ssbruno * notice, this list of conditions and the following disclaimer. 13325618Ssbruno * * Redistributions in binary form must reproduce the above copyright 14325618Ssbruno * notice, this list of conditions and the following disclaimer in 15325618Ssbruno * the documentation and/or other materials provided with the 16325618Ssbruno * distribution. 17325618Ssbruno * * Neither the name of Cavium, Inc. nor the names of its 18325618Ssbruno * contributors may be used to endorse or promote products derived 19325618Ssbruno * from this software without specific prior written permission. 20325618Ssbruno * 21325618Ssbruno * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22325618Ssbruno * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23325618Ssbruno * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24325618Ssbruno * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25325618Ssbruno * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26325618Ssbruno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27325618Ssbruno * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28325618Ssbruno * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29325618Ssbruno * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30325618Ssbruno * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31325618Ssbruno * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32325618Ssbruno */ 33325618Ssbruno/*$FreeBSD: stable/11/sys/dev/liquidio/base/lio_ctrl.c 325618 2017-11-09 19:52:56Z sbruno $*/ 34325618Ssbruno 35325618Ssbruno#include "lio_bsd.h" 36325618Ssbruno#include "lio_common.h" 37325618Ssbruno#include "lio_droq.h" 38325618Ssbruno#include "lio_iq.h" 39325618Ssbruno#include "lio_response_manager.h" 40325618Ssbruno#include "lio_device.h" 41325618Ssbruno#include "lio_ctrl.h" 42325618Ssbruno#include "lio_main.h" 43325618Ssbruno 44325618Ssbrunoint 45325618Ssbrunolio_send_data_pkt(struct octeon_device *oct, struct lio_data_pkt *ndata) 46325618Ssbruno{ 47325618Ssbruno int ring_doorbell = 1; 48325618Ssbruno 49325618Ssbruno return (lio_send_command(oct, ndata->q_no, ring_doorbell, &ndata->cmd, 50325618Ssbruno ndata->buf, ndata->datasize, ndata->reqtype)); 51325618Ssbruno} 52325618Ssbruno 53325618Ssbrunostatic void 54325618Ssbrunolio_ctrl_callback(struct octeon_device *oct, uint32_t status, void *sc_ptr) 55325618Ssbruno{ 56325618Ssbruno struct lio_soft_command *sc = (struct lio_soft_command *)sc_ptr; 57325618Ssbruno struct lio_ctrl_pkt *nctrl; 58325618Ssbruno 59325618Ssbruno nctrl = (struct lio_ctrl_pkt *)sc->ctxptr; 60325618Ssbruno 61325618Ssbruno /* 62325618Ssbruno * Call the callback function if status is OK. 63325618Ssbruno * Status is OK only if a response was expected and core returned 64325618Ssbruno * success. 65325618Ssbruno * If no response was expected, status is OK if the command was posted 66325618Ssbruno * successfully. 67325618Ssbruno */ 68325618Ssbruno if (!status && nctrl->cb_fn) 69325618Ssbruno nctrl->cb_fn(nctrl); 70325618Ssbruno 71325618Ssbruno lio_free_soft_command(oct, sc); 72325618Ssbruno} 73325618Ssbruno 74325618Ssbrunostatic inline struct lio_soft_command * 75325618Ssbrunolio_alloc_ctrl_pkt_sc(struct octeon_device *oct, struct lio_ctrl_pkt *nctrl) 76325618Ssbruno{ 77325618Ssbruno struct lio_soft_command *sc = NULL; 78325618Ssbruno uint32_t datasize = 0, rdatasize, uddsize = 0; 79325618Ssbruno uint8_t *data; 80325618Ssbruno 81325618Ssbruno uddsize = (uint32_t)(nctrl->ncmd.s.more * 8); 82325618Ssbruno 83325618Ssbruno datasize = OCTEON_CMD_SIZE + uddsize; 84325618Ssbruno rdatasize = (nctrl->wait_time) ? 16 : 0; 85325618Ssbruno 86325618Ssbruno sc = lio_alloc_soft_command(oct, datasize, rdatasize, 87325618Ssbruno sizeof(struct lio_ctrl_pkt)); 88325618Ssbruno 89325618Ssbruno if (sc == NULL) 90325618Ssbruno return (NULL); 91325618Ssbruno 92325618Ssbruno memcpy(sc->ctxptr, nctrl, sizeof(struct lio_ctrl_pkt)); 93325618Ssbruno 94325618Ssbruno data = (uint8_t *)sc->virtdptr; 95325618Ssbruno 96325618Ssbruno memcpy(data, &nctrl->ncmd, OCTEON_CMD_SIZE); 97325618Ssbruno 98325618Ssbruno lio_swap_8B_data((uint64_t *)data, (OCTEON_CMD_SIZE >> 3)); 99325618Ssbruno 100325618Ssbruno if (uddsize) { 101325618Ssbruno /* Endian-Swap for UDD should have been done by caller. */ 102325618Ssbruno memcpy(data + OCTEON_CMD_SIZE, nctrl->udd, uddsize); 103325618Ssbruno } 104325618Ssbruno sc->iq_no = (uint32_t)nctrl->iq_no; 105325618Ssbruno 106325618Ssbruno lio_prepare_soft_command(oct, sc, LIO_OPCODE_NIC, LIO_OPCODE_NIC_CMD, 0, 107325618Ssbruno 0, 0); 108325618Ssbruno 109325618Ssbruno sc->callback = lio_ctrl_callback; 110325618Ssbruno sc->callback_arg = sc; 111325618Ssbruno sc->wait_time = nctrl->wait_time; 112325618Ssbruno 113325618Ssbruno return (sc); 114325618Ssbruno} 115325618Ssbruno 116325618Ssbrunoint 117325618Ssbrunolio_send_ctrl_pkt(struct octeon_device *oct, struct lio_ctrl_pkt *nctrl) 118325618Ssbruno{ 119325618Ssbruno struct lio_soft_command *sc = NULL; 120325618Ssbruno int retval; 121325618Ssbruno 122325618Ssbruno mtx_lock(&oct->cmd_resp_wqlock); 123325618Ssbruno /* 124325618Ssbruno * Allow only rx ctrl command to stop traffic on the chip 125325618Ssbruno * during offline operations 126325618Ssbruno */ 127325618Ssbruno if ((oct->cmd_resp_state == LIO_DRV_OFFLINE) && 128325618Ssbruno (nctrl->ncmd.s.cmd != LIO_CMD_RX_CTL)) { 129325618Ssbruno mtx_unlock(&oct->cmd_resp_wqlock); 130325618Ssbruno lio_dev_err(oct, "%s cmd:%d not processed since driver offline\n", 131325618Ssbruno __func__, nctrl->ncmd.s.cmd); 132325618Ssbruno return (-1); 133325618Ssbruno } 134325618Ssbruno 135325618Ssbruno sc = lio_alloc_ctrl_pkt_sc(oct, nctrl); 136325618Ssbruno if (sc == NULL) { 137325618Ssbruno lio_dev_err(oct, "%s soft command alloc failed\n", __func__); 138325618Ssbruno mtx_unlock(&oct->cmd_resp_wqlock); 139325618Ssbruno return (-1); 140325618Ssbruno } 141325618Ssbruno 142325618Ssbruno retval = lio_send_soft_command(oct, sc); 143325618Ssbruno if (retval == LIO_IQ_SEND_FAILED) { 144325618Ssbruno lio_free_soft_command(oct, sc); 145325618Ssbruno lio_dev_err(oct, "%s pf_num:%d soft command:%d send failed status: %x\n", 146325618Ssbruno __func__, oct->pf_num, nctrl->ncmd.s.cmd, retval); 147325618Ssbruno mtx_unlock(&oct->cmd_resp_wqlock); 148325618Ssbruno return (-1); 149325618Ssbruno } 150325618Ssbruno 151325618Ssbruno mtx_unlock(&oct->cmd_resp_wqlock); 152325618Ssbruno return (retval); 153325618Ssbruno} 154