1/* 2 * BSD LICENSE 3 * 4 * Copyright(c) 2017 Cavium, Inc.. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Cavium, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33/*$FreeBSD: stable/11/sys/dev/liquidio/base/lio_ctrl.c 325618 2017-11-09 19:52:56Z sbruno $*/ 34 35#include "lio_bsd.h" 36#include "lio_common.h" 37#include "lio_droq.h" 38#include "lio_iq.h" 39#include "lio_response_manager.h" 40#include "lio_device.h" 41#include "lio_ctrl.h" 42#include "lio_main.h" 43 44int 45lio_send_data_pkt(struct octeon_device *oct, struct lio_data_pkt *ndata) 46{ 47 int ring_doorbell = 1; 48 49 return (lio_send_command(oct, ndata->q_no, ring_doorbell, &ndata->cmd, 50 ndata->buf, ndata->datasize, ndata->reqtype)); 51} 52 53static void 54lio_ctrl_callback(struct octeon_device *oct, uint32_t status, void *sc_ptr) 55{ 56 struct lio_soft_command *sc = (struct lio_soft_command *)sc_ptr; 57 struct lio_ctrl_pkt *nctrl; 58 59 nctrl = (struct lio_ctrl_pkt *)sc->ctxptr; 60 61 /* 62 * Call the callback function if status is OK. 63 * Status is OK only if a response was expected and core returned 64 * success. 65 * If no response was expected, status is OK if the command was posted 66 * successfully. 67 */ 68 if (!status && nctrl->cb_fn) 69 nctrl->cb_fn(nctrl); 70 71 lio_free_soft_command(oct, sc); 72} 73 74static inline struct lio_soft_command * 75lio_alloc_ctrl_pkt_sc(struct octeon_device *oct, struct lio_ctrl_pkt *nctrl) 76{ 77 struct lio_soft_command *sc = NULL; 78 uint32_t datasize = 0, rdatasize, uddsize = 0; 79 uint8_t *data; 80 81 uddsize = (uint32_t)(nctrl->ncmd.s.more * 8); 82 83 datasize = OCTEON_CMD_SIZE + uddsize; 84 rdatasize = (nctrl->wait_time) ? 16 : 0; 85 86 sc = lio_alloc_soft_command(oct, datasize, rdatasize, 87 sizeof(struct lio_ctrl_pkt)); 88 89 if (sc == NULL) 90 return (NULL); 91 92 memcpy(sc->ctxptr, nctrl, sizeof(struct lio_ctrl_pkt)); 93 94 data = (uint8_t *)sc->virtdptr; 95 96 memcpy(data, &nctrl->ncmd, OCTEON_CMD_SIZE); 97 98 lio_swap_8B_data((uint64_t *)data, (OCTEON_CMD_SIZE >> 3)); 99 100 if (uddsize) { 101 /* Endian-Swap for UDD should have been done by caller. */ 102 memcpy(data + OCTEON_CMD_SIZE, nctrl->udd, uddsize); 103 } 104 sc->iq_no = (uint32_t)nctrl->iq_no; 105 106 lio_prepare_soft_command(oct, sc, LIO_OPCODE_NIC, LIO_OPCODE_NIC_CMD, 0, 107 0, 0); 108 109 sc->callback = lio_ctrl_callback; 110 sc->callback_arg = sc; 111 sc->wait_time = nctrl->wait_time; 112 113 return (sc); 114} 115 116int 117lio_send_ctrl_pkt(struct octeon_device *oct, struct lio_ctrl_pkt *nctrl) 118{ 119 struct lio_soft_command *sc = NULL; 120 int retval; 121 122 mtx_lock(&oct->cmd_resp_wqlock); 123 /* 124 * Allow only rx ctrl command to stop traffic on the chip 125 * during offline operations 126 */ 127 if ((oct->cmd_resp_state == LIO_DRV_OFFLINE) && 128 (nctrl->ncmd.s.cmd != LIO_CMD_RX_CTL)) { 129 mtx_unlock(&oct->cmd_resp_wqlock); 130 lio_dev_err(oct, "%s cmd:%d not processed since driver offline\n", 131 __func__, nctrl->ncmd.s.cmd); 132 return (-1); 133 } 134 135 sc = lio_alloc_ctrl_pkt_sc(oct, nctrl); 136 if (sc == NULL) { 137 lio_dev_err(oct, "%s soft command alloc failed\n", __func__); 138 mtx_unlock(&oct->cmd_resp_wqlock); 139 return (-1); 140 } 141 142 retval = lio_send_soft_command(oct, sc); 143 if (retval == LIO_IQ_SEND_FAILED) { 144 lio_free_soft_command(oct, sc); 145 lio_dev_err(oct, "%s pf_num:%d soft command:%d send failed status: %x\n", 146 __func__, oct->pf_num, nctrl->ncmd.s.cmd, retval); 147 mtx_unlock(&oct->cmd_resp_wqlock); 148 return (-1); 149 } 150 151 mtx_unlock(&oct->cmd_resp_wqlock); 152 return (retval); 153} 154