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 34 #include <rte_ethdev.h> 35 #include <rte_cycles.h> 36 37 #include "lio_logs.h" 38 #include "lio_struct.h" 39 #include "lio_mbox.h" 40 41 /** 42 * lio_mbox_read: 43 * @mbox: Pointer mailbox 44 * 45 * Reads the 8-bytes of data from the mbox register 46 * Writes back the acknowledgment indicating completion of read 47 */ 48 int 49 lio_mbox_read(struct lio_mbox *mbox) 50 { 51 union lio_mbox_message msg; 52 int ret = 0; 53 54 msg.mbox_msg64 = rte_read64(mbox->mbox_read_reg); 55 56 if ((msg.mbox_msg64 == LIO_PFVFACK) || (msg.mbox_msg64 == LIO_PFVFSIG)) 57 return 0; 58 59 if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) { 60 mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = 61 msg.mbox_msg64; 62 mbox->mbox_req.recv_len++; 63 } else { 64 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) { 65 mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] = 66 msg.mbox_msg64; 67 mbox->mbox_resp.recv_len++; 68 } else { 69 if ((mbox->state & LIO_MBOX_STATE_IDLE) && 70 (msg.s.type == LIO_MBOX_REQUEST)) { 71 mbox->state &= ~LIO_MBOX_STATE_IDLE; 72 mbox->state |= LIO_MBOX_STATE_REQ_RECEIVING; 73 mbox->mbox_req.msg.mbox_msg64 = msg.mbox_msg64; 74 mbox->mbox_req.q_no = mbox->q_no; 75 mbox->mbox_req.recv_len = 1; 76 } else { 77 if ((mbox->state & 78 LIO_MBOX_STATE_RES_PENDING) && 79 (msg.s.type == LIO_MBOX_RESPONSE)) { 80 mbox->state &= 81 ~LIO_MBOX_STATE_RES_PENDING; 82 mbox->state |= 83 LIO_MBOX_STATE_RES_RECEIVING; 84 mbox->mbox_resp.msg.mbox_msg64 = 85 msg.mbox_msg64; 86 mbox->mbox_resp.q_no = mbox->q_no; 87 mbox->mbox_resp.recv_len = 1; 88 } else { 89 rte_write64(LIO_PFVFERR, 90 mbox->mbox_read_reg); 91 mbox->state |= LIO_MBOX_STATE_ERROR; 92 return -1; 93 } 94 } 95 } 96 } 97 98 if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) { 99 if (mbox->mbox_req.recv_len < msg.s.len) { 100 ret = 0; 101 } else { 102 mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVING; 103 mbox->state |= LIO_MBOX_STATE_REQ_RECEIVED; 104 ret = 1; 105 } 106 } else { 107 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) { 108 if (mbox->mbox_resp.recv_len < msg.s.len) { 109 ret = 0; 110 } else { 111 mbox->state &= ~LIO_MBOX_STATE_RES_RECEIVING; 112 mbox->state |= LIO_MBOX_STATE_RES_RECEIVED; 113 ret = 1; 114 } 115 } else { 116 RTE_ASSERT(0); 117 } 118 } 119 120 rte_write64(LIO_PFVFACK, mbox->mbox_read_reg); 121 122 return ret; 123 } 124 125 /** 126 * lio_mbox_write: 127 * @lio_dev: Pointer lio device 128 * @mbox_cmd: Cmd to send to mailbox. 129 * 130 * Populates the queue specific mbox structure 131 * with cmd information. 132 * Write the cmd to mbox register 133 */ 134 int 135 lio_mbox_write(struct lio_device *lio_dev, 136 struct lio_mbox_cmd *mbox_cmd) 137 { 138 struct lio_mbox *mbox = lio_dev->mbox[mbox_cmd->q_no]; 139 uint32_t count, i, ret = LIO_MBOX_STATUS_SUCCESS; 140 141 if ((mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) && 142 !(mbox->state & LIO_MBOX_STATE_REQ_RECEIVED)) 143 return LIO_MBOX_STATUS_FAILED; 144 145 if ((mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) && 146 !(mbox->state & LIO_MBOX_STATE_IDLE)) 147 return LIO_MBOX_STATUS_BUSY; 148 149 if (mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) { 150 rte_memcpy(&mbox->mbox_resp, mbox_cmd, 151 sizeof(struct lio_mbox_cmd)); 152 mbox->state = LIO_MBOX_STATE_RES_PENDING; 153 } 154 155 count = 0; 156 157 while (rte_read64(mbox->mbox_write_reg) != LIO_PFVFSIG) { 158 rte_delay_ms(1); 159 if (count++ == 1000) { 160 ret = LIO_MBOX_STATUS_FAILED; 161 break; 162 } 163 } 164 165 if (ret == LIO_MBOX_STATUS_SUCCESS) { 166 rte_write64(mbox_cmd->msg.mbox_msg64, mbox->mbox_write_reg); 167 for (i = 0; i < (uint32_t)(mbox_cmd->msg.s.len - 1); i++) { 168 count = 0; 169 while (rte_read64(mbox->mbox_write_reg) != 170 LIO_PFVFACK) { 171 rte_delay_ms(1); 172 if (count++ == 1000) { 173 ret = LIO_MBOX_STATUS_FAILED; 174 break; 175 } 176 } 177 rte_write64(mbox_cmd->data[i], mbox->mbox_write_reg); 178 } 179 } 180 181 if (mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) { 182 mbox->state = LIO_MBOX_STATE_IDLE; 183 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); 184 } else { 185 if ((!mbox_cmd->msg.s.resp_needed) || 186 (ret == LIO_MBOX_STATUS_FAILED)) { 187 mbox->state &= ~LIO_MBOX_STATE_RES_PENDING; 188 if (!(mbox->state & (LIO_MBOX_STATE_REQ_RECEIVING | 189 LIO_MBOX_STATE_REQ_RECEIVED))) 190 mbox->state = LIO_MBOX_STATE_IDLE; 191 } 192 } 193 194 return ret; 195 } 196 197 /** 198 * lio_mbox_process_cmd: 199 * @mbox: Pointer mailbox 200 * @mbox_cmd: Pointer to command received 201 * 202 * Process the cmd received in mbox 203 */ 204 static int 205 lio_mbox_process_cmd(struct lio_mbox *mbox, 206 struct lio_mbox_cmd *mbox_cmd) 207 { 208 struct lio_device *lio_dev = mbox->lio_dev; 209 210 if (mbox_cmd->msg.s.cmd == LIO_CORES_CRASHED) 211 lio_dev_err(lio_dev, "Octeon core(s) crashed or got stuck!\n"); 212 213 return 0; 214 } 215 216 /** 217 * Process the received mbox message. 218 */ 219 int 220 lio_mbox_process_message(struct lio_mbox *mbox) 221 { 222 struct lio_mbox_cmd mbox_cmd; 223 224 if (mbox->state & LIO_MBOX_STATE_ERROR) { 225 if (mbox->state & (LIO_MBOX_STATE_RES_PENDING | 226 LIO_MBOX_STATE_RES_RECEIVING)) { 227 rte_memcpy(&mbox_cmd, &mbox->mbox_resp, 228 sizeof(struct lio_mbox_cmd)); 229 mbox->state = LIO_MBOX_STATE_IDLE; 230 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); 231 mbox_cmd.recv_status = 1; 232 if (mbox_cmd.fn) 233 mbox_cmd.fn(mbox->lio_dev, &mbox_cmd, 234 mbox_cmd.fn_arg); 235 236 return 0; 237 } 238 239 mbox->state = LIO_MBOX_STATE_IDLE; 240 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); 241 242 return 0; 243 } 244 245 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVED) { 246 rte_memcpy(&mbox_cmd, &mbox->mbox_resp, 247 sizeof(struct lio_mbox_cmd)); 248 mbox->state = LIO_MBOX_STATE_IDLE; 249 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); 250 mbox_cmd.recv_status = 0; 251 if (mbox_cmd.fn) 252 mbox_cmd.fn(mbox->lio_dev, &mbox_cmd, mbox_cmd.fn_arg); 253 254 return 0; 255 } 256 257 if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVED) { 258 rte_memcpy(&mbox_cmd, &mbox->mbox_req, 259 sizeof(struct lio_mbox_cmd)); 260 if (!mbox_cmd.msg.s.resp_needed) { 261 mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVED; 262 if (!(mbox->state & LIO_MBOX_STATE_RES_PENDING)) 263 mbox->state = LIO_MBOX_STATE_IDLE; 264 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); 265 } 266 267 lio_mbox_process_cmd(mbox, &mbox_cmd); 268 269 return 0; 270 } 271 272 RTE_ASSERT(0); 273 274 return 0; 275 } 276