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