1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "ngbe_type.h" 7 8 #include "ngbe_mbx.h" 9 10 /** 11 * ngbe_read_mbx - Reads a message from the mailbox 12 * @hw: pointer to the HW structure 13 * @msg: The message buffer 14 * @size: Length of buffer 15 * @mbx_id: id of mailbox to read 16 * 17 * returns 0 if it successfully read message from buffer 18 **/ 19 s32 ngbe_read_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 20 { 21 struct ngbe_mbx_info *mbx = &hw->mbx; 22 s32 ret_val = NGBE_ERR_MBX; 23 24 /* limit read to size of mailbox */ 25 if (size > mbx->size) 26 size = mbx->size; 27 28 if (mbx->read) 29 ret_val = mbx->read(hw, msg, size, mbx_id); 30 31 return ret_val; 32 } 33 34 /** 35 * ngbe_write_mbx - Write a message to the mailbox 36 * @hw: pointer to the HW structure 37 * @msg: The message buffer 38 * @size: Length of buffer 39 * @mbx_id: id of mailbox to write 40 * 41 * returns 0 if it successfully copied message into the buffer 42 **/ 43 s32 ngbe_write_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 44 { 45 struct ngbe_mbx_info *mbx = &hw->mbx; 46 s32 ret_val = 0; 47 48 if (size > mbx->size) { 49 ret_val = NGBE_ERR_MBX; 50 DEBUGOUT("Invalid mailbox message size %d", size); 51 } else if (mbx->write) { 52 ret_val = mbx->write(hw, msg, size, mbx_id); 53 } 54 55 return ret_val; 56 } 57 58 /** 59 * ngbe_check_for_msg - checks to see if someone sent us mail 60 * @hw: pointer to the HW structure 61 * @mbx_id: id of mailbox to check 62 * 63 * returns 0 if the Status bit was found or else ERR_MBX 64 **/ 65 s32 ngbe_check_for_msg(struct ngbe_hw *hw, u16 mbx_id) 66 { 67 struct ngbe_mbx_info *mbx = &hw->mbx; 68 s32 ret_val = NGBE_ERR_MBX; 69 70 if (mbx->check_for_msg) 71 ret_val = mbx->check_for_msg(hw, mbx_id); 72 73 return ret_val; 74 } 75 76 /** 77 * ngbe_check_for_ack - checks to see if someone sent us ACK 78 * @hw: pointer to the HW structure 79 * @mbx_id: id of mailbox to check 80 * 81 * returns 0 if the Status bit was found or else ERR_MBX 82 **/ 83 s32 ngbe_check_for_ack(struct ngbe_hw *hw, u16 mbx_id) 84 { 85 struct ngbe_mbx_info *mbx = &hw->mbx; 86 s32 ret_val = NGBE_ERR_MBX; 87 88 if (mbx->check_for_ack) 89 ret_val = mbx->check_for_ack(hw, mbx_id); 90 91 return ret_val; 92 } 93 94 /** 95 * ngbe_check_for_rst - checks to see if other side has reset 96 * @hw: pointer to the HW structure 97 * @mbx_id: id of mailbox to check 98 * 99 * returns 0 if the Status bit was found or else ERR_MBX 100 **/ 101 s32 ngbe_check_for_rst(struct ngbe_hw *hw, u16 mbx_id) 102 { 103 struct ngbe_mbx_info *mbx = &hw->mbx; 104 s32 ret_val = NGBE_ERR_MBX; 105 106 if (mbx->check_for_rst) 107 ret_val = mbx->check_for_rst(hw, mbx_id); 108 109 return ret_val; 110 } 111 112 STATIC s32 ngbe_check_for_bit_pf(struct ngbe_hw *hw, u32 mask) 113 { 114 u32 mbvficr = rd32(hw, NGBE_MBVFICR); 115 s32 ret_val = NGBE_ERR_MBX; 116 117 if (mbvficr & mask) { 118 ret_val = 0; 119 wr32(hw, NGBE_MBVFICR, mask); 120 } 121 122 return ret_val; 123 } 124 125 /** 126 * ngbe_check_for_msg_pf - checks to see if the VF has sent mail 127 * @hw: pointer to the HW structure 128 * @vf_number: the VF index 129 * 130 * returns 0 if the VF has set the Status bit or else ERR_MBX 131 **/ 132 s32 ngbe_check_for_msg_pf(struct ngbe_hw *hw, u16 vf_number) 133 { 134 s32 ret_val = NGBE_ERR_MBX; 135 u32 vf_bit = vf_number; 136 137 if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFREQ_VF1 << vf_bit)) { 138 ret_val = 0; 139 hw->mbx.stats.reqs++; 140 } 141 142 return ret_val; 143 } 144 145 /** 146 * ngbe_check_for_ack_pf - checks to see if the VF has ACKed 147 * @hw: pointer to the HW structure 148 * @vf_number: the VF index 149 * 150 * returns 0 if the VF has set the Status bit or else ERR_MBX 151 **/ 152 s32 ngbe_check_for_ack_pf(struct ngbe_hw *hw, u16 vf_number) 153 { 154 s32 ret_val = NGBE_ERR_MBX; 155 u32 vf_bit = vf_number; 156 157 if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFACK_VF1 << vf_bit)) { 158 ret_val = 0; 159 hw->mbx.stats.acks++; 160 } 161 162 return ret_val; 163 } 164 165 /** 166 * ngbe_check_for_rst_pf - checks to see if the VF has reset 167 * @hw: pointer to the HW structure 168 * @vf_number: the VF index 169 * 170 * returns 0 if the VF has set the Status bit or else ERR_MBX 171 **/ 172 s32 ngbe_check_for_rst_pf(struct ngbe_hw *hw, u16 vf_number) 173 { 174 u32 vflre = 0; 175 s32 ret_val = NGBE_ERR_MBX; 176 177 vflre = rd32(hw, NGBE_FLRVFE); 178 if (vflre & (1 << vf_number)) { 179 ret_val = 0; 180 wr32(hw, NGBE_FLRVFEC, (1 << vf_number)); 181 hw->mbx.stats.rsts++; 182 } 183 184 return ret_val; 185 } 186 187 /** 188 * ngbe_obtain_mbx_lock_pf - obtain mailbox lock 189 * @hw: pointer to the HW structure 190 * @vf_number: the VF index 191 * 192 * return 0 if we obtained the mailbox lock 193 **/ 194 STATIC s32 ngbe_obtain_mbx_lock_pf(struct ngbe_hw *hw, u16 vf_number) 195 { 196 s32 ret_val = NGBE_ERR_MBX; 197 u32 p2v_mailbox; 198 199 /* Take ownership of the buffer */ 200 wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_PFU); 201 202 /* reserve mailbox for vf use */ 203 p2v_mailbox = rd32(hw, NGBE_MBCTL(vf_number)); 204 if (p2v_mailbox & NGBE_MBCTL_PFU) 205 ret_val = 0; 206 else 207 DEBUGOUT("Failed to obtain mailbox lock for VF%d", vf_number); 208 209 210 return ret_val; 211 } 212 213 /** 214 * ngbe_write_mbx_pf - Places a message in the mailbox 215 * @hw: pointer to the HW structure 216 * @msg: The message buffer 217 * @size: Length of buffer 218 * @vf_number: the VF index 219 * 220 * returns 0 if it successfully copied message into the buffer 221 **/ 222 s32 ngbe_write_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number) 223 { 224 s32 ret_val; 225 u16 i; 226 227 /* lock the mailbox to prevent pf/vf race condition */ 228 ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number); 229 if (ret_val) 230 goto out_no_write; 231 232 /* flush msg and acks as we are overwriting the message buffer */ 233 ngbe_check_for_msg_pf(hw, vf_number); 234 ngbe_check_for_ack_pf(hw, vf_number); 235 236 /* copy the caller specified message to the mailbox memory buffer */ 237 for (i = 0; i < size; i++) 238 wr32a(hw, NGBE_MBMEM(vf_number), i, msg[i]); 239 240 /* Interrupt VF to tell it a message has been sent and release buffer*/ 241 wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_STS); 242 243 /* update stats */ 244 hw->mbx.stats.msgs_tx++; 245 246 out_no_write: 247 return ret_val; 248 } 249 250 /** 251 * ngbe_read_mbx_pf - Read a message from the mailbox 252 * @hw: pointer to the HW structure 253 * @msg: The message buffer 254 * @size: Length of buffer 255 * @vf_number: the VF index 256 * 257 * This function copies a message from the mailbox buffer to the caller's 258 * memory buffer. The presumption is that the caller knows that there was 259 * a message due to a VF request so no polling for message is needed. 260 **/ 261 s32 ngbe_read_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number) 262 { 263 s32 ret_val; 264 u16 i; 265 266 /* lock the mailbox to prevent pf/vf race condition */ 267 ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number); 268 if (ret_val) 269 goto out_no_read; 270 271 /* copy the message to the mailbox memory buffer */ 272 for (i = 0; i < size; i++) 273 msg[i] = rd32a(hw, NGBE_MBMEM(vf_number), i); 274 275 /* Acknowledge the message and release buffer */ 276 wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_ACK); 277 278 /* update stats */ 279 hw->mbx.stats.msgs_rx++; 280 281 out_no_read: 282 return ret_val; 283 } 284 285 /** 286 * ngbe_init_mbx_params_pf - set initial values for pf mailbox 287 * @hw: pointer to the HW structure 288 * 289 * Initializes the hw->mbx struct to correct values for pf mailbox 290 */ 291 void ngbe_init_mbx_params_pf(struct ngbe_hw *hw) 292 { 293 struct ngbe_mbx_info *mbx = &hw->mbx; 294 295 mbx->timeout = 0; 296 mbx->usec_delay = 0; 297 298 mbx->size = NGBE_P2VMBX_SIZE; 299 300 mbx->stats.msgs_tx = 0; 301 mbx->stats.msgs_rx = 0; 302 mbx->stats.reqs = 0; 303 mbx->stats.acks = 0; 304 mbx->stats.rsts = 0; 305 } 306